diff --git a/DEPS b/DEPS index 05a587675..ad676aea 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '4273a150f84d70a9acc340261fd5e7be1af310a5', + 'skia_revision': '2c4ceca62d27ebd3617d91b94a0231030927f864', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '93306f1d7b2c10824e1e8876e5b8a3ab37c42b96', + 'v8_revision': 'da7a3d8e0374cb531d9ce0a3215650eccdd9a8f0', # 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. @@ -141,15 +141,15 @@ # 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': '6ce1be5a5a53eb0213075dd7591a7dd4a3708614', + 'angle_revision': '232bfeae6b292ac4286348a430c4cef78edcf7c0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '3e485a4f3ec814d79dff15ae4b66cd860197548e', + 'swiftshader_revision': 'aff2dd067015060a81d43ea768160045a42648c2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'f79e15b85174760e78a2fb0cd9f7b251eb19e6a2', + 'pdfium_revision': '8f387edb25845b6f2f6c06c608649bea99b4d8da', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -192,7 +192,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'bf564e0beff1b674b28666f8d1932a1687bf59c9', + 'catapult_revision': '4f8e8775daf0c57a4921cb3e39d5bf2d1608dc9e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -288,7 +288,7 @@ # Also, if you change these, make sure you update the svn_revisions in # //buildtools/deps_revisions.gni. 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917', - 'libcxx_revision': 'a50f5035629b7621e92acef968403f71b7d48553', + 'libcxx_revision': '9009625c821e9580bfece732c25bac1cc9c5a7c2', 'libcxxabi_revision': '0d529660e32d77d9111912d73f2c74fc5fa2a858', 'libunwind_revision': '69d9b84cca8354117b9fe9705a4430d789ee599b', } @@ -377,7 +377,7 @@ 'packages': [ { 'package': 'chromium/llvm-build-tools/dsymutil', - 'version': 'kykIT8m8YzNqqLP2xFGBTuo0ZtU9lom3BwiStWleyWkC', + 'version': 'OWlhXkmj18li3yhJk59Kmjbc5KdgLh56TwCd1qBdzlIC', } ], 'condition': 'checkout_mac', @@ -388,7 +388,7 @@ 'packages': [ { 'package': 'chromium/chrome/test/data/autofill/captured_sites', - 'version': 'jYvTM_KjFi4v_BTqCfkAxM1XJ4PkMDSi31FgEDf0z9sC', + 'version': 'zh9Tqke-MCYlzcrTXhogU3H1dgx2YAZs9GG_PeemPsQC', } ], 'condition': 'checkout_chromium_autofill_test_dependencies', @@ -801,7 +801,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd537949d45f364e638004d2b6404f764d8b61002', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c4bdf992238cc127f2b08fd8a77ff6fc71a3f44f', 'condition': 'checkout_linux', }, @@ -826,7 +826,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cf9613f166a2f3a7a6a52cff8ae5282aac45f3d9', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5637e87bda2811565c3e4e58bd2274aeb3a4757e', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -876,7 +876,7 @@ }, 'src/third_party/grpc/src': { - 'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + '0fc01a302f03c313d33492439366821cb66e0eb6', + 'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + 'b245ad4ae810ed6bc13378421edfd3986a8ffac3', }, 'src/third_party/freetype/src': @@ -1012,7 +1012,7 @@ }, 'src/third_party/leveldatabase/src': - Var('chromium_git') + '/external/leveldb.git' + '@' + 'fe4494804f5e3a2e25485d32aeb0eb7d2f25732e', + Var('chromium_git') + '/external/leveldb.git' + '@' + '9ce30510d482f5b2fa2965201453f0fc914f700c', 'src/third_party/libFuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'), @@ -1059,7 +1059,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '1533bd84f12e5b24b5c2e41d1729942c7aa218ad', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '3e2b4b3d4803f20814d6b6cb3109efbc95249b60', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1', @@ -1168,7 +1168,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '91c4a41613b36db6ff5d7398dff0dc42f9a264ca', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '32dc81e1a3cc86a792c99aae85b8f029149d0dc8', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1339,7 +1339,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '7dbc0eb2efa4708da5e3e44d2a15bfdee4ceb474', + Var('webrtc_git') + '/src.git' + '@' + 'f7f9845d9e5b24c73a70fceb278a20b43e9d9919', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1380,7 +1380,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2b8a8c7dba1186ebe62445f8d48cb796733e547a', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c2f5ff535204aee167e30fa9122290d9d505891f', 'condition': 'checkout_src_internal', }, @@ -1485,6 +1485,28 @@ 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/androidx_test_rules': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/androidx_test_rules', + 'version': 'version:1.1.0-cr0', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + + 'src/third_party/android_deps/libs/androidx_test_runner': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/androidx_test_runner', + 'version': 'version:1.1.0-cr0', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/android_deps/libs/com_android_support_animated_vector_drawable': { 'packages': [ { @@ -2123,6 +2145,17 @@ 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/net_sf_kxml_kxml2': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/net_sf_kxml_kxml2', + 'version': 'version:2.3.0-cr0', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/android_deps/libs/org_checkerframework_checker_compat_qual': { 'packages': [ { @@ -2528,7 +2561,7 @@ '--no_resume', '--extract', '--no_auth', - '--bucket', 'chromium-nodejs/8.9.1', + '--bucket', 'chromium-nodejs/10.15.3', '-s', 'src/third_party/node/linux/node-linux-x64.tar.gz.sha1', ], }, @@ -2541,7 +2574,7 @@ '--no_resume', '--extract', '--no_auth', - '--bucket', 'chromium-nodejs/8.9.1', + '--bucket', 'chromium-nodejs/10.15.3', '-s', 'src/third_party/node/mac/node-darwin-x64.tar.gz.sha1', ], }, @@ -2553,7 +2586,7 @@ 'src/third_party/depot_tools/download_from_google_storage.py', '--no_resume', '--no_auth', - '--bucket', 'chromium-nodejs/8.9.1', + '--bucket', 'chromium-nodejs/10.15.3', '-s', 'src/third_party/node/win/node.exe.sha1', ], },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index c950c89..37259187 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -2568,7 +2568,11 @@ file_to_pydeps_map = None for f in self._input_api.AffectedFiles(include_deletes=True): local_path = f.LocalPath() - if local_path == 'DEPS': + # Changes to DEPS can lead to .pydeps changes if any .py files are in + # subrepositories. We can't figure out which files change, so re-check + # all files. + # Changes to print_python_deps.py affect all .pydeps. + if local_path == 'DEPS' or local_path.endswith('print_python_deps.py'): return self._pydeps_files elif local_path.endswith('.pydeps'): if local_path in self._pydeps_files:
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 6b549a9..d341529 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -211,7 +211,7 @@ } # These assets are needed by both monochrome and stand alone WebView, but not by -# Chrome. +# Chrome or TrichromeWebView. android_assets("monochrome_webview_assets") { deps = [ "//third_party/icu:icu_assets", @@ -226,15 +226,6 @@ } } -java_group("assets") { - deps = [ - ":license_assets", - ":locale_pak_assets", - ":monochrome_webview_assets", - ":pak_file_assets", - ] -} - java_group("stub_assets") { deps = [ ":license_assets", @@ -433,6 +424,9 @@ renaming_sources = [ "$_secondary_abi_out_dir/v8_context_snapshot.bin" ] renaming_destinations = [ "v8_context_snapshot_$arch_suffix.bin" ] } else { + sources = [ + "$root_out_dir/natives_blob.bin", + ] renaming_sources = [ "$_secondary_abi_out_dir/snapshot_blob.bin" ] renaming_destinations = [ "snapshot_blob_$arch_suffix.bin" ] }
diff --git a/android_webview/browser/gfx/surfaces_instance.h b/android_webview/browser/gfx/surfaces_instance.h index 737cd6b..2e39f8e0 100644 --- a/android_webview/browser/gfx/surfaces_instance.h +++ b/android_webview/browser/gfx/surfaces_instance.h
@@ -72,8 +72,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override {} void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override {} - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override {} // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck(
diff --git a/android_webview/browser/scoped_add_feature_flags.cc b/android_webview/browser/scoped_add_feature_flags.cc index 03f80fd..cf2f7d0 100644 --- a/android_webview/browser/scoped_add_feature_flags.cc +++ b/android_webview/browser/scoped_add_feature_flags.cc
@@ -11,12 +11,16 @@ namespace android_webview { -ScopedAddFeatureFlags::ScopedAddFeatureFlags(base::CommandLine* cl) - : cl_(cl), - enabled_features_(base::FeatureList::SplitFeatureListString( - cl->GetSwitchValueASCII(switches::kEnableFeatures))), - disabled_features_(base::FeatureList::SplitFeatureListString( - cl->GetSwitchValueASCII(switches::kDisableFeatures))) {} +ScopedAddFeatureFlags::ScopedAddFeatureFlags(base::CommandLine* cl) : cl_(cl) { + std::string enabled_features = + cl->GetSwitchValueASCII(switches::kEnableFeatures); + std::string disabled_features = + cl->GetSwitchValueASCII(switches::kDisableFeatures); + for (auto& sp : base::FeatureList::SplitFeatureListString(enabled_features)) + enabled_features_.emplace_back(sp); + for (auto& sp : base::FeatureList::SplitFeatureListString(disabled_features)) + disabled_features_.emplace_back(sp); +} ScopedAddFeatureFlags::~ScopedAddFeatureFlags() { cl_->AppendSwitchASCII(switches::kEnableFeatures,
diff --git a/android_webview/browser/scoped_add_feature_flags.h b/android_webview/browser/scoped_add_feature_flags.h index 0b990ec4..0433ac4 100644 --- a/android_webview/browser/scoped_add_feature_flags.h +++ b/android_webview/browser/scoped_add_feature_flags.h
@@ -5,10 +5,10 @@ #ifndef ANDROID_WEBVIEW_BROWSER_SCOPED_ADD_FEATURE_FLAGS_H_ #define ANDROID_WEBVIEW_BROWSER_SCOPED_ADD_FEATURE_FLAGS_H_ +#include <string> #include <vector> #include "base/feature_list.h" -#include "base/strings/string_piece.h" namespace base { class CommandLine; @@ -29,8 +29,8 @@ void AddFeatureIfNotSet(const base::Feature& feature, bool enable); base::CommandLine* const cl_; - std::vector<base::StringPiece> enabled_features_; - std::vector<base::StringPiece> disabled_features_; + std::vector<std::string> enabled_features_; + std::vector<std::string> disabled_features_; DISALLOW_COPY_AND_ASSIGN(ScopedAddFeatureFlags); };
diff --git a/android_webview/browser/scoped_add_feature_flags_unittests.cc b/android_webview/browser/scoped_add_feature_flags_unittests.cc new file mode 100644 index 0000000..f73958d --- /dev/null +++ b/android_webview/browser/scoped_add_feature_flags_unittests.cc
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/browser/scoped_add_feature_flags.h" + +#include <string> + +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/feature_list.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::CommandLine; + +namespace android_webview { + +TEST(ScopedAddFeatureFlags, ConflictWithExistingFlags) { + CommandLine command_line(CommandLine::NO_PROGRAM); + command_line.AppendSwitchASCII(switches::kEnableFeatures, + "ExistingEnabledFoo,ExistingEnabledBar"); + command_line.AppendSwitchASCII(switches::kDisableFeatures, + "ExistingDisabledFoo,ExistingDisabledBar"); + + const base::Feature kExistingEnabledFoo{"ExistingEnabledFoo", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kExistingDisabledFoo{"ExistingDisabledFoo", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kEnabledBaz{"EnabledBaz", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kDisabledBaz{"DisabledBaz", + base::FEATURE_DISABLED_BY_DEFAULT}; + { + ScopedAddFeatureFlags scoped_add(&command_line); + scoped_add.EnableIfNotSet(kExistingEnabledFoo); + scoped_add.EnableIfNotSet(kExistingDisabledFoo); + scoped_add.EnableIfNotSet(kEnabledBaz); + scoped_add.DisableIfNotSet(kExistingEnabledFoo); + scoped_add.DisableIfNotSet(kExistingDisabledFoo); + scoped_add.DisableIfNotSet(kDisabledBaz); + } + + EXPECT_EQ(std::string("ExistingEnabledFoo,ExistingEnabledBar,EnabledBaz"), + command_line.GetSwitchValueASCII(switches::kEnableFeatures)); + EXPECT_EQ(std::string("ExistingDisabledFoo,ExistingDisabledBar,DisabledBaz"), + command_line.GetSwitchValueASCII(switches::kDisableFeatures)); +} + +} // namespace android_webview
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 de21c7f..3f7d81b 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
@@ -26,12 +26,12 @@ import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.JavascriptEventObserver; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.GestureListenerManager; import org.chromium.content_public.browser.GestureStateListener; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.UseZoomForDSFPolicy; import org.chromium.net.test.util.TestWebServer; @@ -211,7 +211,7 @@ private boolean checkScrollOnMainSync(final ScrollTestContainerView testContainerView, final int scrollXPix, final int scrollYPix) { - return ThreadUtils.runOnUiThreadBlockingNoException( + return TestThreadUtils.runOnUiThreadBlockingNoException( () -> scrollXPix == testContainerView.getScrollX() && scrollYPix == testContainerView.getScrollY()); } @@ -666,10 +666,9 @@ assertScrollOnMainSync(testContainerView, 0, 0); - final int maxScrollYPix = ThreadUtils.runOnUiThreadBlocking( - () - -> (testContainerView.getAwContents().computeVerticalScrollRange() - - testContainerView.getHeight())); + final int maxScrollYPix = TestThreadUtils.runOnUiThreadBlocking( + () -> (testContainerView.getAwContents().computeVerticalScrollRange() + - testContainerView.getHeight())); final CallbackHelper onScrollToCallbackHelper = testContainerView.getOnScrollToCallbackHelper(); @@ -768,8 +767,7 @@ + "</div>"); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () - -> GestureListenerManager + () -> GestureListenerManager .fromWebContents(testContainerView.getWebContents()) .addListener(testGestureStateListener)); final CallbackHelper onScrollUpdateGestureConsumedHelper = @@ -870,7 +868,7 @@ scrollToOnMainSync(testContainerView, 0, targetScrollYPix); final int scrolledYPix = - ThreadUtils.runOnUiThreadBlocking(() -> testContainerView.getScrollY()); + TestThreadUtils.runOnUiThreadBlocking(() -> testContainerView.getScrollY()); Assert.assertTrue(scrolledYPix > 0);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/ArchiveTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/ArchiveTest.java index 2f5d843..8cf29a10 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/ArchiveTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/ArchiveTest.java
@@ -16,11 +16,11 @@ import org.chromium.android_webview.AwContents; import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; import org.chromium.base.task.PostTask; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.io.File; import java.util.concurrent.Semaphore; @@ -183,10 +183,12 @@ final String path, boolean autoname, final Callback<String> callback) { PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mTestContainerView.getAwContents().saveWebArchive(path, false, callback)); - ThreadUtils.runOnUiThreadBlocking(() -> { - // Just wait for this task to having been posted on the UI thread. - // This ensures that if the implementation of saveWebArchive posts a task to the UI - // thread we will allow that task to run before finishing our test. - }); + TestThreadUtils.runOnUiThreadBlocking( + () -> { + // Just wait for this task to having been posted on the UI thread. + // This ensures that if the implementation of saveWebArchive posts a + // task to the UI + // thread we will allow that task to run before finishing our test. + }); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java index 6914c83..e8ae0f4 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java
@@ -27,13 +27,13 @@ import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.JSUtils; import org.chromium.base.Log; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.InMemorySharedPreferences; import org.chromium.content_public.browser.LoadUrlParams; 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.TestCallbackHelperContainer.OnPageFinishedHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.lang.annotation.Annotation; @@ -135,24 +135,24 @@ final Context appContext = InstrumentationRegistry.getInstrumentation() .getTargetContext() .getApplicationContext(); - ThreadUtils.runOnUiThreadBlockingNoException( + TestThreadUtils.runOnUiThreadBlockingNoException( () -> mBrowserContext = createAwBrowserContextOnUiThread(prefs, appContext)); } public void startBrowserProcess() throws Exception { // The Activity must be launched in order for proper webview statics to be setup. launchActivity(); - ThreadUtils.runOnUiThreadBlocking(() -> AwBrowserProcess.start()); + TestThreadUtils.runOnUiThreadBlocking(() -> AwBrowserProcess.start()); } public static void enableJavaScriptOnUiThread(final AwContents awContents) { - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> awContents.getSettings().setJavaScriptEnabled(true)); } public static void setNetworkAvailableOnUiThread( final AwContents awContents, final boolean networkUp) { - ThreadUtils.runOnUiThreadBlocking(() -> awContents.setNetworkAvailable(networkUp)); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.setNetworkAvailable(networkUp)); } /** @@ -192,7 +192,7 @@ public void loadUrlAsync( final AwContents awContents, final String url, final Map<String, String> extraHeaders) { - ThreadUtils.runOnUiThreadBlocking(() -> awContents.loadUrl(url, extraHeaders)); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.loadUrl(url, extraHeaders)); } /** @@ -221,7 +221,7 @@ awContents.postUrl(url, mPostData); } } - ThreadUtils.runOnUiThreadBlocking(new PostUrl(postData)); + TestThreadUtils.runOnUiThreadBlocking(new PostUrl(postData)); } /** @@ -240,7 +240,7 @@ CallbackHelper onPageFinishedHelper, final String data, final String mimeType, final boolean isBase64Encoded, final String charset) throws Exception { int currentCallCount = onPageFinishedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> awContents.loadUrl(LoadUrlParams.createLoadDataParams( data, mimeType, isBase64Encoded, charset))); onPageFinishedHelper.waitForCallback( @@ -252,7 +252,7 @@ */ public void loadDataAsync(final AwContents awContents, final String data, final String mimeType, final boolean isBase64Encoded) throws Exception { - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> awContents.loadData(data, mimeType, isBase64Encoded ? "base64" : null)); } @@ -279,7 +279,8 @@ public void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHelper) throws Exception { int currentCallCount = onPageFinishedHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(() -> awContents.getNavigationController().reload(true)); + TestThreadUtils.runOnUiThreadBlocking( + () -> awContents.getNavigationController().reload(true)); onPageFinishedHelper.waitForCallback( currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); } @@ -288,13 +289,13 @@ * Stops loading on the UI thread. */ public void stopLoading(final AwContents awContents) { - ThreadUtils.runOnUiThreadBlocking(() -> awContents.stopLoading()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.stopLoading()); } public void waitForVisualStateCallback(final AwContents awContents) throws Exception { final CallbackHelper ch = new CallbackHelper(); final int chCount = ch.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { final long requestId = 666; awContents.insertVisualStateCallback(requestId, new AwContents.VisualStateCallback() { @Override @@ -309,7 +310,7 @@ public void insertVisualStateCallbackOnUIThread(final AwContents awContents, final long requestId, final AwContents.VisualStateCallback callback) { - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> awContents.insertVisualStateCallback(requestId, callback)); } @@ -382,21 +383,22 @@ public AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClient client, final boolean supportsLegacyQuirks, final TestDependencyFactory testDependencyFactory) { - return ThreadUtils.runOnUiThreadBlockingNoException(() -> createAwTestContainerView( - client, supportsLegacyQuirks, testDependencyFactory)); + return TestThreadUtils.runOnUiThreadBlockingNoException( + () -> createAwTestContainerView( + client, supportsLegacyQuirks, testDependencyFactory)); } public void destroyAwContentsOnMainSync(final AwContents awContents) { if (awContents == null) return; - ThreadUtils.runOnUiThreadBlocking(() -> awContents.destroy()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.destroy()); } public String getTitleOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getTitle()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getTitle()); } public AwSettings getAwSettingsOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getSettings()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getSettings()); } /** @@ -456,7 +458,7 @@ * callable on the UI thread. */ public void pollUiThread(final Callable<Boolean> callable) throws Exception { - pollInstrumentationThread(() -> ThreadUtils.runOnUiThreadBlocking(callable)); + pollInstrumentationThread(() -> TestThreadUtils.runOnUiThreadBlocking(callable)); } /** @@ -465,39 +467,39 @@ */ public void clearCacheOnUiThread(final AwContents awContents, final boolean includeDiskFiles) throws Exception { - ThreadUtils.runOnUiThreadBlocking(() -> awContents.clearCache(includeDiskFiles)); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.clearCache(includeDiskFiles)); } /** * Returns pure page scale. */ public float getScaleOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getPageScaleFactor()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getPageScaleFactor()); } /** * Returns page scale multiplied by the screen density. */ public float getPixelScaleOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getScale()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getScale()); } /** * Returns whether a user can zoom the page in. */ public boolean canZoomInOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.canZoomIn()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.canZoomIn()); } /** * Returns whether a user can zoom the page out. */ public boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.canZoomOut()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.canZoomOut()); } public void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Exception { - ThreadUtils.runOnUiThreadBlocking(() -> awContents.killRenderProcess()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.killRenderProcess()); } /** @@ -508,7 +510,7 @@ String mainHtml, String popupHtml, String popupPath, String triggerScript) throws Exception { enableJavaScriptOnUiThread(parentAwContents); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { parentAwContents.getSettings().setSupportMultipleWindows(true); parentAwContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); }); @@ -526,7 +528,7 @@ TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper = parentAwContentsClient.getOnCreateWindowHelper(); int currentCallCount = onCreateWindowHelper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> parentAwContents.evaluateJavaScriptForTests(triggerScript, null)); onCreateWindowHelper.waitForCallback( currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); @@ -570,7 +572,7 @@ if (onCreateWindowHandler != null) onCreateWindowHandler.onCreateWindow(popupContents); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> parentAwContents.supplyContentsForPopup(popupContents)); OnPageFinishedHelper onPageFinishedHelper = popupContentsClient.getOnPageFinishedHelper();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutocompleteTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutocompleteTest.java index 9039fe9..5be4518 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutocompleteTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutocompleteTest.java
@@ -16,10 +16,10 @@ import org.junit.Test; import org.chromium.android_webview.AwContents; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MetricsUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.util.concurrent.Callable; @@ -54,27 +54,21 @@ } private void verifyUmaAutocompleteEnabled(final boolean enabled) throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - if (enabled) { - assertEquals(1, mAutocompleteEnabled.getDelta()); - assertEquals(0, mAutocompleteDisabled.getDelta()); - } else { - assertEquals(0, mAutocompleteEnabled.getDelta()); - assertEquals(1, mAutocompleteDisabled.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + if (enabled) { + assertEquals(1, mAutocompleteEnabled.getDelta()); + assertEquals(0, mAutocompleteDisabled.getDelta()); + } else { + assertEquals(0, mAutocompleteEnabled.getDelta()); + assertEquals(1, mAutocompleteDisabled.getDelta()); } }); } private void verifyUmaNotRecorded() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(0, mAutocompleteEnabled.getDelta()); - assertEquals(0, mAutocompleteDisabled.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(0, mAutocompleteEnabled.getDelta()); + assertEquals(0, mAutocompleteDisabled.getDelta()); }); } @@ -89,7 +83,7 @@ } private boolean dispatchKeyEvent(final KeyEvent event) throws Throwable { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { + return TestThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override public Boolean call() { return mTestContainerView.dispatchKeyEvent(event); @@ -121,12 +115,8 @@ } private void disableAwAutocomplete() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mAwContents.getSettings().setSaveFormData(false); - } - }); + TestThreadUtils.runOnUiThreadBlocking( + () -> mAwContents.getSettings().setSaveFormData(false)); } @Before
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index 429380f..34b21538 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -43,7 +43,6 @@ import org.chromium.android_webview.AwWebResourceResponse; import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory; import org.chromium.base.Log; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; @@ -54,6 +53,7 @@ import org.chromium.components.autofill.SubmissionSource; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.DOMUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.io.ByteArrayInputStream; @@ -528,22 +528,14 @@ } public int getSessionValue() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mSessionValue = getUMAEnumerateValue(mSessionDelta); - } - }); + TestThreadUtils.runOnUiThreadBlocking( + () -> { mSessionValue = getUMAEnumerateValue(mSessionDelta); }); return mSessionValue; } public int getSubmissionSourceValue() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mSourceValue = getUMAEnumerateValue(mSubmissionSourceDelta); - } - }); + TestThreadUtils.runOnUiThreadBlocking( + () -> { mSourceValue = getUMAEnumerateValue(mSubmissionSourceDelta); }); return mSourceValue; } @@ -620,109 +612,85 @@ } private void initDeltaSamples() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mSessionDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>(); - for (int i = 0; i < AwAutofillUMA.AUTOFILL_SESSION_HISTOGRAM_COUNT; i++) { - mSessionDelta.put( - new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION, i), - i); - } - mSubmissionSourceDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>(); - for (int i = 0; i < AwAutofillUMA.SUBMISSION_SOURCE_HISTOGRAM_COUNT; i++) { - mSubmissionSourceDelta.put( - new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE, i), - i); - } - mAutofillWebViewViewEnabled = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 1 /*true*/); - mAutofillWebViewViewDisabled = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 0 /*false*/); - mAutofillWebViewCreatedByActivityContext = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 1); - mAutofillWebViewCreatedByAppContext = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 0); - mUserChangedAutofilledField = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 1 /*true*/); - mUserChangedNonAutofilledField = new MetricsUtils.HistogramDelta( - AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 0 /*falsTe*/); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mSessionDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>(); + for (int i = 0; i < AwAutofillUMA.AUTOFILL_SESSION_HISTOGRAM_COUNT; i++) { + mSessionDelta.put( + new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_AUTOFILL_SESSION, i), + i); } + mSubmissionSourceDelta = new HashMap<MetricsUtils.HistogramDelta, Integer>(); + for (int i = 0; i < AwAutofillUMA.SUBMISSION_SOURCE_HISTOGRAM_COUNT; i++) { + mSubmissionSourceDelta.put( + new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_SUBMISSION_SOURCE, i), + i); + } + mAutofillWebViewViewEnabled = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 1 /*true*/); + mAutofillWebViewViewDisabled = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_ENABLED, 0 /*false*/); + mAutofillWebViewCreatedByActivityContext = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 1); + mAutofillWebViewCreatedByAppContext = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_WEBVIEW_CREATED_BY_ACTIVITY_CONTEXT, 0); + mUserChangedAutofilledField = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 1 /*true*/); + mUserChangedNonAutofilledField = new MetricsUtils.HistogramDelta( + AwAutofillUMA.UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, 0 /*falsTe*/); }); } public int getHistogramSampleCount(String name) throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mHistogramSimpleCount = - Integer.valueOf(RecordHistogram.getHistogramTotalCountForTesting(name)); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + mHistogramSimpleCount = + Integer.valueOf(RecordHistogram.getHistogramTotalCountForTesting(name)); }); return mHistogramSimpleCount; } public void verifyAutofillEnabled() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(1, mAutofillWebViewViewEnabled.getDelta()); - assertEquals(0, mAutofillWebViewViewDisabled.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(1, mAutofillWebViewViewEnabled.getDelta()); + assertEquals(0, mAutofillWebViewViewDisabled.getDelta()); }); } public void verifyAutofillDisabled() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(0, mAutofillWebViewViewEnabled.getDelta()); - assertEquals(1, mAutofillWebViewViewDisabled.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(0, mAutofillWebViewViewEnabled.getDelta()); + assertEquals(1, mAutofillWebViewViewDisabled.getDelta()); }); } public void verifyUserChangedAutofilledField() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(0, mUserChangedNonAutofilledField.getDelta()); - assertEquals(1, mUserChangedAutofilledField.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(0, mUserChangedNonAutofilledField.getDelta()); + assertEquals(1, mUserChangedAutofilledField.getDelta()); }); } public void verifyUserChangedNonAutofilledField() throws Throwable { // User changed the form, but not the autofilled field. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(1, mUserChangedNonAutofilledField.getDelta()); - assertEquals(0, mUserChangedAutofilledField.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(1, mUserChangedNonAutofilledField.getDelta()); + assertEquals(0, mUserChangedAutofilledField.getDelta()); }); } public void verifyUserDidntChangeForm() throws Throwable { // User didn't change the form at all. - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(0, mUserChangedNonAutofilledField.getDelta()); - assertEquals(0, mUserChangedAutofilledField.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(0, mUserChangedNonAutofilledField.getDelta()); + assertEquals(0, mUserChangedAutofilledField.getDelta()); }); } public void verifyWebViewCreatedByActivityContext() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - assertEquals(1, mAutofillWebViewCreatedByActivityContext.getDelta()); - assertEquals(0, mAutofillWebViewCreatedByAppContext.getDelta()); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + assertEquals(1, mAutofillWebViewCreatedByActivityContext.getDelta()); + assertEquals(0, mAutofillWebViewCreatedByAppContext.getDelta()); }); } @@ -1879,31 +1847,18 @@ } private void invokeOnProvideAutoFillVirtualStructure() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mTestValues.testViewStructure = new TestViewStructure(); - mAwContents.onProvideAutoFillVirtualStructure(mTestValues.testViewStructure, 1); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + mTestValues.testViewStructure = new TestViewStructure(); + mAwContents.onProvideAutoFillVirtualStructure(mTestValues.testViewStructure, 1); }); } private void invokeAutofill(SparseArray<AutofillValue> values) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mAwContents.autofill(values); - } - }); + TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.autofill(values)); } private void invokeOnInputUIShown() { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mTestAwAutofillManager.notifyInputUIChange(); - } - }); + TestThreadUtils.runOnUiThreadBlocking(() -> mTestAwAutofillManager.notifyInputUIChange()); } private int getCallbackCount() { @@ -1966,7 +1921,7 @@ } private boolean dispatchKeyEvent(final KeyEvent event) throws Throwable { - return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { + return TestThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override public Boolean call() { return mTestContainerView.dispatchKeyEvent(event);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java index 9c63efc..baf2b931 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java
@@ -22,13 +22,13 @@ import org.chromium.android_webview.test.util.JSUtils; import org.chromium.android_webview.test.util.JavascriptEventObserver; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.WebContents; 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.TouchCommon; import java.util.concurrent.TimeoutException; @@ -374,7 +374,7 @@ private boolean getKeepScreenOnOnInstrumentationThread(final View view) { try { - return ThreadUtils.runOnUiThreadBlocking(() -> getKeepScreenOnOnUiThread(view)); + return TestThreadUtils.runOnUiThreadBlocking(() -> getKeepScreenOnOnUiThread(view)); } catch (Exception e) { Assert.fail(e.getMessage()); return false; @@ -462,7 +462,7 @@ private WebContents getWebContentsOnUiThread() { try { - return ThreadUtils.runOnUiThreadBlocking(() -> mTestContainerView.getWebContents()); + return TestThreadUtils.runOnUiThreadBlocking(() -> mTestContainerView.getWebContents()); } catch (Exception e) { Assert.fail(e.getMessage()); return null;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java index 9c96355..50a25fc 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRenderProcessGoneTest.java
@@ -17,12 +17,12 @@ import org.chromium.android_webview.AwRenderProcess; import org.chromium.android_webview.AwRenderProcessGoneDetail; import org.chromium.android_webview.renderer_priority.RendererPriority; -import org.chromium.base.ThreadUtils; import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentUrlConstants; import java.util.concurrent.TimeUnit; @@ -83,7 +83,7 @@ GetRenderProcessGoneHelper helper = contentsClient.getGetRenderProcessGoneHelper(); final AwRenderProcess renderProcess = - ThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); // Ensure that the renderer has started. mActivityTestRule.loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), @@ -155,8 +155,8 @@ mActivityTestRule.createAwTestContainerViewOnMainSync(contentsClient); final AwContents awContents = testView.getAwContents(); - Assert.assertFalse( - ThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess().terminate())); + Assert.assertFalse(TestThreadUtils.runOnUiThreadBlocking( + () -> awContents.getRenderProcess().terminate())); } @Test @@ -171,14 +171,14 @@ final AwContents awContents = testView.getAwContents(); AwRenderProcess renderProcessBeforeStart = - ThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); // Ensure that the renderer has started. mActivityTestRule.loadUrlSync(awContents, contentsClient.getOnPageFinishedHelper(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); AwRenderProcess renderProcessAfterStart = - ThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); + TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); Assert.assertEquals(renderProcessBeforeStart, renderProcessAfterStart); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java index 3560acb9..92ae3810 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnUnhandledKeyEventTest.java
@@ -13,11 +13,11 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.ImeAdapter; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; import java.util.Arrays; @@ -137,7 +137,8 @@ } private boolean dispatchKeyEvent(final KeyEvent event) throws Throwable { - return ThreadUtils.runOnUiThreadBlocking(() -> mTestContainerView.dispatchKeyEvent(event)); + return TestThreadUtils.runOnUiThreadBlocking( + () -> mTestContainerView.dispatchKeyEvent(event)); } private void dispatchDownAndUpKeyEvents(final int code) throws Throwable {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java index c16ce6a..32bae58 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java
@@ -24,12 +24,12 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.gfx.AwGLFunctor; import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.ImeAdapter; import org.chromium.content_public.browser.WebContentsAccessibility; 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.common.ContentUrlConstants; /** @@ -142,9 +142,8 @@ // It is difficult to show keyboard and wait until input method window shows up. // Instead, we simply emulate Android's behavior by keeping strong references. // See crbug.com/595613 for details. - resultReceivers[i] = ThreadUtils.runOnUiThreadBlocking( - () - -> ImeAdapter.fromWebContents(containerView.getWebContents()) + resultReceivers[i] = TestThreadUtils.runOnUiThreadBlocking( + () -> ImeAdapter.fromWebContents(containerView.getWebContents()) .getNewShowKeyboardReceiver()); } @@ -171,7 +170,7 @@ containerViews[i] = containerView; mActivityTestRule.loadUrlAsync( containerViews[i].getAwContents(), ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { WebContentsAccessibility webContentsA11y = WebContentsAccessibility.fromWebContents(containerView.getWebContents()); webContentsA11y.setState(true); @@ -336,7 +335,7 @@ @Override public boolean isSatisfied() { try { - return ThreadUtils.runOnUiThreadBlocking(() -> { + return TestThreadUtils.runOnUiThreadBlocking(() -> { int count_aw_contents = AwContents.getNativeInstanceCount(); int count_aw_functor = AwGLFunctor.getNativeInstanceCount(); return count_aw_contents <= MAX_IDLE_INSTANCES
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java index fff2de80..3d3f635 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java
@@ -19,8 +19,8 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.VisualStateCallback; import org.chromium.android_webview.test.util.GraphicsTestUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentUrlConstants; import java.util.concurrent.CountDownLatch; @@ -46,7 +46,7 @@ } void setBackgroundColorOnUiThread(final int c) { - ThreadUtils.runOnUiThreadBlocking(() -> mAwContents.setBackgroundColor(c)); + TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.setBackgroundColor(c)); } @Test @@ -87,7 +87,7 @@ @SmallTest @Feature({"AndroidWebView"}) public void testPictureListener() throws Throwable { - ThreadUtils.runOnUiThreadBlocking(() -> mAwContents.enableOnNewPicture(true, true)); + TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.enableOnNewPicture(true, true)); int pictureCount = mContentsClient.getPictureListenerHelper().getCallCount(); mActivityTestRule.loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), @@ -122,10 +122,10 @@ }); Assert.assertTrue(latch.await(AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - final int width = ThreadUtils.runOnUiThreadBlockingNoException( - () -> mContainerView.getWidth()); - final int height = ThreadUtils.runOnUiThreadBlockingNoException( - () -> mContainerView.getHeight()); + final int width = + TestThreadUtils.runOnUiThreadBlockingNoException(() -> mContainerView.getWidth()); + final int height = + TestThreadUtils.runOnUiThreadBlockingNoException(() -> mContainerView.getHeight()); visibleBitmap = GraphicsTestUtils.drawAwContentsOnUiThread(mAwContents, width, height); // Things that affect DOM page visibility:
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index b8112ac..c80b01c8 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -35,11 +35,11 @@ import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHelper; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.base.BuildInfo; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentSwitches; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.net.test.EmbeddedTestServer; @@ -586,7 +586,8 @@ private @RendererPriority int getRendererPriorityOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getEffectivePriorityForTesting()); + return TestThreadUtils.runOnUiThreadBlocking( + () -> awContents.getEffectivePriorityForTesting()); } private void setRendererPriorityOnUiThread(final AwContents awContents, @@ -715,7 +716,7 @@ private AwRenderProcess getRenderProcessOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); + return TestThreadUtils.runOnUiThreadBlocking(() -> awContents.getRenderProcess()); } @Test @@ -924,11 +925,8 @@ } private int getHistogramSampleCount(String name) throws Throwable { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - mHistogramTotalCount = RecordHistogram.getHistogramTotalCountForTesting(name); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + mHistogramTotalCount = RecordHistogram.getHistogramTotalCountForTesting(name); }); return mHistogramTotalCount; }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwImeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwImeTest.java index aafd221..ed32d393 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwImeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwImeTest.java
@@ -17,7 +17,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -25,6 +24,7 @@ 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.TestInputMethodManagerWrapper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Tests for IME (input method editor) on Android WebView. @@ -56,7 +56,7 @@ @Before public void setUp() throws Exception { mContentsClient = new TestAwContentsClient(); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { // Use detached container view to avoid focus request. mTestContainerView = mActivityTestRule.createDetachedAwTestContainerView(mContentsClient); @@ -82,7 +82,7 @@ } private void focusOnEditTextAndShowKeyboard() { - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { mEditText.requestFocus(); InputMethodManager imm = (InputMethodManager) mActivityTestRule.getActivity().getSystemService( @@ -92,7 +92,7 @@ } private void focusOnWebViewAndEnableEditing() throws Exception { - ThreadUtils.runOnUiThreadBlocking((Runnable) () -> mTestContainerView.requestFocus()); + TestThreadUtils.runOnUiThreadBlocking((Runnable) () -> mTestContainerView.requestFocus()); AwActivityTestRule.enableJavaScriptOnUiThread(mTestContainerView.getAwContents()); // View focus may not have been propagated to the renderer process yet. If document is not @@ -163,7 +163,7 @@ } }); - ThreadUtils.runOnUiThreadBlocking((Runnable) () -> { + TestThreadUtils.runOnUiThreadBlocking((Runnable) () -> { getInputConnection().sendKeyEvent( new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP)); }); @@ -195,7 +195,7 @@ } }); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { mTestContainerView.dispatchKeyEvent( new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP)); });
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java index 5960cb1..51561c7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java
@@ -15,8 +15,8 @@ import org.junit.runner.RunWith; import org.chromium.android_webview.AwContents; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Test suite for the WebView specific JavaBridge features. @@ -77,7 +77,7 @@ mActivityTestRule.executeJavaScriptAndWaitForResult( awContents, mContentsClient, "typeof test.destroy")); int currentCallCount = client2.getOnPageFinishedHelper().getCallCount(); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> awContents.evaluateJavaScriptForTests("test.destroy()", null)); client2.getOnPageFinishedHelper().waitForCallback(currentCallCount);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java index 2536a7e..4320fc0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
@@ -15,11 +15,11 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwSettings; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.ui.display.DisplayAndroid; @@ -56,7 +56,7 @@ settings.setJavaScriptEnabled(true); - DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { + DisplayAndroid displayAndroid = TestThreadUtils.runOnUiThreadBlockingNoException(() -> { return DisplayAndroid.getNonMultiDisplay( InstrumentationRegistry.getInstrumentation().getTargetContext()); }); @@ -100,7 +100,7 @@ settings.setJavaScriptEnabled(true); settings.setUseWideViewPort(true); - DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { + DisplayAndroid displayAndroid = TestThreadUtils.runOnUiThreadBlockingNoException(() -> { return DisplayAndroid.getNonMultiDisplay( InstrumentationRegistry.getInstrumentation().getTargetContext()); }); @@ -133,7 +133,7 @@ settings.setJavaScriptEnabled(true); - DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { + DisplayAndroid displayAndroid = TestThreadUtils.runOnUiThreadBlockingNoException(() -> { return DisplayAndroid.getNonMultiDisplay( InstrumentationRegistry.getInstrumentation().getTargetContext()); }); @@ -167,7 +167,7 @@ mActivityTestRule.loadUrlSync( awContents, onPageFinishedHelper, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - DisplayAndroid displayAndroid = ThreadUtils.runOnUiThreadBlockingNoException(() -> { + DisplayAndroid displayAndroid = TestThreadUtils.runOnUiThreadBlockingNoException(() -> { return DisplayAndroid.getNonMultiDisplay( InstrumentationRegistry.getInstrumentation().getTargetContext()); });
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwProxyControllerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwProxyControllerTest.java index ece3870..f1747ce 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwProxyControllerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwProxyControllerTest.java
@@ -16,9 +16,9 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwProxyController; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.util.concurrent.Executor; @@ -212,7 +212,7 @@ throws Exception { CallbackHelper ch = new CallbackHelper(); int callCount = ch.getCallCount(); - String result = ThreadUtils.runOnUiThreadBlocking(() -> { + String result = TestThreadUtils.runOnUiThreadBlocking(() -> { return mAwProxyController.setProxyOverride(proxyRules, bypassRules, new Runnable() { @Override public void run() { @@ -229,7 +229,7 @@ private void clearProxyOverrideSync() throws Exception { CallbackHelper ch = new CallbackHelper(); int callCount = ch.getCallCount(); - String result = ThreadUtils.runOnUiThreadBlocking(() -> { + String result = TestThreadUtils.runOnUiThreadBlocking(() -> { return mAwProxyController.clearProxyOverride(new Runnable() { @Override public void run() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java index 623ceda..a2c38165 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -38,7 +38,6 @@ import org.chromium.android_webview.test.util.VideoTestUtil; import org.chromium.android_webview.test.util.VideoTestWebServer; import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; @@ -50,6 +49,7 @@ import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.browser.test.util.DOMUtils; import org.chromium.content_public.browser.test.util.HistoryUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentSwitches; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.net.test.EmbeddedTestServer; @@ -1503,8 +1503,8 @@ final WebContents webContents = mAwContents.getWebContents(); final CallbackHelper onTitleUpdatedHelper = new CallbackHelper(); - final WebContentsObserver observer = - ThreadUtils.runOnUiThreadBlocking(() -> new WebContentsObserver(webContents) { + final WebContentsObserver observer = TestThreadUtils.runOnUiThreadBlocking( + () -> new WebContentsObserver(webContents) { @Override public void titleWasSet(String title) { onTitleUpdatedHelper.notifyCalled(); @@ -1540,7 +1540,7 @@ PREV_TITLE, getTitleOnUiThread()); } - ThreadUtils.runOnUiThreadBlocking(() -> webContents.removeObserver(observer)); + TestThreadUtils.runOnUiThreadBlocking(() -> webContents.removeObserver(observer)); } private String getData() { @@ -1550,7 +1550,7 @@ } public static int calcDisplayWidthDp(Context context) { - return ThreadUtils.runOnUiThreadBlockingNoException(() -> { + return TestThreadUtils.runOnUiThreadBlockingNoException(() -> { DisplayAndroid displayAndroid = DisplayAndroid.getNonMultiDisplay(context); return DisplayUtil.pxToDp(displayAndroid, displayAndroid.getDisplayWidth()); }); @@ -3365,8 +3365,7 @@ final int y = (webView.getBottom() - webView.getTop()) / 2; final AwContents awContents = webView.getAwContents(); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () - -> awContents.getWebContents().getEventForwarder().doubleTapForTest( + () -> awContents.getWebContents().getEventForwarder().doubleTapForTest( SystemClock.uptimeMillis(), x, y)); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java index da5f1db..0df3c70d 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java
@@ -44,8 +44,7 @@ mUnreachableWebDataUrl = AwContentsStatics.getUnreachableWebDataUrl(); // AwWebContentsObserver constructor must be run on the UI thread. InstrumentationRegistry.getInstrumentation().runOnMainSync( - () - -> mWebContentsObserver = + () -> mWebContentsObserver = new AwWebContentsObserver(mTestContainerView.getWebContents(), mTestContainerView.getAwContents(), mContentsClient)); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java index a67a937..705b8e1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
@@ -109,8 +109,7 @@ private void waitForScaleToBecome(final float expectedScale) throws Throwable { AwActivityTestRule.pollInstrumentationThread( - () - -> Math.abs(expectedScale + () -> Math.abs(expectedScale - mActivityTestRule.getScaleOnUiThread(mAwContents)) < EPSILON); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java index 56e6561..a363ac2 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/GeolocationTest.java
@@ -20,9 +20,9 @@ import org.chromium.android_webview.AwGeolocationPermissions; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.device.geolocation.LocationProviderOverrider; import org.chromium.device.geolocation.MockLocationProvider; @@ -157,15 +157,15 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "https://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests( - "initiate_getCurrentPosition();", null)); + "initiate_getCurrentPosition();", null)); AwActivityTestRule.pollInstrumentationThread(() -> getPositionCountFromJS() == 1); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests( - "initiate_getCurrentPosition();", null)); + "initiate_getCurrentPosition();", null)); AwActivityTestRule.pollInstrumentationThread(() -> getPositionCountFromJS() == 2); } @@ -182,7 +182,7 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "https://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests("initiate_watchPosition();", null)); AwActivityTestRule.pollInstrumentationThread(() -> getPositionCountFromJS() > 1); @@ -198,7 +198,7 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "https://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests("initiate_watchPosition();", null)); AwActivityTestRule.pollInstrumentationThread(() -> getPositionCountFromJS() > 1); @@ -236,7 +236,7 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "https://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests("initiate_watchPosition();", null)); Assert.assertEquals(0, getPositionCountFromJS()); @@ -276,9 +276,9 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "https://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests( - "initiate_getCurrentPosition();", null)); + "initiate_getCurrentPosition();", null)); AwActivityTestRule.pollInstrumentationThread(new Callable<Boolean>() { @Override @@ -300,9 +300,9 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "http://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests( - "initiate_getCurrentPosition();", null)); + "initiate_getCurrentPosition();", null)); AwActivityTestRule.pollInstrumentationThread(new Callable<Boolean>() { @Override @@ -322,9 +322,9 @@ mContentsClient.getOnPageFinishedHelper(), RAW_HTML, "text/html", false, "http://google.com/", ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> mAwContents.evaluateJavaScriptForTests( - "initiate_getCurrentPosition();", null)); + "initiate_getCurrentPosition();", null)); AwActivityTestRule.pollInstrumentationThread(() -> getPositionCountFromJS() > 0); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java index a9db26e4..c09602c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/NavigationHistoryTest.java
@@ -16,11 +16,11 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.CommonResources; -import org.chromium.base.ThreadUtils; import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.NavigationHistory; import org.chromium.content_public.browser.test.util.HistoryUtils; 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; /** @@ -58,7 +58,7 @@ private NavigationHistory getNavigationHistory(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking( + return TestThreadUtils.runOnUiThreadBlocking( () -> awContents.getNavigationController().getNavigationHistory()); }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java index f8feb23d..13aa9f06 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PlatformMediaCodecTest.java
@@ -12,11 +12,11 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.DOMUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Test that a page with a non-Chrome media codec can playback correctly; this @@ -53,7 +53,7 @@ private WebContents getWebContentsOnUiThread() { try { - return ThreadUtils.runOnUiThreadBlocking(() -> mWebContents); + return TestThreadUtils.runOnUiThreadBlocking(() -> mWebContents); } catch (Exception e) { Assert.fail(e.getMessage()); return null;
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 4bccb1e..670aea4 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
@@ -21,10 +21,10 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.ErrorCodeConversionHelper; import org.chromium.android_webview.policy.AwPolicyProvider; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; 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; @@ -81,7 +81,7 @@ public void testBlacklistedUrl() throws Throwable { final AwPolicyProvider testProvider = new AwPolicyProvider(mActivityTestRule.getActivity().getApplicationContext()); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> CombinedPolicyProvider.get().registerProvider(testProvider)); navigateAndCheckOutcome(mFooTestUrl, 0 /* error count before */, 0 /* error count after*/); @@ -161,7 +161,7 @@ AbstractAppRestrictionsProvider.setTestRestrictions( PolicyData.asBundle(Arrays.asList(policies))); - ThreadUtils.runOnUiThreadBlocking(() -> testProvider.refresh()); + TestThreadUtils.runOnUiThreadBlocking(() -> testProvider.refresh()); // To avoid race conditions InstrumentationRegistry.getInstrumentation().waitForIdleSync();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java index b866822..f7905e3 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PopupWindowTest.java
@@ -18,7 +18,6 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.AwActivityTestRule.PopupInfo; import org.chromium.android_webview.test.util.CommonResources; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.content_public.browser.SelectionPopupController; @@ -26,6 +25,7 @@ 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.TestCallbackHelperContainer; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.util.Locale; @@ -260,10 +260,10 @@ // Now long press on some texts and see if the text handles show up. DOMUtils.longPressNode(popupContents.getWebContents(), "plain_text"); - SelectionPopupController controller = ThreadUtils.runOnUiThreadBlocking( + SelectionPopupController controller = TestThreadUtils.runOnUiThreadBlocking( () -> SelectionPopupController.fromWebContents(popupContents.getWebContents())); assertWaitForSelectActionBarStatus(true, controller); - Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(() -> controller.hasSelection())); + Assert.assertTrue(TestThreadUtils.runOnUiThreadBlocking(() -> controller.hasSelection())); // Now hide the select action bar. This should hide the text handles and // clear the selection. @@ -292,7 +292,7 @@ } private void runPopupUserGestureTest(boolean hasOpener) throws Throwable { - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { mParentContents.getSettings().setJavaScriptEnabled(true); mParentContents.getSettings().setSupportMultipleWindows(true); mParentContents.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java index 54ac9b9..9ba057ac 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java
@@ -22,7 +22,6 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.CommonResources; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; @@ -30,6 +29,7 @@ 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.TestCallbackHelperContainer.OnPageFinishedHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.util.concurrent.CountDownLatch; @@ -614,7 +614,7 @@ final ChannelContainer channelContainer = new ChannelContainer(); loadPage(ECHO_PAGE); final MessagePort[] channel = - ThreadUtils.runOnUiThreadBlocking(() -> mAwContents.createMessageChannel()); + TestThreadUtils.runOnUiThreadBlocking(() -> mAwContents.createMessageChannel()); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { channel[0].setMessageCallback(
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java index db9bab0..76d8a8c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -56,6 +56,7 @@ import org.chromium.content_public.browser.WebContents; 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.common.ContentUrlConstants; import org.chromium.net.test.EmbeddedTestServer; @@ -348,8 +349,7 @@ mTestServer = EmbeddedTestServer.createAndStartServer( InstrumentationRegistry.getInstrumentation().getContext()); InstrumentationRegistry.getInstrumentation().runOnMainSync( - () - -> mWebContentsObserver = + () -> mWebContentsObserver = new TestAwWebContentsObserver(mContainerView.getWebContents(), mAwContents, mContentsClient) {}); } @@ -584,7 +584,7 @@ private void verifyWhiteListRule(final String rule, boolean expected) throws Throwable { final WhitelistHelper helper = new WhitelistHelper(); final int count = helper.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { ArrayList<String> s = new ArrayList<String>(); s.add(rule); AwContentsStatics.setSafeBrowsingWhitelist(s, helper); @@ -1083,7 +1083,7 @@ } private String getSafeBrowsingLocaleOnUiThreadForTesting() throws Exception { - return ThreadUtils.runOnUiThreadBlocking( + return TestThreadUtils.runOnUiThreadBlocking( () -> AwContents.getSafeBrowsingLocaleForTesting()); } @@ -1200,7 +1200,7 @@ .appendQueryParameter("hl", getSafeBrowsingLocaleOnUiThreadForTesting()) .fragment("safe-browsing-policies") .build(); - ThreadUtils.runOnUiThreadBlocking( + TestThreadUtils.runOnUiThreadBlocking( () -> { mPrivacyPolicyUrl = AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl(); }); Assert.assertEquals(privacyPolicyUrl, this.mPrivacyPolicyUrl); Assert.assertNotNull(this.mPrivacyPolicyUrl); @@ -1224,7 +1224,7 @@ @Override public boolean isSatisfied() { try { - return ThreadUtils.runOnUiThreadBlocking(() -> { + return TestThreadUtils.runOnUiThreadBlocking(() -> { int count_aw_contents = AwContents.getNativeInstanceCount(); return count_aw_contents == 0; });
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java index da346040..d6573b2 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SaveRestoreStateTest.java
@@ -17,10 +17,10 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.CommonResources; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationHistory; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; /** @@ -99,7 +99,7 @@ private NavigationHistory getNavigationHistoryOnUiThread( final TestVars vars) throws Throwable { - return ThreadUtils.runOnUiThreadBlocking( + return TestThreadUtils.runOnUiThreadBlocking( () -> vars.navigationController.getNavigationHistory()); } @@ -156,7 +156,7 @@ final Bundle invalidState = new Bundle(); invalidState.putByteArray(AwContents.SAVE_RESTORE_STATE_KEY, "invalid state".getBytes()); - boolean result = ThreadUtils.runOnUiThreadBlocking( + boolean result = TestThreadUtils.runOnUiThreadBlocking( () -> mVars.awContents.restoreState(invalidState)); Assert.assertFalse(result); } @@ -167,7 +167,7 @@ public void testSaveStateForNoNavigationFails() throws Throwable { final Bundle state = new Bundle(); boolean result = - ThreadUtils.runOnUiThreadBlocking(() -> mVars.awContents.restoreState(state)); + TestThreadUtils.runOnUiThreadBlocking(() -> mVars.awContents.restoreState(state)); Assert.assertFalse(result); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java index 5840b9f..4f61483 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java
@@ -26,7 +26,6 @@ import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.JavascriptEventObserver; -import org.chromium.base.ThreadUtils; import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; @@ -35,6 +34,7 @@ import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.DOMUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.io.ByteArrayInputStream; import java.io.FilterInputStream; @@ -404,7 +404,7 @@ private AwTestContainerView createDetachedTestContainerViewOnMainSync( final AwContentsClient awContentsClient) { - return ThreadUtils.runOnUiThreadBlockingNoException(() -> { + return TestThreadUtils.runOnUiThreadBlockingNoException(() -> { AwTestContainerView detachedView = mActivityTestRule.createDetachedAwTestContainerView(awContentsClient); detachedView.setClipBounds(new Rect(0, 0, 100, 100));
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java index 8c38f49..32c5e4c1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/WebKitHitTestTest.java
@@ -24,9 +24,9 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.util.AwTestTouchUtils; import org.chromium.android_webview.test.util.CommonResources; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnPageCommitVisibleHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; import java.util.concurrent.TimeUnit; @@ -125,7 +125,7 @@ && stringEquals(expectedImageSrc, data.imgSrc); }); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { Handler dummyHandler = new Handler(); Message focusNodeHrefMsg = dummyHandler.obtainMessage(); Message imageRefMsg = dummyHandler.obtainMessage();
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java index 157da35..2c98294b 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/WebViewModalDialogOverrideTest.java
@@ -20,11 +20,11 @@ import org.chromium.android_webview.JsPromptResultReceiver; import org.chromium.android_webview.JsResultReceiver; import org.chromium.android_webview.test.util.AwTestTouchUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.GestureListenerManager; import org.chromium.content_public.browser.GestureStateListener; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.concurrent.atomic.AtomicBoolean; @@ -195,7 +195,7 @@ private void tapViewAndWait(AwTestContainerView view) throws Throwable { final TapGestureStateListener tapGestureStateListener = new TapGestureStateListener(); int callCount = tapGestureStateListener.getCallCount(); - ThreadUtils.runOnUiThreadBlocking(() -> { + TestThreadUtils.runOnUiThreadBlocking(() -> { GestureListenerManager.fromWebContents(view.getWebContents()) .addListener(tapGestureStateListener); });
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java index 660335f..abbee44 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/AwQuotaManagerBridgeTestUtil.java
@@ -7,15 +7,15 @@ import android.support.test.InstrumentationRegistry; import org.chromium.android_webview.AwQuotaManagerBridge; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * This class provides common methods for AwQuotaManagerBridge related tests */ public class AwQuotaManagerBridgeTestUtil { public static AwQuotaManagerBridge getQuotaManagerBridge() throws Exception { - return ThreadUtils.runOnUiThreadBlocking(() -> AwQuotaManagerBridge.getInstance()); + return TestThreadUtils.runOnUiThreadBlocking(() -> AwQuotaManagerBridge.getInstance()); } private static class GetOriginsCallbackHelper extends CallbackHelper {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java index eaf2532..14a2941 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/GraphicsTestUtils.java
@@ -12,7 +12,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.test.AwActivityTestRule; import org.chromium.android_webview.test.AwTestContainerView; -import org.chromium.base.ThreadUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.display.DisplayAndroid; /** @@ -20,7 +20,7 @@ */ public class GraphicsTestUtils { public static float dipScaleForContext(Context context) { - return ThreadUtils.runOnUiThreadBlockingNoException( + return TestThreadUtils.runOnUiThreadBlockingNoException( () -> { return DisplayAndroid.getNonMultiDisplay(context).getDipScale(); }); } @@ -37,7 +37,7 @@ public static Bitmap drawAwContentsOnUiThread( final AwContents awContents, final int width, final int height) { - return ThreadUtils.runOnUiThreadBlockingNoException( + return TestThreadUtils.runOnUiThreadBlockingNoException( () -> drawAwContents(awContents, width, height)); } @@ -72,17 +72,18 @@ public static int sampleBackgroundColorOnUiThread(final AwContents awContents) throws Exception { - return ThreadUtils.runOnUiThreadBlocking( + return TestThreadUtils.runOnUiThreadBlocking( () -> drawAwContents(awContents, 10, 10, 0, 0).getPixel(0, 0)); } // Gets the pixel color at the center of AwContents. public static int getPixelColorAtCenterOfView( final AwContents awContents, final AwTestContainerView testContainerView) { - return ThreadUtils.runOnUiThreadBlockingNoException( - () -> drawAwContents(awContents, 2, 2, -(float) testContainerView.getWidth() / 2, - -(float) testContainerView.getHeight() / 2) - .getPixel(0, 0)); + return TestThreadUtils.runOnUiThreadBlockingNoException( + () -> drawAwContents(awContents, 2, 2, + -(float) testContainerView.getWidth() / 2, + -(float) testContainerView.getHeight() / 2) + .getPixel(0, 0)); } public static void pollForBackgroundColor(final AwContents awContents, final int c)
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java index 9d71471..100914e3 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/util/VideoSurfaceViewUtils.java
@@ -7,7 +7,7 @@ import android.view.View; import android.view.ViewGroup; -import org.chromium.base.ThreadUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Utils for testing SurfaceViews (SurfaceViews that display video). @@ -16,7 +16,7 @@ private static int containsNumChildrenOfType( final View view, final Class<? extends View> childType) throws Exception { - return ThreadUtils.runOnUiThreadBlocking( + return TestThreadUtils.runOnUiThreadBlocking( () -> containsNumChildrenOfTypeOnUiThread(view, childType)); }
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 75e8d20..fd6adf5 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -7,13 +7,16 @@ import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//build/config/locales.gni") +import("//tools/v8_context_snapshot/v8_context_snapshot.gni") template("system_webview_apk_tmpl") { android_apk(target_name) { forward_variables_from(invoker, "*") deps += [ - "//android_webview:assets", + "//android_webview:license_assets", + "//android_webview:locale_pak_assets", + "//android_webview:pak_file_assets", "//android_webview/apk:webview_license_activity_java", "//android_webview/apk:webview_license_provider_java", "//android_webview/glue", @@ -30,6 +33,10 @@ _use_trichrome_library = defined(use_trichrome_library) && use_trichrome_library + if (!_use_trichrome_library || !trichrome_shared_assets) { + deps += [ "//android_webview:monochrome_webview_assets" ] + } + if (!_use_trichrome_library) { shared_libraries = [ "//android_webview:libwebviewchromium" ] deps += [ @@ -59,6 +66,11 @@ if (build_apk_secondary_abi) { secondary_native_lib_placeholders = [ "libdummy.so" ] + if (use_v8_context_snapshot) { + deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ] + } else { + deps += [ "//v8:v8_external_startup_data_assets" ] + } } } else { native_lib_placeholders = [ "libdummy.so" ]
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index e7f8bd9f..73d1ab0a 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -352,6 +352,7 @@ "../browser/permission/permission_request_handler_unittest.cc", "../browser/renderer_host/auto_login_parser_unittest.cc", "../browser/safe_browsing/aw_safe_browsing_whitelist_manager_unittest.cc", + "../browser/scoped_add_feature_flags_unittests.cc", "../browser/state_serializer_unittest.cc", "../lib/webview_tests.cc", ]
diff --git a/android_webview/tools/automated_ui_tests/BUILD.gn b/android_webview/tools/automated_ui_tests/BUILD.gn index 8a84ad7..eda759cb 100644 --- a/android_webview/tools/automated_ui_tests/BUILD.gn +++ b/android_webview/tools/automated_ui_tests/BUILD.gn
@@ -69,4 +69,5 @@ data = [ "test/data/", ] + additional_apks = [ system_webview_apk_target ] }
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index 9d069279..e769cba 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -270,6 +270,9 @@ registry->RegisterIntegerPref( prefs::kAccessibilityAutoclickMovementThreshold, kDefaultAutoclickMovementThreshold); + registry->RegisterIntegerPref( + prefs::kAccessibilityAutoclickMenuPosition, + static_cast<int>(kDefaultAutoclickMenuPosition)); registry->RegisterBooleanPref(prefs::kAccessibilityCaretHighlightEnabled, false); registry->RegisterBooleanPref(prefs::kAccessibilityCursorHighlightEnabled, @@ -320,6 +323,7 @@ prefs::kAccessibilityAutoclickRevertToLeftClick); registry->RegisterForeignPref( prefs::kAccessibilityAutoclickMovementThreshold); + registry->RegisterForeignPref(prefs::kAccessibilityAutoclickMenuPosition); registry->RegisterForeignPref(prefs::kAccessibilityCaretHighlightEnabled); registry->RegisterForeignPref(prefs::kAccessibilityCursorHighlightEnabled); registry->RegisterForeignPref(prefs::kAccessibilityDictationEnabled); @@ -837,6 +841,11 @@ &AccessibilityController::UpdateAutoclickMovementThresholdFromPref, base::Unretained(this))); pref_change_registrar_->Add( + prefs::kAccessibilityAutoclickMenuPosition, + base::BindRepeating( + &AccessibilityController::UpdateAutoclickMenuPositionFromPref, + base::Unretained(this))); + pref_change_registrar_->Add( prefs::kAccessibilityCaretHighlightEnabled, base::BindRepeating( &AccessibilityController::UpdateCaretHighlightFromPref, @@ -900,6 +909,7 @@ UpdateAutoclickEventTypeFromPref(); UpdateAutoclickRevertToLeftClickFromPref(); UpdateAutoclickMovementThresholdFromPref(); + UpdateAutoclickMenuPositionFromPref(); UpdateCaretHighlightFromPref(); UpdateCursorHighlightFromPref(); UpdateDictationFromPref(); @@ -980,6 +990,15 @@ movement_threshold); } +void AccessibilityController::UpdateAutoclickMenuPositionFromPref() { + DCHECK(active_user_prefs_); + mojom::AutoclickMenuPosition menu_position = + static_cast<mojom::AutoclickMenuPosition>(active_user_prefs_->GetInteger( + prefs::kAccessibilityAutoclickMenuPosition)); + + Shell::Get()->autoclick_controller()->SetMenuPosition(menu_position); +} + void AccessibilityController::UpdateCaretHighlightFromPref() { DCHECK(active_user_prefs_); const bool enabled = active_user_prefs_->GetBoolean(
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h index b24e12f..774a5ac 100644 --- a/ash/accessibility/accessibility_controller.h +++ b/ash/accessibility/accessibility_controller.h
@@ -206,6 +206,7 @@ void UpdateAutoclickEventTypeFromPref(); void UpdateAutoclickRevertToLeftClickFromPref(); void UpdateAutoclickMovementThresholdFromPref(); + void UpdateAutoclickMenuPositionFromPref(); void UpdateCaretHighlightFromPref(); void UpdateCursorHighlightFromPref(); void UpdateDictationFromPref();
diff --git a/ash/accessibility/accessibility_focus_ring_controller.cc b/ash/accessibility/accessibility_focus_ring_controller.cc index 1f051fd3..be919e2 100644 --- a/ash/accessibility/accessibility_focus_ring_controller.cc +++ b/ash/accessibility/accessibility_focus_ring_controller.cc
@@ -68,12 +68,8 @@ AccessibilityFocusRingGroup* focus_ring_group = GetFocusRingGroupForId(focus_ring_id, true /* Create if missing */); - focus_ring_group->SetColor(focus_ring->color, this); - - if (focus_ring_group->SetFocusRectsAndBehavior(focus_ring->rects_in_screen, - focus_ring->behavior, this)) { + if (focus_ring_group->UpdateFocusRing(std::move(focus_ring), this)) OnLayerChange(focus_ring_group->focus_animation_info()); - } } void AccessibilityFocusRingController::HideFocusRing( @@ -185,7 +181,7 @@ void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() { for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end(); ++iter) - iter->second->UpdateFocusRingsFromFocusRects(this); + iter->second->UpdateFocusRingsFromInfo(this); } void AccessibilityFocusRingController::OnAnimationStep(
diff --git a/ash/accessibility/accessibility_focus_ring_group.cc b/ash/accessibility/accessibility_focus_ring_group.cc index c8a5f2a..4c35e5a1 100644 --- a/ash/accessibility/accessibility_focus_ring_group.cc +++ b/ash/accessibility/accessibility_focus_ring_group.cc
@@ -54,37 +54,11 @@ AccessibilityFocusRingGroup::~AccessibilityFocusRingGroup() {} -void AccessibilityFocusRingGroup::SetColor( - SkColor color, - AccessibilityLayerDelegate* delegate) { - focus_ring_color_ = color; - UpdateFocusRingsFromFocusRects(delegate); -} - -void AccessibilityFocusRingGroup::ResetColor( - AccessibilityLayerDelegate* delegate) { - focus_ring_color_.reset(); - UpdateFocusRingsFromFocusRects(delegate); -} - -void AccessibilityFocusRingGroup::EnableDoubleFocusRing( - SkColor color, - AccessibilityLayerDelegate* delegate) { - focus_ring_secondary_color_ = color; - UpdateFocusRingsFromFocusRects(delegate); -} - -void AccessibilityFocusRingGroup::DisableDoubleFocusRing( - AccessibilityLayerDelegate* delegate) { - focus_ring_secondary_color_.reset(); - UpdateFocusRingsFromFocusRects(delegate); -} - -void AccessibilityFocusRingGroup::UpdateFocusRingsFromFocusRects( +void AccessibilityFocusRingGroup::UpdateFocusRingsFromInfo( AccessibilityLayerDelegate* delegate) { previous_focus_rings_.swap(focus_rings_); focus_rings_.clear(); - RectsToRings(focus_rects_, &(focus_rings_)); + RectsToRings(focus_ring_info_->rects_in_screen, &(focus_rings_)); focus_layers_.resize(focus_rings_.size()); if (focus_rings_.empty()) return; @@ -95,7 +69,8 @@ std::make_unique<AccessibilityFocusRingLayer>(delegate); } - if (focus_ring_behavior_ == mojom::FocusRingBehavior::PERSIST_FOCUS_RING && + if (focus_ring_info_->behavior == + mojom::FocusRingBehavior::PERSIST_FOCUS_RING && focus_layers_[0]->CanAnimate() && !no_fade_for_testing_) { // In PERSIST mode, animate the first ring to its destination // location, then set the rest of the rings directly. @@ -109,15 +84,9 @@ } for (size_t i = 0; i < focus_rings_.size(); ++i) { - if (focus_ring_color_) - focus_layers_[i]->SetColor(*(focus_ring_color_)); - else - focus_layers_[i]->ResetColor(); - - if (focus_ring_secondary_color_) - focus_layers_[i]->EnableDoubleFocusRing(*(focus_ring_secondary_color_)); - else - focus_layers_[i]->DisableDoubleFocusRing(); + focus_layers_[i]->SetAppearance(focus_ring_info_->type, + focus_ring_info_->color, + focus_ring_info_->secondary_color); } } @@ -136,7 +105,8 @@ if (timestamp < focus_animation_info_.change_time) timestamp = focus_animation_info_.change_time; - if (focus_ring_behavior_ == mojom::FocusRingBehavior::PERSIST_FOCUS_RING) { + if (focus_ring_info_->behavior == + mojom::FocusRingBehavior::PERSIST_FOCUS_RING) { base::TimeDelta delta = timestamp - focus_animation_info_.change_time; base::TimeDelta transition_time = base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds); @@ -164,30 +134,28 @@ } } -bool AccessibilityFocusRingGroup::SetFocusRectsAndBehavior( - const std::vector<gfx::Rect>& rects, - mojom::FocusRingBehavior focus_ring_behavior, +bool AccessibilityFocusRingGroup::UpdateFocusRing( + mojom::FocusRingPtr focus_ring, AccessibilityLayerDelegate* delegate) { - std::vector<gfx::Rect> clean_rects(rects); + std::vector<gfx::Rect> rects(focus_ring->rects_in_screen); // Remove duplicates if (rects.size() > 1) { std::set<gfx::Rect> rects_set(rects.begin(), rects.end()); - clean_rects.assign(rects_set.begin(), rects_set.end()); + focus_ring->rects_in_screen.assign(rects_set.begin(), rects_set.end()); } // If there is no change, don't do any work. - if (focus_ring_behavior_ == focus_ring_behavior && - clean_rects == focus_rects_) + if (focus_ring_info_ == focus_ring) return false; - focus_ring_behavior_ = focus_ring_behavior; - focus_rects_ = clean_rects; - UpdateFocusRingsFromFocusRects(delegate); + + focus_ring_info_ = std::move(focus_ring); + UpdateFocusRingsFromInfo(delegate); return true; } void AccessibilityFocusRingGroup::ClearFocusRects( AccessibilityLayerDelegate* delegate) { - focus_rects_.clear(); - UpdateFocusRingsFromFocusRects(delegate); + focus_ring_info_->rects_in_screen.clear(); + UpdateFocusRingsFromInfo(delegate); } int AccessibilityFocusRingGroup::GetMargin() const {
diff --git a/ash/accessibility/accessibility_focus_ring_group.h b/ash/accessibility/accessibility_focus_ring_group.h index e74895e0..b70038b2 100644 --- a/ash/accessibility/accessibility_focus_ring_group.h +++ b/ash/accessibility/accessibility_focus_ring_group.h
@@ -28,22 +28,13 @@ AccessibilityFocusRingGroup(); virtual ~AccessibilityFocusRingGroup(); - void SetColor(SkColor color, AccessibilityLayerDelegate* delegate); - void ResetColor(AccessibilityLayerDelegate* delegate); - - void EnableDoubleFocusRing(SkColor secondary_color, - AccessibilityLayerDelegate* delegate); - void DisableDoubleFocusRing(AccessibilityLayerDelegate* delegate); - - void UpdateFocusRingsFromFocusRects(AccessibilityLayerDelegate* delegate); + void UpdateFocusRingsFromInfo(AccessibilityLayerDelegate* delegate); bool CanAnimate() const; void AnimateFocusRings(base::TimeTicks timestamp); - // Returns true if the rects and behavior are changed, false if there was no - // change. - bool SetFocusRectsAndBehavior(const std::vector<gfx::Rect>& rects, - mojom::FocusRingBehavior focus_ring_behavior, - AccessibilityLayerDelegate* delegate); + // Returns true if the focus ring has changed, false if there were no changes. + bool UpdateFocusRing(mojom::FocusRingPtr focus_ring, + AccessibilityLayerDelegate* delegate); void ClearFocusRects(AccessibilityLayerDelegate* delegate); @@ -79,15 +70,11 @@ gfx::Rect* bottom) const; bool Intersects(const gfx::Rect& r1, const gfx::Rect& r2) const; - std::vector<gfx::Rect> focus_rects_; - base::Optional<SkColor> focus_ring_color_; - base::Optional<SkColor> focus_ring_secondary_color_; + mojom::FocusRingPtr focus_ring_info_; std::vector<AccessibilityFocusRing> previous_focus_rings_; std::vector<std::unique_ptr<AccessibilityFocusRingLayer>> focus_layers_; std::vector<AccessibilityFocusRing> focus_rings_; LayerAnimationInfo focus_animation_info_; - mojom::FocusRingBehavior focus_ring_behavior_ = - mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING; bool no_fade_for_testing_ = false; DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingGroup);
diff --git a/ash/accessibility/accessibility_focus_ring_layer.cc b/ash/accessibility/accessibility_focus_ring_layer.cc index fa31c6c..3ee48db2 100644 --- a/ash/accessibility/accessibility_focus_ring_layer.cc +++ b/ash/accessibility/accessibility_focus_ring_layer.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" #include "ui/gfx/canvas.h" @@ -17,10 +18,9 @@ namespace { // The number of pixels in the color gradient that fades to transparent. -const int kGradientWidth = 6; - -// The default color of the focus ring. -const SkColor kDefaultFocusRingColor = SkColorSetARGB(255, 247, 152, 58); +constexpr int kGradientWidth = 6; +constexpr int kDefaultStrokeWidth = 2; +constexpr float kDashLength = 3.f; int sign(int x) { return ((x > 0) ? 1 : (x == 0) ? 0 : -1); @@ -103,15 +103,14 @@ CreateOrUpdateLayer(root_window, "AccessibilityFocusRing", bounds); } -void AccessibilityFocusRingLayer::EnableDoubleFocusRing( - SkColor secondary_color) { +void AccessibilityFocusRingLayer::SetAppearance(mojom::FocusRingType type, + SkColor color, + SkColor secondary_color) { + SetColor(color); + type_ = type; secondary_color_ = secondary_color; } -void AccessibilityFocusRingLayer::DisableDoubleFocusRing() { - secondary_color_.reset(); -} - void AccessibilityFocusRingLayer::OnPaintLayer( const ui::PaintContext& context) { ui::PaintRecorder recorder(context, layer()->size()); @@ -119,38 +118,77 @@ cc::PaintFlags flags; flags.setAntiAlias(true); flags.setStyle(cc::PaintFlags::kStroke_Style); - flags.setStrokeWidth(2); - if (secondary_color_) - DrawDoubleFocusRing(recorder, flags); - else - DrawFocusRing(recorder, flags); + switch (type_) { + case mojom::FocusRingType::GLOW: + DrawGlowFocusRing(recorder, flags); + break; + case mojom::FocusRingType::SOLID: + DrawSolidFocusRing(recorder, flags); + break; + case mojom::FocusRingType::DASHED: + DrawDashedFocusRing(recorder, flags); + break; + } } -void AccessibilityFocusRingLayer::DrawDoubleFocusRing( +void AccessibilityFocusRingLayer::DrawSolidFocusRing( ui::PaintRecorder& recorder, cc::PaintFlags& flags) { - SkColor base_color = - has_custom_color() ? custom_color() : kDefaultFocusRingColor; + if (!has_custom_color()) + NOTREACHED(); SkPath path; gfx::Vector2d offset = layer()->bounds().OffsetFromOrigin(); - flags.setColor(base_color); + flags.setColor(custom_color()); + flags.setStrokeWidth(kDefaultStrokeWidth); + path = MakePath(ring_, 0, offset); recorder.canvas()->DrawPath(path, flags); - flags.setColor(*(secondary_color_)); - path = MakePath(ring_, 2, offset); + flags.setColor(secondary_color_); + path = MakePath(ring_, kDefaultStrokeWidth, offset); recorder.canvas()->DrawPath(path, flags); } -void AccessibilityFocusRingLayer::DrawFocusRing(ui::PaintRecorder& recorder, - cc::PaintFlags& flags) { - SkColor base_color = - has_custom_color() ? custom_color() : kDefaultFocusRingColor; +void AccessibilityFocusRingLayer::DrawDashedFocusRing( + ui::PaintRecorder& recorder, + cc::PaintFlags& flags) { + if (!has_custom_color()) + NOTREACHED(); SkPath path; gfx::Vector2d offset = layer()->bounds().OffsetFromOrigin(); + + SkScalar intervals[] = {kDashLength, kDashLength}; + int intervals_length = 2; + flags.setPathEffect(SkDashPathEffect::Make(intervals, intervals_length, 0)); + + // To keep the dashes properly lined up, we will draw the outside line first, + // and cover it with the inner line. + flags.setColor(secondary_color_); + flags.setStrokeWidth(2 * kDefaultStrokeWidth); + + path = MakePath(ring_, 0, offset); + recorder.canvas()->DrawPath(path, flags); + + flags.setColor(custom_color()); + flags.setStrokeWidth(kDefaultStrokeWidth); + + path = MakePath(ring_, 0, offset); + recorder.canvas()->DrawPath(path, flags); +} + +void AccessibilityFocusRingLayer::DrawGlowFocusRing(ui::PaintRecorder& recorder, + cc::PaintFlags& flags) { + if (!has_custom_color()) + NOTREACHED(); + SkColor base_color = custom_color(); + + SkPath path; + gfx::Vector2d offset = layer()->bounds().OffsetFromOrigin(); + flags.setStrokeWidth(kDefaultStrokeWidth); + const int w = kGradientWidth; for (int i = 0; i < w; ++i) { flags.setColor(SkColorSetA(base_color, 255 * (w - i) * (w - i) / (w * w)));
diff --git a/ash/accessibility/accessibility_focus_ring_layer.h b/ash/accessibility/accessibility_focus_ring_layer.h index 5e586cf0..42ba115 100644 --- a/ash/accessibility/accessibility_focus_ring_layer.h +++ b/ash/accessibility/accessibility_focus_ring_layer.h
@@ -8,6 +8,7 @@ #include "ash/accessibility/accessibility_focus_ring.h" #include "ash/accessibility/focus_ring_layer.h" #include "ash/ash_export.h" +#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h" #include "base/macros.h" #include "ui/compositor/paint_recorder.h" @@ -24,8 +25,9 @@ // Create the layer and update its bounds and position in the hierarchy. void Set(const AccessibilityFocusRing& ring); - void EnableDoubleFocusRing(SkColor secondary_color); - void DisableDoubleFocusRing(); + void SetAppearance(mojom::FocusRingType type, + SkColor color, + SkColor secondary_color); SkColor color_for_testing() { return custom_color(); } @@ -33,13 +35,16 @@ // ui::LayerDelegate overrides: void OnPaintLayer(const ui::PaintContext& context) override; - void DrawFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags); - void DrawDoubleFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags); + void DrawGlowFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags); + void DrawSolidFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags); + void DrawDashedFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags); // The outline of the current focus ring. AccessibilityFocusRing ring_; - // The secondary color, if there is a double focus ring. - base::Optional<SkColor> secondary_color_; + // The type of focus ring. + mojom::FocusRingType type_; + // The secondary color. + SkColor secondary_color_; DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingLayer); };
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 5d04d414..ae50a24 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -850,8 +850,12 @@ } } -void AppListControllerImpl::OpenSearchResult(const std::string& result_id, - int event_flags) { +void AppListControllerImpl::OpenSearchResult( + const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) { app_list::SearchResult* result = search_model_.FindSearchResult(result_id); if (!result) return; @@ -860,9 +864,10 @@ result->display_type(), ash::SearchResultDisplayType::kLast); - // Record the search metric if the SearchResult is not a suggested app. - if (result->display_type() != ash::SearchResultDisplayType::kRecommendation) { - // Count AppList.Search here because it is composed of search + action. + // Suggestion chips are not represented to the user as search results, so do + // not record search result metrics for them. + if (launched_from != + ash::mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip) { base::RecordAction(base::UserMetricsAction("AppList_OpenSearchResult")); UMA_HISTOGRAM_COUNTS_100(app_list::kSearchQueryLength, @@ -877,6 +882,7 @@ if (presenter_.IsVisible() && result->is_omnibox_search() && IsAssistantAllowedAndEnabled() && app_list_features::IsEmbeddedAssistantUIEnabled()) { + // TODO(newcomer): Record search result launches via assistant. Shell::Get()->assistant_controller()->ui_controller()->ShowUi( AssistantEntryPoint::kLauncherSearchResult); Shell::Get()->assistant_controller()->OpenUrl( @@ -884,7 +890,8 @@ base::UTF16ToUTF8(result->title()))); } else { if (client_) - client_->OpenSearchResult(result_id, event_flags); + client_->OpenSearchResult(result_id, event_flags, launched_from, + launch_type, suggestion_index); } ResetHomeLauncherIfShown(); @@ -898,14 +905,6 @@ suggestion_index); } -void AppListControllerImpl::LogSearchClick( - const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) { - if (client_) - client_->LogSearchClick(result_id, suggestion_index, launched_from); -} - void AppListControllerImpl::LogSearchAbandonHistogram() { app_list::RecordSearchAbandonWithQueryLengthHistogram(GetLastQueryLength()); }
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 4395afc2..7e5d5b69 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -156,10 +156,11 @@ app_list::SearchModel* GetSearchModel() override; void StartAssistant() override; void StartSearch(const base::string16& raw_query) override; - void OpenSearchResult(const std::string& result_id, int event_flags) override; - void LogSearchClick(const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) override; + void OpenSearchResult(const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) override; void LogResultLaunchHistogram( app_list::SearchResultLaunchLocation launch_location, int suggestion_index) override;
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h index 30cb00c..0ac383a 100644 --- a/ash/app_list/app_list_view_delegate.h +++ b/ash/app_list/app_list_view_delegate.h
@@ -50,17 +50,18 @@ // box by the user. virtual void StartSearch(const base::string16& raw_query) = 0; - // Invoked to open the search result. + // Invoked to open the search result and log a click. If the result is + // represented by a SuggestedChipView or is a zero state result, + // |suggested_index| is the index of the view in the list of suggestions. + // |launched_from| values must match the LaunchedFrom enum in + // chrome/browser/ui/app_list/app_launch_event_logger.proto. |launch_type| is + // either kAppSearchResult or kSearchResult and is used to determine which + // histograms to log to. virtual void OpenSearchResult(const std::string& result_id, - int event_flags) = 0; - // Called to log a click on the search result with |result_id| located at - // position |suggestion_index|. Logged for the suggestion chip and the tile - // item view. |launched_from| values must match the LaunchedFrom enum in - // chrome/browser/ui/app_list/app_launch_event_logger.proto. - virtual void LogSearchClick( - const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) = 0; + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) = 0; // Called to log UMA metrics for the launch of an item either in the app tile // list or the search result list. The |launch_location| argument determines
diff --git a/ash/app_list/test/app_list_test_view_delegate.cc b/ash/app_list/test/app_list_test_view_delegate.cc index abd862f..7539368 100644 --- a/ash/app_list/test/app_list_test_view_delegate.cc +++ b/ash/app_list/test/app_list_test_view_delegate.cc
@@ -35,8 +35,12 @@ return search_model_.get(); } -void AppListTestViewDelegate::OpenSearchResult(const std::string& result_id, - int event_flags) { +void AppListTestViewDelegate::OpenSearchResult( + const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) { const SearchModel::SearchResults* results = search_model_->results(); for (size_t i = 0; i < results->item_count(); ++i) { if (results->GetItemAt(i)->id() == result_id) {
diff --git a/ash/app_list/test/app_list_test_view_delegate.h b/ash/app_list/test/app_list_test_view_delegate.h index 6ee59a7..597fe5f 100644 --- a/ash/app_list/test/app_list_test_view_delegate.h +++ b/ash/app_list/test/app_list_test_view_delegate.h
@@ -59,10 +59,11 @@ SearchModel* GetSearchModel() override; void StartAssistant() override {} void StartSearch(const base::string16& raw_query) override {} - void OpenSearchResult(const std::string& result_id, int event_flags) override; - void LogSearchClick(const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) override {} + void OpenSearchResult(const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) override; void LogResultLaunchHistogram( app_list::SearchResultLaunchLocation launch_location, int suggestion_index) override {}
diff --git a/ash/app_list/test/test_app_list_client.h b/ash/app_list/test/test_app_list_client.h index 679320fe..6826bf465 100644 --- a/ash/app_list/test/test_app_list_client.h +++ b/ash/app_list/test/test_app_list_client.h
@@ -25,10 +25,10 @@ // ash::mojom::AppListClient: void StartSearch(const base::string16& trimmed_query) override {} void OpenSearchResult(const std::string& result_id, - int event_flags) override {} - void LogSearchClick(const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) override {} + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) override {} void InvokeSearchResultAction(const std::string& result_id, int action_index, int event_flags) override {}
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index 241b63f..055042dd 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -962,7 +962,7 @@ } void AppsGridView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (!details.is_add && details.parent == this) { // The view being delete should not have reference in |view_model_|. CHECK_EQ(-1, view_model_.GetIndexOfView(details.child));
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h index 56a8c76d..e61a149 100644 --- a/ash/app_list/views/apps_grid_view.h +++ b/ash/app_list/views/apps_grid_view.h
@@ -182,7 +182,7 @@ bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnKeyReleased(const ui::KeyEvent& event) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; bool GetDropFormats(int* formats, std::set<ui::ClipboardFormatType>* format_types) override;
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc index 0930eac..9aa9ece 100644 --- a/ash/app_list/views/search_result_answer_card_view.cc +++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -223,7 +223,11 @@ if (result()) { RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), view_delegate_->GetSearchModel()); - view_delegate_->OpenSearchResult(result()->id(), event.flags()); + view_delegate_->OpenSearchResult( + result()->id(), event.flags(), + ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox, + ash::mojom::AppListLaunchType::kSearchResult, + -1 /* suggestion_index */); } }
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc index 03e458f..31a3bbe2 100644 --- a/ash/app_list/views/search_result_list_view.cc +++ b/ash/app_list/views/search_result_list_view.cc
@@ -228,7 +228,11 @@ view_delegate_->LogResultLaunchHistogram( SearchResultLaunchLocation::kResultList, view->get_index_in_search_result_list_view()); - view_delegate_->OpenSearchResult(view->result()->id(), event_flags); + view_delegate_->OpenSearchResult( + view->result()->id(), event_flags, + ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox, + ash::mojom::AppListLaunchType::kSearchResult, + -1 /* suggestion_index */); } }
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index cf3a116a..a3d5d88 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -18,6 +18,7 @@ #include "ash/app_list/views/search_result_list_view.h" #include "ash/app_list/views/search_result_tile_item_list_view.h" #include "ash/public/cpp/app_list/app_list_config.h" +#include "base/memory/ptr_util.h" #include "ui/chromeos/search_box/search_box_constants.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_palette.h" @@ -174,7 +175,7 @@ scroller->SetBorder(views::CreateEmptyBorder( gfx::Insets(kSearchBoxHeight + kSeparatorThickness, 0, 0, 0))); scroller->set_draw_overflow_indicator(false); - scroller->SetContents(contents_view_); + scroller->SetContents(base::WrapUnique(contents_view_)); // Setting clip height is necessary to make ScrollView take into account its // contents' size. Using zeroes doesn't prevent it from scrolling and sizing // correctly.
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 fa07d9b..121a65f 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.cc +++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -71,10 +71,11 @@ LogAppLaunch(index_in_suggestion_chip_container_); RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), view_delegate_->GetSearchModel()); - view_delegate_->OpenSearchResult(result()->id(), event.flags()); - view_delegate_->LogSearchClick( - result()->id(), index_in_suggestion_chip_container_, - ash::mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip); + view_delegate_->OpenSearchResult( + result()->id(), event.flags(), + ash::mojom::AppListLaunchedFrom::kLaunchedFromSuggestionChip, + ash::mojom::AppListLaunchType::kAppSearchResult, + index_in_suggestion_chip_container_); } void SearchResultSuggestionChipView::Layout() {
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index ca342bb2..41a7779 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -250,17 +250,7 @@ void SearchResultTileItemView::ButtonPressed(views::Button* sender, const ui::Event& event) { - if (IsSuggestedAppTile()) - LogAppLaunch(); - - RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), - view_delegate_->GetSearchModel()); - view_delegate_->OpenSearchResult(result()->id(), event.flags()); - view_delegate_->LogResultLaunchHistogram( - SearchResultLaunchLocation::kTileList, index_in_item_list_view_); - view_delegate_->LogSearchClick( - result()->id(), index_in_item_list_view_, - ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox); + ActivateResult(event.flags()); } void SearchResultTileItemView::GetAccessibleNodeData( @@ -288,14 +278,9 @@ return true; if (event.key_code() == ui::VKEY_RETURN) { - if (IsSuggestedAppTile()) - LogAppLaunch(); - RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), - view_delegate_->GetSearchModel()); - view_delegate_->OpenSearchResult(result()->id(), event.flags()); + ActivateResult(event.flags()); return true; } - return false; } @@ -403,6 +388,20 @@ } } +void SearchResultTileItemView::ActivateResult(int event_flags) { + LogAppLaunchForSuggestedApp(); + + RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), + view_delegate_->GetSearchModel()); + view_delegate_->OpenSearchResult( + result()->id(), event_flags, + ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox, + ash::mojom::AppListLaunchType::kAppSearchResult, + index_in_item_list_view_); + view_delegate_->LogResultLaunchHistogram( + SearchResultLaunchLocation::kTileList, index_in_item_list_view_); +} + void SearchResultTileItemView::SetIcon(const gfx::ImageSkia& icon) { const int icon_size = AppListConfig::instance().search_tile_icon_dimension(); gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage( @@ -499,7 +498,7 @@ return IsSuggestedAppTile() && show_in_apps_page_; } -void SearchResultTileItemView::LogAppLaunch() const { +void SearchResultTileItemView::LogAppLaunchForSuggestedApp() const { // Only log the app launch if the class is being used as a suggested app. if (!IsSuggestedAppTile()) return;
diff --git a/ash/app_list/views/search_result_tile_item_view.h b/ash/app_list/views/search_result_tile_item_view.h index c34fbfe..79ef3ff 100644 --- a/ash/app_list/views/search_result_tile_item_view.h +++ b/ash/app_list/views/search_result_tile_item_view.h
@@ -69,6 +69,9 @@ void ExecuteCommand(int command_id, int event_flags) override; private: + // Launch the result and log to various histograms. + void ActivateResult(int event_flags); + // Bound by ShowContextMenuForViewImpl(). void OnGetContextMenuModel(views::View* source, const gfx::Point& point, @@ -92,7 +95,7 @@ bool IsSuggestedAppTileShownInAppPage() const; // Records an app being launched. - void LogAppLaunch() const; + void LogAppLaunchForSuggestedApp() const; void UpdateBackgroundColor();
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc index 5b854e4..25f58db 100644 --- a/ash/assistant/assistant_interaction_controller.cc +++ b/ash/assistant/assistant_interaction_controller.cc
@@ -533,6 +533,11 @@ // earliest indication that the mic has closed. model_.SetMicState(MicState::kClosed); + // It is possible that an error Tts could be sent in addition to server Tts. + // In that case, the pending_response may have already been finalized. + if (!model_.pending_response()) + model_.SetPendingResponse(std::make_unique<AssistantResponse>()); + // Add an error message to the response. model_.pending_response()->AddUiElement( std::make_unique<AssistantTextElement>( @@ -543,6 +548,8 @@ // We have an agreement with the server that TTS will always be the last part // of an interaction to be processed. To be timely in updating UI, we use // this as an opportunity to begin processing the Assistant response. + // TODO(xiaohuic): sometimes we actually do receive additional TTS responses, + // need to properly handle those cases. OnProcessPendingResponse(); }
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc index 083a107..48f6e52 100644 --- a/ash/assistant/ui/assistant_container_view.cc +++ b/ash/assistant/ui/assistant_container_view.cc
@@ -307,7 +307,7 @@ } void AssistantContainerView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { // Do nothing. We override this method to prevent a super class implementation // from taking effect which would otherwise cause ChromeVox to read the entire // Assistant view hierarchy.
diff --git a/ash/assistant/ui/assistant_container_view.h b/ash/assistant/ui/assistant_container_view.h index 477d94a..7195240 100644 --- a/ash/assistant/ui/assistant_container_view.h +++ b/ash/assistant/ui/assistant_container_view.h
@@ -37,7 +37,7 @@ views::FocusTraversable* GetFocusTraversable() override; void ChildPreferredSizeChanged(views::View* child) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void SizeToContents() override; void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override;
diff --git a/ash/assistant/ui/assistant_notification_overlay.cc b/ash/assistant/ui/assistant_notification_overlay.cc index 8c95eb72..244062d 100644 --- a/ash/assistant/ui/assistant_notification_overlay.cc +++ b/ash/assistant/ui/assistant_notification_overlay.cc
@@ -51,7 +51,7 @@ } void AssistantNotificationOverlay::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.parent == this) PreferredSizeChanged(); }
diff --git a/ash/assistant/ui/assistant_notification_overlay.h b/ash/assistant/ui/assistant_notification_overlay.h index a48b9ac..ec393fed 100644 --- a/ash/assistant/ui/assistant_notification_overlay.h +++ b/ash/assistant/ui/assistant_notification_overlay.h
@@ -29,7 +29,7 @@ const char* GetClassName() const override; LayoutParams GetLayoutParams() const override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // AssistantUiModelObserver: void OnUiVisibilityChanged(
diff --git a/ash/assistant/ui/base/assistant_scroll_view.cc b/ash/assistant/ui/base/assistant_scroll_view.cc index 8186b1a..d7e0c86 100644 --- a/ash/assistant/ui/base/assistant_scroll_view.cc +++ b/ash/assistant/ui/base/assistant_scroll_view.cc
@@ -4,6 +4,9 @@ #include "ash/assistant/ui/base/assistant_scroll_view.h" +#include <memory> +#include <utility> + #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" namespace ash { @@ -80,9 +83,9 @@ set_draw_overflow_indicator(false); // Content view. - content_view_ = new ContentView(); - content_view_->AddObserver(this); - SetContents(content_view_); + auto content_view = std::make_unique<ContentView>(); + content_view->AddObserver(this); + content_view_ = SetContents(std::move(content_view)); // Scroll bars. horizontal_scroll_bar_ = new InvisibleScrollBar(/*horizontal=*/true);
diff --git a/ash/assistant/ui/main_stage/assistant_main_stage.cc b/ash/assistant/ui/main_stage/assistant_main_stage.cc index 3d93d288..3f3db904 100644 --- a/ash/assistant/ui/main_stage/assistant_main_stage.cc +++ b/ash/assistant/ui/main_stage/assistant_main_stage.cc
@@ -429,6 +429,9 @@ using assistant::util::CreateOpacityElement; using assistant::util::CreateTransformElement; + if (!committed_query_view_) + return; + // Clear the previously active query. OnActiveQueryCleared();
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc index 445e479d..cf312d9a 100644 --- a/ash/autoclick/autoclick_controller.cc +++ b/ash/autoclick/autoclick_controller.cc
@@ -7,7 +7,6 @@ #include "ash/accessibility/accessibility_controller.h" #include "ash/autoclick/autoclick_drag_event_rewriter.h" #include "ash/autoclick/autoclick_ring_handler.h" -#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" @@ -65,17 +64,7 @@ } AutoclickController::AutoclickController() - : enabled_(false), - event_type_(kDefaultAutoclickEventType), - revert_to_left_click_(true), - movement_threshold_(kDefaultAutoclickMovementThreshold), - tap_down_target_(nullptr), - delay_(GetDefaultAutoclickDelay()), - mouse_event_flags_(ui::EF_NONE), - anchor_location_(-kDefaultAutoclickMovementThreshold, - -kDefaultAutoclickMovementThreshold), - gesture_anchor_location_(-kDefaultAutoclickMovementThreshold, - -kDefaultAutoclickMovementThreshold), + : delay_(GetDefaultAutoclickDelay()), autoclick_ring_handler_(std::make_unique<AutoclickRingHandler>()), drag_event_rewriter_(std::make_unique<AutoclickDragEventRewriter>()) { Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource()->AddEventRewriter( @@ -147,6 +136,12 @@ UpdateRingSize(); } +void AutoclickController::SetMenuPosition( + mojom::AutoclickMenuPosition menu_position) { + menu_position_ = menu_position; + // TODO(katie): When the on-screen menu exists, update its position here. +} + void AutoclickController::CreateAutoclickRingWidget( const gfx::Point& point_in_screen) { aura::Window* target = ash::wm::GetRootWindowAt(point_in_screen);
diff --git a/ash/autoclick/autoclick_controller.h b/ash/autoclick/autoclick_controller.h index ef85ba3f..85e02473 100644 --- a/ash/autoclick/autoclick_controller.h +++ b/ash/autoclick/autoclick_controller.h
@@ -6,6 +6,7 @@ #define ASH_AUTOCLICK_AUTOCLICK_CONTROLLER_H #include "ash/ash_export.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/public/interfaces/accessibility_controller_enums.mojom.h" #include "base/macros.h" #include "base/time/time.h" @@ -56,6 +57,9 @@ // a new Autoclick event. void SetMovementThreshold(int movement_threshold); + // Sets the menu position and updates the UI. + void SetMenuPosition(mojom::AutoclickMenuPosition menu_position); + // Sets whether to revert to a left click after any other event type. void set_revert_to_left_click(bool revert_to_left_click) { revert_to_left_click_ = revert_to_left_click; @@ -89,16 +93,32 @@ // aura::WindowObserver overrides: void OnWindowDestroying(aura::Window* window) override; - bool enabled_; - mojom::AutoclickEventType event_type_; - bool revert_to_left_click_; - int movement_threshold_; + // Whether Autoclick is currently enabled. + bool enabled_ = false; + mojom::AutoclickEventType event_type_ = kDefaultAutoclickEventType; + bool revert_to_left_click_ = true; + int movement_threshold_ = kDefaultAutoclickMovementThreshold; + mojom::AutoclickMenuPosition menu_position_ = kDefaultAutoclickMenuPosition; + int mouse_event_flags_ = ui::EF_NONE; // The target window is observed by AutoclickController for the duration // of a autoclick gesture. - aura::Window* tap_down_target_; + aura::Window* tap_down_target_ = nullptr; + // The position in screen coordinates used to determine the distance the + // mouse has moved since dwell began. It is used to determine + // if move events should cancel the gesture. + gfx::Point anchor_location_ = gfx::Point(-kDefaultAutoclickMovementThreshold, + -kDefaultAutoclickMovementThreshold); + // The position in screen coodinates tracking where the autoclick gesture + // should be anchored. While the |start_gesture_timer_| is running and before + // the animation is drawn, subtle mouse movements will update the + // |gesture_anchor_location_|, so that once animation begins it can focus on + // the most recent mose point. + gfx::Point gesture_anchor_location_ = + gfx::Point(-kDefaultAutoclickMovementThreshold, + -kDefaultAutoclickMovementThreshold); + std::unique_ptr<views::Widget> widget_; base::TimeDelta delay_; - int mouse_event_flags_; // The timer that counts down from the beginning of a gesture until a click. std::unique_ptr<base::RetainingOneShotTimer> autoclick_timer_; // The timer that counts from when the user stops moving the mouse @@ -106,16 +126,6 @@ // showing up when the mouse cursor is moving quickly across the screen, // instead waiting for the mouse to begin a dwell. std::unique_ptr<base::RetainingOneShotTimer> start_gesture_timer_; - // The position in screen coordinates used to determine the distance the - // mouse has moved since dwell began. It is used to determine - // if move events should cancel the gesture. - gfx::Point anchor_location_; - // The position in screen coodinates tracking where the autoclick gesture - // should be anchored. While the |start_gesture_timer_| is running and before - // the animation is drawn, subtle mouse movements will update the - // |gesture_anchor_location_|, so that once animation begins it can focus on - // the most recent mose point. - gfx::Point gesture_anchor_location_; std::unique_ptr<AutoclickRingHandler> autoclick_ring_handler_; std::unique_ptr<AutoclickDragEventRewriter> drag_event_rewriter_;
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc index 93d7b56..9b01c8a 100644 --- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc +++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -5,6 +5,8 @@ #include "ash/components/shortcut_viewer/views/keyboard_shortcut_view.h" #include <algorithm> +#include <memory> +#include <utility> #include "ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h" #include "ash/components/shortcut_viewer/vector_icons/vector_icons.h" @@ -87,11 +89,11 @@ illustration_view->AddChildView(text); } -views::ScrollView* CreateScrollView(views::View* content_view) { +views::ScrollView* CreateScrollView(std::unique_ptr<views::View> content_view) { views::ScrollView* const scroller = new views::ScrollView(); scroller->set_draw_overflow_indicator(false); scroller->ClipHeightTo(0, 0); - scroller->SetContents(content_view); + scroller->SetContents(std::move(content_view)); return scroller; } @@ -353,23 +355,25 @@ if (current_category != category) { current_category = category; ++tab_index; - views::View* content_view = nullptr; + std::unique_ptr<views::View> content_view; // Delay constructing a KeyboardShortcutItemListView until it is needed. if (initial_category.value_or(category) == category) { - item_list_view = new KeyboardShortcutItemListView(); - content_view = item_list_view; + auto item_view = std::make_unique<KeyboardShortcutItemListView>(); + item_list_view = item_view.get(); + content_view = std::move(item_view); } else { - content_view = new views::View(); + content_view = std::make_unique<views::View>(); } // Create new tabs or update the existing tabs' contents. if (already_has_tabs) { auto* scroll_view = static_cast<views::ScrollView*>(tab_contents->child_at(tab_index)); - scroll_view->SetContents(content_view); + scroll_view->SetContents(std::move(content_view)); } else { - categories_tabbed_pane_->AddTab(GetStringForCategory(current_category), - CreateScrollView(content_view)); + categories_tabbed_pane_->AddTab( + GetStringForCategory(current_category), + CreateScrollView(std::move(content_view))); } } @@ -487,7 +491,7 @@ found_items_list_view->SetBorder(views::CreateEmptyBorder( gfx::Insets(kTopPadding, kHorizontalPadding, 0, kHorizontalPadding))); search_container_content_view = - CreateScrollView(found_items_list_view.release()); + CreateScrollView(std::move(found_items_list_view)); } replacement_strings.emplace_back(search_query); search_box_view_->SetAccessibleValue(l10n_util::GetStringFUTF16(
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc index a1e6327d..9cb28af3 100644 --- a/ash/frame/caption_buttons/frame_size_button_unittest.cc +++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -54,7 +54,7 @@ } void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (details.is_add && details.child == this) { caption_button_container_ = new FrameCaptionButtonContainerView( GetWidget(), &caption_controller_);
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index 491f158..6ff8ee9 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -25,6 +25,7 @@ #include "ash/shell.h" #include "ash/wallpaper/wallpaper_controller.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" @@ -746,7 +747,7 @@ auto make_scroll = [](views::View* content, int height) -> views::View* { views::ScrollView* scroll = views::ScrollView::CreateScrollViewWithBorder(); scroll->SetPreferredSize(gfx::Size(600, height)); - scroll->SetContents(content); + scroll->SetContents(base::WrapUnique(content)); scroll->SetBackgroundColor(SK_ColorTRANSPARENT); scroll->SetVerticalScrollBar(new views::OverlayScrollBar(false)); scroll->SetHorizontalScrollBar(new views::OverlayScrollBar(true));
diff --git a/ash/login/ui/login_menu_view.cc b/ash/login/ui/login_menu_view.cc index d4ec5c0..ffdc32e9 100644 --- a/ash/login/ui/login_menu_view.cc +++ b/ash/login/ui/login_menu_view.cc
@@ -4,6 +4,9 @@ #include "ash/login/ui/login_menu_view.h" +#include <memory> +#include <utility> + #include "ash/login/ui/hover_notifier.h" #include "ash/login/ui/non_accessible_view.h" #include "base/bind.h" @@ -139,8 +142,8 @@ std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); box_layout->SetFlexForView(scroller_, 1); - contents_ = new NonAccessibleView(); - views::BoxLayout* layout = contents_->SetLayoutManager( + auto contents = std::make_unique<NonAccessibleView>(); + views::BoxLayout* layout = contents->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); layout->SetDefaultFlex(1); layout->set_minimum_cross_axis_size(kMenuItemWidthDp); @@ -149,14 +152,14 @@ for (size_t i = 0; i < items.size(); i++) { const Item& item = items[i]; - contents_->AddChildView(new MenuItemView( + contents->AddChildView(new MenuItemView( item, base::BindRepeating(&LoginMenuView::OnHighLightChange, base::Unretained(this), i))); if (item.selected) selected_index_ = i; } - scroller_->SetContents(contents_); + contents_ = scroller_->SetContents(std::move(contents)); scroller_->SetVerticalScrollBar(new LoginScrollBar()); }
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc index d4281cd..5c1a14bb 100644 --- a/ash/login/ui/scrollable_users_list_view.cc +++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -5,6 +5,7 @@ #include "ash/login/ui/scrollable_users_list_view.h" #include <limits> +#include <memory> #include "ash/login/ui/login_display_style.h" #include "ash/login/ui/login_user_view.h" @@ -324,13 +325,13 @@ // // |user_view_host_| cannot be set as |contents()| directly because it needs // to be vertically centered when non-scrollable. - auto* ensure_min_height = new EnsureMinHeightView(); + auto ensure_min_height = std::make_unique<EnsureMinHeightView>(); ensure_min_height ->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)) ->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); ensure_min_height->AddChildView(user_view_host_); - SetContents(ensure_min_height); + SetContents(std::move(ensure_min_height)); SetBackgroundColor(SK_ColorTRANSPARENT); set_draw_overflow_indicator(false);
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index d7f4372..51c7aff 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -114,8 +114,6 @@ "touch_uma.h", "wallpaper_types.h", "window_animation_types.h", - "window_pin_type.cc", - "window_pin_type.h", "window_properties.cc", "window_properties.h", "window_state_type.cc",
diff --git a/ash/public/cpp/ash_constants.h b/ash/public/cpp/ash_constants.h index d5018b44..a4376603 100644 --- a/ash/public/cpp/ash_constants.h +++ b/ash/public/cpp/ash_constants.h
@@ -47,6 +47,10 @@ // a new autoclick. constexpr int kDefaultAutoclickMovementThreshold = 20; +// The default automatic click menu position. +constexpr mojom::AutoclickMenuPosition kDefaultAutoclickMenuPosition = + mojom::AutoclickMenuPosition::kBottomRight; + // The default frame color. constexpr SkColor kDefaultFrameColor = SkColorSetRGB(0xFD, 0xFE, 0xFF);
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc index f845d24f..8b20938 100644 --- a/ash/public/cpp/ash_pref_names.cc +++ b/ash/public/cpp/ash_pref_names.cc
@@ -61,6 +61,9 @@ // a new autoclick. const char kAccessibilityAutoclickMovementThreshold[] = "settings.a11y.autoclick_movement_threshold"; +// The Autoclick menu position on the screen, an mojom::AutoclickMenuPosition. +const char kAccessibilityAutoclickMenuPosition[] = + "settings.a11y.autoclick_menu_position"; // A boolean pref which determines whether caret highlighting is enabled. const char kAccessibilityCaretHighlightEnabled[] = "settings.a11y.caret_highlight";
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h index 5e142f7..69cc8e7 100644 --- a/ash/public/cpp/ash_pref_names.h +++ b/ash/public/cpp/ash_pref_names.h
@@ -26,6 +26,7 @@ ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickEventType[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickRevertToLeftClick[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickMovementThreshold[]; +ASH_PUBLIC_EXPORT extern const char kAccessibilityAutoclickMenuPosition[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityCaretHighlightEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityCursorHighlightEnabled[]; ASH_PUBLIC_EXPORT extern const char kAccessibilityFocusHighlightEnabled[];
diff --git a/ash/public/cpp/window_pin_type.cc b/ash/public/cpp/window_pin_type.cc deleted file mode 100644 index 677652d4..0000000 --- a/ash/public/cpp/window_pin_type.cc +++ /dev/null
@@ -1,29 +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. - -#include "ash/public/cpp/window_pin_type.h" - -#include "ash/public/cpp/window_properties.h" -#include "ash/public/interfaces/window_pin_type.mojom.h" -#include "ui/aura/window.h" -#include "ui/base/base_window.h" - -namespace ash { - -bool IsValidWindowPinType(int64_t value) { - return value == int64_t(ash::mojom::WindowPinType::NONE) || - value == int64_t(ash::mojom::WindowPinType::PINNED) || - value == int64_t(ash::mojom::WindowPinType::TRUSTED_PINNED); -} - -bool IsWindowTrustedPinned(const aura::Window* window) { - mojom::WindowPinType type = window->GetProperty(kWindowPinTypeKey); - return type == mojom::WindowPinType::TRUSTED_PINNED; -} - -bool IsWindowTrustedPinned(const ui::BaseWindow* window) { - return IsWindowTrustedPinned(window->GetNativeWindow()); -} - -} // namespace ash
diff --git a/ash/public/cpp/window_pin_type.h b/ash/public/cpp/window_pin_type.h deleted file mode 100644 index 8d316fa..0000000 --- a/ash/public/cpp/window_pin_type.h +++ /dev/null
@@ -1,30 +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 ASH_PUBLIC_CPP_WINDOW_PIN_TYPE_H_ -#define ASH_PUBLIC_CPP_WINDOW_PIN_TYPE_H_ - -#include <cstdint> - -#include "ash/public/cpp/ash_public_export.h" - -namespace aura { -class Window; -} - -namespace ui { -class BaseWindow; -} - -namespace ash { - -ASH_PUBLIC_EXPORT bool IsValidWindowPinType(int64_t value); - -ASH_PUBLIC_EXPORT bool IsWindowTrustedPinned(const aura::Window* window); - -ASH_PUBLIC_EXPORT bool IsWindowTrustedPinned(const ui::BaseWindow* window); - -} // namespace ash - -#endif // ASH_PUBLIC_CPP_WINDOW_PIN_TYPE_H_
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc index 976a2c1..55e25691 100644 --- a/ash/public/cpp/window_properties.cc +++ b/ash/public/cpp/window_properties.cc
@@ -7,7 +7,6 @@ #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/public/interfaces/window_properties.mojom.h" @@ -39,6 +38,12 @@ value == wm::ANIMATE_BOTH || value == wm::ANIMATE_NONE; } +bool IsValidWindowPinType(int64_t value) { + return value == static_cast<int64_t>(mojom::WindowPinType::NONE) || + value == static_cast<int64_t>(mojom::WindowPinType::PINNED) || + value == static_cast<int64_t>(mojom::WindowPinType::TRUSTED_PINNED); +} + } // namespace void RegisterWindowProperties(aura::PropertyConverter* property_converter) {
diff --git a/ash/public/interfaces/accessibility_controller_enums.mojom b/ash/public/interfaces/accessibility_controller_enums.mojom index 696c7a9..6acf46a 100644 --- a/ash/public/interfaces/accessibility_controller_enums.mojom +++ b/ash/public/interfaces/accessibility_controller_enums.mojom
@@ -78,11 +78,10 @@ kSelectToSpeakStateSpeaking, }; -// The type of mouse event the dwell control feature should perform when +// The type of mouse event the Automatic Clicks feature should perform when // dwelling. These values are written to prefs and correspond to // AutoclickActionType in enums.xml, so should not be changed. New values // should be added at the end. -[Extensible] enum AutoclickEventType { // Perform a left click. kLeftClick, @@ -102,3 +101,20 @@ // TODO(katie): Add scroll. }; + +// The Automatic Clicks feature's on-screen menu display location. These values +// are written to prefs so they should not be changed. New values should be +// added at the end. +enum AutoclickMenuPosition { + // The bottom right of the screen. + kBottomRight, + + // The bottom left of the screen. + kBottomLeft, + + // The top left of the screen. + kTopLeft, + + // The top right of the screen. + kTopRight, +};
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom index b232dc9f..af2139c4 100644 --- a/ash/public/interfaces/app_list.mojom +++ b/ash/public/interfaces/app_list.mojom
@@ -101,7 +101,7 @@ kStatusSyncing, // Syncing apps or installing synced apps. }; -// The UI component the user launched the app from. Must match +// The UI component the user launched the search result from. Must match // chrome/browser/ui/app_list/app_launch_event_logger.proto. enum AppListLaunchedFrom { kLaunchedFromGrid = 1, @@ -110,6 +110,15 @@ kLaunchedFromSearchBox, }; +// The UI representation of the search result. Currently all search results +// that are not apps (OminboxResult, LauncherSearcResult, etc.) are grouped +// into kSearchResult. Meanwhile SearchResultTileItemView (shown in zero state) +// and suggested chips are considered kAppSearchResult. +enum AppListLaunchType { + kSearchResult = 0, + kAppSearchResult, +}; + // How the result should be displayed. Do not change the order of these as // they are used for metrics. enum SearchResultDisplayType { @@ -323,17 +332,17 @@ // Triggers a search query. // |trimmed_query|: the trimmed input texts from the search text field. StartSearch(mojo_base.mojom.String16 trimmed_query); - // Opens a search result when its view is clicked or pressed. + // Opens a search result and logs to metrics when its view is clicked or + // pressed. // |result_id|: the id of the search result the user wants to open. - OpenSearchResult(string result_id, int32 event_flags); - // Logs a click on the search result. - // |result_id|: the id of the search result that was clicked on. - // |suggestion_index|: the position of the result in the suggestion chip. - // |launched_from|: where the app was launched. - LogSearchClick( - string result_id, - int32 suggestion_index, - AppListLaunchedFrom launched_from); + // |launched_from|: where the result was launched. + // |launch_type|: how the result is represented in the UI. + // |suggestion_index|: the position of the result as a suggestion chip in + // the AppsGridView or the position of the result in the zero state search + // page. + OpenSearchResult(string result_id, int32 event_flags, + AppListLaunchedFrom launched_from, + AppListLaunchType launch_type, int32 suggestion_index); // Invokes a custom action on a result with |result_id|. // |action_index| corresponds to the index of an action on the search result, // for example, installing. They are stored in SearchResult::actions_.
diff --git a/ash/public/interfaces/shell_test_api.test-mojom b/ash/public/interfaces/shell_test_api.test-mojom index 3dbd259..4b17732 100644 --- a/ash/public/interfaces/shell_test_api.test-mojom +++ b/ash/public/interfaces/shell_test_api.test-mojom
@@ -33,4 +33,9 @@ // Set the minimum velocity to cause fling gesture. SetMinFlingVelocity(float velocity); + + // Runs the callback when the WindowTreeHost of the primary display is no + // longer holding pointer events. See + // |aura::WindowTreeHost::holding_pointer_moves_| for details. + WaitForNoPointerHoldLock() => (); };
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc index 3d37e025..28af351 100644 --- a/ash/shelf/app_list_button.cc +++ b/ash/shelf/app_list_button.cc
@@ -188,19 +188,6 @@ return kViewClassName; } -std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple() - const { - const int app_list_button_radius = ShelfConstants::control_border_radius(); - gfx::Point center = GetCenterPoint(); - gfx::Rect bounds(center.x() - app_list_button_radius, - center.y() - app_list_button_radius, - 2 * app_list_button_radius, 2 * app_list_button_radius); - return std::make_unique<views::FloodFillInkDropRipple>( - size(), GetLocalBounds().InsetsFrom(bounds), - GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(), - ink_drop_visible_opacity()); -} - void AppListButton::PaintButtonContents(gfx::Canvas* canvas) { gfx::PointF circle_center(GetCenterPoint());
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h index c92b86c..c698120 100644 --- a/ash/shelf/app_list_button.h +++ b/ash/shelf/app_list_button.h
@@ -50,7 +50,6 @@ protected: // views::Button: - std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; void PaintButtonContents(gfx::Canvas* canvas) override; private:
diff --git a/ash/shelf/app_list_button_unittest.cc b/ash/shelf/app_list_button_unittest.cc index fa0bbb0..f94e57c 100644 --- a/ash/shelf/app_list_button_unittest.cc +++ b/ash/shelf/app_list_button_unittest.cc
@@ -16,6 +16,7 @@ #include "ash/root_window_controller.h" #include "ash/session/session_controller.h" #include "ash/shelf/shelf.h" +#include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_view.h" #include "ash/shelf/shelf_view_test_api.h" #include "ash/shell.h" @@ -153,7 +154,7 @@ Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); test_api.RunMessageLoopUntilAnimationsDone(); - EXPECT_EQ(0, app_list_button()->bounds().x()); + EXPECT_EQ(ShelfConstants::button_spacing(), app_list_button()->bounds().x()); } class VoiceInteractionAppListButtonTest : public AppListButtonTest {
diff --git a/ash/shelf/overflow_bubble_view.cc b/ash/shelf/overflow_bubble_view.cc index d7c242f..487773d 100644 --- a/ash/shelf/overflow_bubble_view.cc +++ b/ash/shelf/overflow_bubble_view.cc
@@ -179,6 +179,8 @@ gfx::Rect OverflowBubbleView::GetBubbleBounds() { const gfx::Size content_size = GetPreferredSize(); const gfx::Rect anchor_rect = GetAnchorRect(); + const int distance_to_overflow_button = + kDistanceToMainShelf + (kShelfSize - kShelfControlSize) / 2; gfx::Rect monitor_rect = display::Screen::GetScreen() ->GetDisplayNearestPoint(anchor_rect.CenterPoint()) @@ -191,7 +193,7 @@ base::i18n::IsRTL() ? anchor_rect.x() - kEndPadding : anchor_rect.right() - content_size.width() - kEndPadding, - anchor_rect.y() - kDistanceToMainShelf - content_size.height(), + anchor_rect.y() - distance_to_overflow_button - content_size.height(), content_size.width() + 2 * kEndPadding, content_size.height()); if (bounds.x() < monitor_rect.x()) bounds.Offset(monitor_rect.x() - bounds.x(), 0); @@ -203,9 +205,10 @@ 0, anchor_rect.bottom() - content_size.height() - kEndPadding, content_size.width(), content_size.height() + 2 * kEndPadding); if (shelf_->alignment() == SHELF_ALIGNMENT_LEFT) - bounds.set_x(anchor_rect.right() + kDistanceToMainShelf); + bounds.set_x(anchor_rect.right() + distance_to_overflow_button); else - bounds.set_x(anchor_rect.x() - kDistanceToMainShelf - content_size.width()); + bounds.set_x(anchor_rect.x() - distance_to_overflow_button - + content_size.width()); if (bounds.y() < monitor_rect.y()) bounds.Offset(0, monitor_rect.y() - bounds.y()); if (bounds.bottom() > monitor_rect.bottom())
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc index 0143fb8..2c28903 100644 --- a/ash/shelf/shelf_control_button.cc +++ b/ash/shelf/shelf_control_button.cc
@@ -4,6 +4,7 @@ #include "ash/shelf/shelf_control_button.h" +#include "ash/public/cpp/ash_constants.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shelf/ink_drop_button_listener.h" #include "ash/shelf/shelf.h" @@ -15,6 +16,7 @@ #include "ui/views/animation/flood_fill_ink_drop_ripple.h" #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/animation/ink_drop_mask.h" +#include "ui/views/view_class_properties.h" #include "ui/views/widget/widget.h" namespace ash { @@ -22,21 +24,26 @@ ShelfControlButton::ShelfControlButton(ShelfView* shelf_view) : ShelfButton(shelf_view), shelf_(shelf_view->shelf()) { set_has_ink_drop_action_on_click(true); - SetSize(gfx::Size(kShelfControlSize, kShelfControlSize)); + + SetInstallFocusRingOnFocus(true); + focus_ring()->SetColor(kFocusBorderColor); + SetFocusPainter(nullptr); } ShelfControlButton::~ShelfControlButton() = default; gfx::Point ShelfControlButton::GetCenterPoint() const { - return gfx::Point(width() / 2.f, width() / 2.f); + return gfx::Point(width() / 2.f, height() / 2.f); } std::unique_ptr<views::InkDropRipple> ShelfControlButton::CreateInkDropRipple() const { + const int button_radius = ShelfConstants::control_border_radius(); + gfx::Point center = GetCenterPoint(); + gfx::Rect bounds(center.x() - button_radius, center.y() - button_radius, + 2 * button_radius, 2 * button_radius); return std::make_unique<views::FloodFillInkDropRipple>( - size(), - gfx::Insets(ShelfConstants::button_size() / 2 - - ShelfConstants::control_border_radius()), + size(), GetLocalBounds().InsetsFrom(bounds), GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(), ink_drop_visible_opacity()); } @@ -51,21 +58,24 @@ return "ash/ShelfControlButton"; } -gfx::Rect ShelfControlButton::CalculateButtonBounds() const { - ShelfAlignment alignment = shelf_->alignment(); - gfx::Rect content_bounds = GetContentsBounds(); - // Align the button to the top of a bottom-aligned shelf, to the right edge - // a left-aligned shelf, and to the left edge of a right-aligned shelf. - const int inset = (ShelfConstants::shelf_size() - kShelfControlSize) / 2; - const int x = alignment == SHELF_ALIGNMENT_LEFT - ? content_bounds.right() - inset - kShelfControlSize - : content_bounds.x() + inset; - return gfx::Rect(x, content_bounds.y() + inset, kShelfControlSize, - kShelfControlSize); +void ShelfControlButton::PaintButtonContents(gfx::Canvas* canvas) { + PaintBackground(canvas, GetContentsBounds()); } -void ShelfControlButton::PaintButtonContents(gfx::Canvas* canvas) { - PaintBackground(canvas, CalculateButtonBounds()); +void ShelfControlButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { + const int border_radius = ShelfConstants::control_border_radius(); + // Some control buttons have a slightly larger size to fill the shelf and + // maximize the click target, but we still want their "visual" size to be + // the same, so we find the center point and draw a square around that. + const gfx::Point center = GetCenterPoint(); + const int half_size = kShelfControlSize / 2; + const gfx::Rect visual_size(center.x() - half_size, center.y() - half_size, + kShelfControlSize, kShelfControlSize); + auto path = std::make_unique<SkPath>(); + path->addRoundRect(gfx::RectToSkRect(visual_size), border_radius, + border_radius); + SetProperty(views::kHighlightPathKey, path.release()); + ShelfButton::OnBoundsChanged(previous_bounds); } void ShelfControlButton::PaintBackground(gfx::Canvas* canvas,
diff --git a/ash/shelf/shelf_control_button.h b/ash/shelf/shelf_control_button.h index ed1055c..2008b63 100644 --- a/ash/shelf/shelf_control_button.h +++ b/ash/shelf/shelf_control_button.h
@@ -33,13 +33,13 @@ std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; const char* GetClassName() const override; + // views::View + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + void PaintBackground(gfx::Canvas* canvas, const gfx::Rect& bounds); void PaintButtonContents(gfx::Canvas* canvas) override; private: - // Calculates the bounds of the control button based on the shelf alignment. - gfx::Rect CalculateButtonBounds() const; - Shelf* shelf_; DISALLOW_COPY_AND_ASSIGN(ShelfControlButton);
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 97e4f4e9..af800a3 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -247,43 +247,6 @@ rect.height())); } -gfx::Size ShelfLayoutManager::GetPreferredSize() { - TargetBounds target_bounds; - CalculateTargetBoundsAndUpdateWorkArea(&target_bounds); - return target_bounds.shelf_bounds.size(); -} - -void ShelfLayoutManager::LayoutShelfAndUpdateBounds() { - TargetBounds target_bounds; - CalculateTargetBoundsAndUpdateWorkArea(&target_bounds); - UpdateBoundsAndOpacity(target_bounds, false, nullptr); - - // Update insets in ShelfWindowTargeter when shelf bounds change. - for (auto& observer : observers_) - observer.WillChangeVisibilityState(visibility_state()); -} - -void ShelfLayoutManager::LayoutShelf() { - // The ShelfWidget may be partially closed (no native widget) during shutdown - // so skip layout. - if (in_shutdown_) - return; - - LayoutShelfAndUpdateBounds(); -} - -ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { - switch (shelf_->auto_hide_behavior()) { - case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: - return SHELF_AUTO_HIDE; - case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: - return SHELF_VISIBLE; - case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: - return SHELF_HIDDEN; - } - return SHELF_VISIBLE; -} - void ShelfLayoutManager::UpdateVisibilityState() { // Bail out early after shelf is destroyed. aura::Window* shelf_window = shelf_widget_->GetNativeWindow(); @@ -457,27 +420,6 @@ return false; } -bool ShelfLayoutManager::IsDraggingWindowFromTopOrCaptionArea() const { - // Currently dragging maximized or fullscreen window from the top or the - // caption area is only allowed in tablet mode. - if (!IsTabletModeEnabled()) - return false; - - // TODO(minch): Check active window directly if removed search field - // in overview mode. http://crbug.com/866679 - auto windows = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); - for (auto* window : windows) { - wm::WindowState* window_state = wm::GetWindowState(window); - if (window_state && window_state->is_dragged() && - (window_state->IsMaximized() || window_state->IsFullscreen()) && - (window_state->drag_details()->window_component == HTCLIENT || - window_state->drag_details()->window_component == HTCAPTION)) { - return true; - } - } - return false; -} - ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const { if (state_.pre_lock_screen_animation_active) return SHELF_BACKGROUND_DEFAULT; @@ -540,7 +482,7 @@ } bool ShelfLayoutManager::ShouldBlurShelfBackground() { - return IsBackgroundBlurEnabled() && + return is_background_blur_enabled_ && shelf_background_type_ == SHELF_BACKGROUND_DEFAULT && state_.session_state == session_manager::SessionState::ACTIVE; } @@ -806,6 +748,37 @@ } } +ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() { + switch (shelf_->auto_hide_behavior()) { + case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS: + return SHELF_AUTO_HIDE; + case SHELF_AUTO_HIDE_BEHAVIOR_NEVER: + return SHELF_VISIBLE; + case SHELF_AUTO_HIDE_ALWAYS_HIDDEN: + return SHELF_HIDDEN; + } + return SHELF_VISIBLE; +} + +void ShelfLayoutManager::LayoutShelfAndUpdateBounds() { + TargetBounds target_bounds; + CalculateTargetBoundsAndUpdateWorkArea(&target_bounds); + UpdateBoundsAndOpacity(target_bounds, false, nullptr); + + // Update insets in ShelfWindowTargeter when shelf bounds change. + for (auto& observer : observers_) + observer.WillChangeVisibilityState(visibility_state()); +} + +void ShelfLayoutManager::LayoutShelf() { + // The ShelfWidget may be partially closed (no native widget) during shutdown + // so skip layout. + if (in_shutdown_) + return; + + LayoutShelfAndUpdateBounds(); +} + void ShelfLayoutManager::UpdateBoundsAndOpacity( const TargetBounds& target_bounds, bool animate, @@ -897,6 +870,27 @@ return !keyboard_displaced_bounds_.IsEmpty(); } +bool ShelfLayoutManager::IsDraggingWindowFromTopOrCaptionArea() const { + // Currently dragging maximized or fullscreen window from the top or the + // caption area is only allowed in tablet mode. + if (!IsTabletModeEnabled()) + return false; + + // TODO(minch): Check active window directly if removed search field + // in overview mode. http://crbug.com/866679 + auto windows = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + for (auto* window : windows) { + wm::WindowState* window_state = wm::GetWindowState(window); + if (window_state && window_state->is_dragged() && + (window_state->IsMaximized() || window_state->IsFullscreen()) && + (window_state->drag_details()->window_component == HTCLIENT || + window_state->drag_details()->window_component == HTCAPTION)) { + return true; + } + } + return false; +} + void ShelfLayoutManager::StopAnimating() { GetLayer(shelf_widget_)->GetAnimator()->StopAnimating(); GetLayer(shelf_widget_->status_area_widget())->GetAnimator()->StopAnimating();
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index ee2662f..c64bfe4 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -77,20 +77,10 @@ // Returns the ideal bounds of the shelf assuming it is visible. gfx::Rect GetIdealBounds() const; - // Returns the preferred size of the shelf for the target visibility state. - gfx::Size GetPreferredSize(); - - // Stops any animations and sets the bounds of the shelf and status widgets. - void LayoutShelfAndUpdateBounds(); - // Stops any animations, sets the bounds of the shelf and status widgets, and // changes the work area void LayoutShelf(); - // Returns shelf visibility state based on current value of auto hide - // behavior setting. - ShelfVisibilityState CalculateShelfVisibility(); - // Updates the visibility state. void UpdateVisibilityState(); @@ -113,11 +103,6 @@ // be processed any further, false otherwise. bool ProcessGestureEvent(const ui::GestureEvent& event_in_screen); - // Returns true if a maximized or fullscreen window is being dragged from the - // top of the display or from the caption area. Note currently for this case - // it's only allowed in tablet mode, not in laptop mode. - bool IsDraggingWindowFromTopOrCaptionArea() const; - // Returns how the shelf background should be painted. ShelfBackgroundType GetShelfBackgroundType() const; @@ -206,10 +191,6 @@ ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } int accessibility_panel_height() const { return accessibility_panel_height_; } int docked_magnifier_height() const { return docked_magnifier_height_; } - ShelfWidget* shelf_widget() { return shelf_widget_; } - - // Returns whether background blur is enabled. - bool IsBackgroundBlurEnabled() { return is_background_blur_enabled_; } // TODO(harrym|oshima): These templates will be moved to a new Shelf class. // A helper function for choosing values specific to a shelf alignment. @@ -279,6 +260,13 @@ // Sets the visibility of the shelf to |state|. void SetState(ShelfVisibilityState visibility_state); + // Returns shelf visibility state based on current value of auto hide + // behavior setting. + ShelfVisibilityState CalculateShelfVisibility(); + + // Stops any animations and sets the bounds of the shelf and status widgets. + void LayoutShelfAndUpdateBounds(); + // Updates the bounds and opacity of the shelf and status widgets. // If |observer| is specified, it will be called back when the animations, if // any, are complete. @@ -289,6 +277,11 @@ // Returns whether the virtual keyboard is currently being shown. bool IsKeyboardShown() const; + // Returns true if a maximized or fullscreen window is being dragged from the + // top of the display or from the caption area. Note currently for this case + // it's only allowed in tablet mode, not in laptop mode. + bool IsDraggingWindowFromTopOrCaptionArea() const; + // Stops any animations and progresses them to the end. void StopAnimating();
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index c8b1dd6..87be8b8 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -89,8 +89,8 @@ constexpr int kSeparatorSize = 20; constexpr int kSeparatorThickness = 1; -// The margin between the app list button and the first shelf item. -constexpr int kAppListButtonMargin = 32; +// The margin on either side of the group of app icons. +constexpr int kAppIconGroupMargin = 16; // White with ~20% opacity. constexpr SkColor kSeparatorColor = SkColorSetARGB(0x32, 0xFF, 0xFF, 0xFF); @@ -518,8 +518,7 @@ } gfx::Size ShelfView::CalculatePreferredSize() const { - gfx::Rect overflow_bounds; - CalculateIdealBounds(&overflow_bounds); + CalculateIdealBounds(); int last_button_index = last_visible_index_; if (!is_overflow_mode() && overflow_button_ && overflow_button_->visible()) @@ -1060,12 +1059,11 @@ return; } - gfx::Rect overflow_bounds; - CalculateIdealBounds(&overflow_bounds); + CalculateIdealBounds(); views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); - overflow_button_->SetBoundsRect(overflow_bounds); UpdateBackButton(); LayoutAppListAndBackButtonHighlight(); + LayoutOverflowButton(); UpdateVisibleShelfItemBoundsUnion(); } @@ -1083,17 +1081,24 @@ return -1; } -int ShelfView::GetDimensionOfCenteredShelfItems() const { +int ShelfView::GetDimensionOfAppIcons(int max_size) const { int size = 0; - int added_items = 0; - for (ShelfItem item : model_->items()) { - if (item.type == TYPE_PINNED_APP || item.type == TYPE_APP || - item.type == TYPE_BROWSER_SHORTCUT) { - size += ShelfConstants::button_size(); - added_items++; + for (int i = kAppListButtonIndex + 1; i < view_model_->view_size(); ++i) { + int new_size = size; + new_size += ShelfConstants::button_size(); + if (i > kAppListButtonIndex + 1) { + // TODO(manucornet): If one of the displayed items is the overflow + // button, we are overestimating the dimension a tiny bit because + // control buttons are smaller than app buttons. But taking this into + // account is a little tricky because at this stage we don't know whether + // we are overflowing. Fix this and add tests to check for perfect + // centering when the overflow button is shown. + new_size += ShelfConstants::button_spacing(); } + if (new_size > max_size) + return size; + size = new_size; } - size += (added_items - 1) * ShelfConstants::button_spacing(); return size; } @@ -1138,13 +1143,17 @@ back_and_app_list_background_size)); } -void ShelfView::CalculateIdealBounds(gfx::Rect* overflow_bounds) const { +void ShelfView::CalculateIdealBounds() const { DCHECK(model_->item_count() == view_model_->view_size()); const int button_spacing = ShelfConstants::button_spacing(); - const int button_size = ShelfConstants::button_size(); - const int available_size = shelf_->PrimaryAxisValue(width(), height()); + // Size occupied by the app list button and back button plus all appropriate + // margins is not available for actual app icons. + const int available_size_for_app_icons = + available_size - kShelfButtonSpacing - + (IsTabletModeEnabled() ? 2 : 1) * kShelfControlSize - + 2 * kAppIconGroupMargin; const int separator_index = GetSeparatorIndex(); const bool virtual_keyboard_visible = Shell::Get()->system_tray_model()->virtual_keyboard()->visible(); @@ -1155,13 +1164,17 @@ !virtual_keyboard_visible); int app_list_button_position; - int x = 0; - int y = 0; - - int w = shelf_->PrimaryAxisValue(button_size, width()); - int h = shelf_->PrimaryAxisValue(height(), button_size); + int x = shelf_->PrimaryAxisValue(button_spacing, 0); + int y = shelf_->PrimaryAxisValue(0, button_spacing); for (int i = 0; i < view_model_->view_size(); ++i) { + // "Primary" as in "same direction as the shelf's direction". The + // "secondary" (orthogonal) size is always the full shelf to maximize click + // targets even for control buttons. + const int size_primary = + (i <= kAppListButtonIndex) ? kShelfControlSize : kShelfButtonSize; + const int size_secondary = kShelfButtonSize; + if (i < first_visible_index_) { // This happens for the overflow view. view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0)); @@ -1169,19 +1182,41 @@ } if (i == kAppListButtonIndex + 1) { // Start centering after we've laid out the app list button. - // Center the shelf items on the whole shelf, including the status - // area widget. - int centered_shelf_items_size = GetDimensionOfCenteredShelfItems(); + // Now there are two possibilities. Either all the apps fit when centered + // on the whole screen width, in which case we do that. Or, when space + // becomes a little tight (which happens especially when the status area + // is wider because of extra panels), we center apps according to the + // available space on the shelf (subtracting what's already allocated to + // the app list button). + + int app_icons_size = GetDimensionOfAppIcons(available_size_for_app_icons); StatusAreaWidget* status_widget = shelf_widget_->status_area_widget(); - int status_widget_size = + const int status_widget_size = status_widget ? shelf_->PrimaryAxisValue( status_widget->GetWindowBoundsInScreen().width(), status_widget->GetWindowBoundsInScreen().height()) : 0; - int padding_for_centering = - (available_size + status_widget_size - centered_shelf_items_size) / 2; + const int screen_size = available_size + status_widget_size; + + int padding_for_centering = 0; + // An easy way to check whether the apps fit at the exact center of the + // screen is to imagine that we have another status widget on the + // other side (the status widget is always bigger than the app list + // button plus the back button if applicable) and see if the apps + // can fit in the middle. + if (app_icons_size + 2 * status_widget_size + 2 * kAppIconGroupMargin < + screen_size) { + padding_for_centering = (screen_size - app_icons_size) / 2; + } else { + padding_for_centering = + kShelfButtonSpacing + + (IsTabletModeEnabled() ? 2 : 1) * kShelfControlSize + + kAppIconGroupMargin + + (available_size_for_app_icons - app_icons_size) / 2; + } + if (padding_for_centering > - app_list_button_position + kAppListButtonMargin) { + app_list_button_position + kAppIconGroupMargin) { // Only shift buttons to the right, never let them interfere with the // left-aligned system buttons. x = shelf_->PrimaryAxisValue(padding_for_centering, 0); @@ -1189,30 +1224,26 @@ } } - view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h)); + view_model_->set_ideal_bounds( + i, + gfx::Rect(x, y, shelf_->PrimaryAxisValue(size_primary, size_secondary), + shelf_->PrimaryAxisValue(size_secondary, size_primary))); + // If not in tablet mode do not increase |x| or |y|. Instead just let the // next item (app list button) cover the back button, which will have // opacity 0 anyways. if (i == kBackButtonIndex && !IsTabletModeEnabled()) continue; - // There is no spacing between the first two elements. Do not worry about y - // since the back button only appears in tablet mode, which forces the shelf - // to be bottom aligned. - x = shelf_->PrimaryAxisValue(x + w + (i == 0 ? 0 : button_spacing), x); - y = shelf_->PrimaryAxisValue(y, y + h + button_spacing); - - // In the new UI, padding between the back & app list buttons is smaller - // than between all other shelf items. - if (i == kBackButtonIndex) - x -= button_spacing; + x = shelf_->PrimaryAxisValue(x + size_primary + button_spacing, x); + y = shelf_->PrimaryAxisValue(y, y + size_primary + button_spacing); if (i == kAppListButtonIndex) { app_list_button_position = shelf_->PrimaryAxisValue(x, y); // A larger minimum padding after the app list button is required: // increment with the necessary extra amount. - x += shelf_->PrimaryAxisValue(kAppListButtonMargin - button_spacing, 0); - y += shelf_->PrimaryAxisValue(0, kAppListButtonMargin - button_spacing); + x += shelf_->PrimaryAxisValue(kAppIconGroupMargin - button_spacing, 0); + y += shelf_->PrimaryAxisValue(0, kAppIconGroupMargin - button_spacing); } if (i == separator_index) { @@ -1237,11 +1268,8 @@ const_cast<ShelfView*>(this)->UpdateAllButtonsVisibilityInOverflowMode(); return; } - - overflow_bounds->set_size(gfx::Size(shelf_->PrimaryAxisValue(w, width()), - shelf_->PrimaryAxisValue(height(), h))); last_visible_index_ = - IndexOfLastItemThatFitsSize(available_size - button_spacing); + IndexOfLastItemThatFitsSize(available_size - kAppIconGroupMargin); bool show_overflow = last_visible_index_ < model_->item_count() - 1; // In the main shelf, the first visible index is either the back button (in @@ -1263,8 +1291,8 @@ // FinalizeRipOffDrag(). if (dragged_off_shelf_ && view_model_->view_at(i) == drag_view_) continue; - // If virtual keyboard is visible, only back button and app list button are - // shown. + // If the virtual keyboard is visible, only the back button and the app + // list button are shown. const bool is_visible_item = !virtual_keyboard_visible || i == kBackButtonIndex || i == kAppListButtonIndex; @@ -1274,28 +1302,6 @@ overflow_button_->SetVisible(show_overflow); if (show_overflow) { - DCHECK_NE(0, view_model_->view_size()); - if (last_visible_index_ == -1) { - x = 0; - y = 0; - } else { - x = shelf_->PrimaryAxisValue( - view_model_->ideal_bounds(last_visible_index_).right(), - view_model_->ideal_bounds(last_visible_index_).x()); - y = shelf_->PrimaryAxisValue( - view_model_->ideal_bounds(last_visible_index_).y(), - view_model_->ideal_bounds(last_visible_index_).bottom()); - } - - if (last_visible_index_ >= 0) { - // Add more space between last visible item and overflow button. - // Without this, two buttons look too close compared with other items. - x = shelf_->PrimaryAxisValue(x + button_spacing, x); - y = shelf_->PrimaryAxisValue(y, y + button_spacing); - } - - overflow_bounds->set_x(x); - overflow_bounds->set_y(y); if (overflow_bubble_.get() && overflow_bubble_->IsShowing()) UpdateOverflowRange(overflow_bubble_->bubble_view()->shelf_view()); } else { @@ -1304,6 +1310,31 @@ } } +void ShelfView::LayoutOverflowButton() const { + DCHECK_NE(0, view_model_->view_size()); + int x = 0; + int y = 0; + if (last_visible_index_ != -1) { + const int offset = (kShelfButtonSize - kShelfControlSize) / 2; + x = shelf_->PrimaryAxisValue( + offset + view_model_->ideal_bounds(last_visible_index_).right(), + offset + view_model_->ideal_bounds(last_visible_index_).x()); + y = shelf_->PrimaryAxisValue( + offset + view_model_->ideal_bounds(last_visible_index_).y(), + offset + view_model_->ideal_bounds(last_visible_index_).bottom()); + } + + if (last_visible_index_ >= 0) { + // Add more space between last visible item and overflow button. + // Without this, two buttons look too close compared with other items. + x = shelf_->PrimaryAxisValue(x + ShelfConstants::button_spacing(), x); + y = shelf_->PrimaryAxisValue(y, y + ShelfConstants::button_spacing()); + } + + overflow_button_->SetBoundsRect( + gfx::Rect(x, y, kShelfControlSize, kShelfControlSize)); +} + int ShelfView::IndexOfLastItemThatFitsSize(int max_value) const { int index = model_->item_count() - 1; while (index >= 0 && @@ -1316,8 +1347,7 @@ } void ShelfView::AnimateToIdealBounds() { - gfx::Rect overflow_bounds; - CalculateIdealBounds(&overflow_bounds); + CalculateIdealBounds(); for (int i = 0; i < view_model_->view_size(); ++i) { View* view = view_model_->view_at(i); bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i)); @@ -1326,8 +1356,8 @@ if (i && view->border()) view->SetBorder(views::NullBorder()); } - overflow_button_->SetBoundsRect(overflow_bounds); LayoutAppListAndBackButtonHighlight(); + LayoutOverflowButton(); UpdateVisibleShelfItemBoundsUnion(); } @@ -2020,8 +2050,7 @@ // button before this animation completes it doesn't appear at some random // spot (because it was in the middle of animating from 0,0 0x0 to its // target). - gfx::Rect overflow_bounds; - CalculateIdealBounds(&overflow_bounds); + CalculateIdealBounds(); view->SetBoundsRect(view_model_->ideal_bounds(model_index)); // The first animation moves all the views to their target position. |view|
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 8af59e6..1695af0 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -247,9 +247,10 @@ // Returns whether |item| should belong in the pinned section of the shelf. bool IsItemPinned(const ShelfItem& item) const; - // Enumerates the shelf items that are centered in the new UI and returns - // the total size they occupy. - int GetDimensionOfCenteredShelfItems() const; + // Enumerates the shelf apps and returns the total size they occupy, + // accounting for all apps or, if the total size is greater than |max_size|, + // the size of however many app can fit without exceeding |max_size|. + int GetDimensionOfAppIcons(int max_size) const; // Returns the index of the item after which the separator should be shown, // or -1 if no separator is required. @@ -343,7 +344,9 @@ // Calculates the ideal bounds. The bounds of each button corresponding to an // item in the model is set in |view_model_|. - void CalculateIdealBounds(gfx::Rect* overflow_bounds) const; + void CalculateIdealBounds() const; + + void LayoutOverflowButton() const; // Returns the index of the last view whose max primary axis coordinate is // less than |max_value|. Returns -1 if nothing fits, or there are no views.
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 656b3dd..a2c5ec7 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/app_list/test/app_list_test_helper.h" #include "ash/app_list/views/app_list_view.h" #include "ash/focus_cycler.h" +#include "ash/ime/ime_controller.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_prefs.h" @@ -2281,6 +2282,108 @@ EXPECT_TRUE(test_api_->CloseMenu()); } +void ExpectWithinOnePixel(int a, int b) { + EXPECT_TRUE(abs(a - b) <= 1) << "Values " << a << " and " << b + << " should have a difference no greater than 1"; +} + +TEST_F(ShelfViewTest, IconCenteringTest) { + const display::Display display = + display::Screen::GetScreen()->GetPrimaryDisplay(); + const int screen_width = display.bounds().width(); + const int screen_center = screen_width / 2; + + // Show the IME panel, to introduce for asymettry with a larger status area. + Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true); + + // At the start, we have exactly one app icon for the browser. That should + // be centered on the screen. + const ShelfAppButton* button1 = GetButtonByID(model_->items()[2].id); + ExpectWithinOnePixel(screen_center, + button1->GetBoundsInScreen().CenterPoint().x()); + // Also check that the distance between the icon edge and the screen edge is + // the same on both sides. + ExpectWithinOnePixel(button1->GetBoundsInScreen().x(), + screen_width - button1->GetBoundsInScreen().right()); + + const int apps_that_can_easily_fit_at_center_of_screen = 3; + std::vector<ShelfAppButton*> app_buttons; + // Start with just the browser app button. + app_buttons.push_back(GetButtonByID(model_->items()[2].id)); + int n_buttons = 1; + + // Now repeat the same process by adding apps until they can't fit at the + // center of the screen. + for (int i = 1; i < apps_that_can_easily_fit_at_center_of_screen; ++i) { + // Add a new app and add its button to our list. + app_buttons.push_back(GetButtonByID(AddApp())); + n_buttons = app_buttons.size(); + if (n_buttons % 2 == 1) { + // Odd number of apps. Check that the middle app is exactly at the center + // of the screen. + ExpectWithinOnePixel( + screen_center, + app_buttons[n_buttons / 2]->GetBoundsInScreen().CenterPoint().x()); + } + // Also check that the first icon is at the same distance from the left + // screen edge as the last icon is from the right screen edge. + ExpectWithinOnePixel( + app_buttons[0]->GetBoundsInScreen().x(), + screen_width - app_buttons[n_buttons - 1]->GetBoundsInScreen().right()); + } + + // Now add apps until the overflow button appears. + while (!shelf_view_->GetOverflowButton()->visible()) { + app_buttons.push_back(GetButtonByID(AddApp())); + n_buttons = app_buttons.size(); + } + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); + // TODO(manucornet): Once the issue of overflow button size versus app size + // has been resolved and the centering is pixel-perfect, test here that + // the distance between the left app and the app list button is equal to the + // distance between the overflow button and the status area. +} + +TEST_F(ShelfViewTest, FirstAndLastVisibleIndex) { + // At the start, the only things visible on the shelf are the app list button + // (index 1) and the browser app button (index 2). + EXPECT_EQ(1, shelf_view_->first_visible_index()); + EXPECT_EQ(2, shelf_view_->last_visible_index()); + // By enabling tablet mode, the back button (index 0) should become visible. + Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); + EXPECT_EQ(0, shelf_view_->first_visible_index()); + EXPECT_EQ(2, shelf_view_->last_visible_index()); + // And things should return back to the previous state once tablet mode is off + // again. + Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); + EXPECT_EQ(1, shelf_view_->first_visible_index()); + EXPECT_EQ(2, shelf_view_->last_visible_index()); + // Now let's add some apps until the overflow button shows up, each time + // checking the first and last visible indices are what we expect. + int last_visible_index = 2; + int last_visible_index_before_overflow; + ShelfID last_added_item_id; + while (true) { + last_added_item_id = AddApp(); + if (shelf_view_->GetOverflowButton()->visible()) { + last_visible_index_before_overflow = last_visible_index; + break; + } + last_visible_index++; + EXPECT_EQ(1, shelf_view_->first_visible_index()); + EXPECT_EQ(last_visible_index, shelf_view_->last_visible_index()); + } + // Now remove the last item we just added. That should get rid of the + // overflow button, and get back to the previous state. + RemoveByID(last_added_item_id); + EXPECT_EQ(1, shelf_view_->first_visible_index()); + EXPECT_EQ(last_visible_index_before_overflow, + shelf_view_->last_visible_index()); + // Adding another app should let the overflow button appear again. + AddApp(); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); +} + // Test class that tests both context and application menus. class ShelfViewMenuTest : public ShelfViewTest, public testing::WithParamInterface<bool> {
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc index 964e3c54..b4a15f1 100644 --- a/ash/shelf/shelf_window_watcher.cc +++ b/ash/shelf/shelf_window_watcher.cc
@@ -135,7 +135,8 @@ ShelfID::Deserialize(window->GetProperty(kShelfIDKey))); } - if (key == aura::client::kAppIconKey || key == aura::client::kWindowIconKey || + if (key == aura::client::kAppIconLargeKey || + key == aura::client::kAppIconKey || key == aura::client::kWindowIconKey || key == aura::client::kDrawAttentionKey || key == kShelfItemTypeKey || key == kShelfIDKey) { window_watcher_->OnUserWindowPropertyChanged(window);
diff --git a/ash/shell/example_app_list_client.cc b/ash/shell/example_app_list_client.cc index 56f339b..b798f46 100644 --- a/ash/shell/example_app_list_client.cc +++ b/ash/shell/example_app_list_client.cc
@@ -228,8 +228,12 @@ controller_->PublishSearchResults(std::move(result_data)); } -void ExampleAppListClient::OpenSearchResult(const std::string& result_id, - int event_flags) { +void ExampleAppListClient::OpenSearchResult( + const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) { auto it = std::find_if( search_results_.begin(), search_results_.end(), [&result_id](const std::unique_ptr<ExampleSearchResult>& result) {
diff --git a/ash/shell/example_app_list_client.h b/ash/shell/example_app_list_client.h index 810f1bf1f..e008068 100644 --- a/ash/shell/example_app_list_client.h +++ b/ash/shell/example_app_list_client.h
@@ -32,7 +32,11 @@ // TestAppListClient: void StartSearch(const base::string16& trimmed_query) override; - void OpenSearchResult(const std::string& result_id, int event_flags) override; + void OpenSearchResult(const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) override; void ActivateItem(const std::string& id, int event_flags) override; AppListControllerImpl* controller_;
diff --git a/ash/shell/lock_view.cc b/ash/shell/lock_view.cc index ff30789d..c6f06f0 100644 --- a/ash/shell/lock_view.cc +++ b/ash/shell/lock_view.cc
@@ -15,6 +15,7 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/text_utils.h" #include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/label.h" #include "ui/views/corewm/tooltip_controller.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -26,8 +27,11 @@ public views::ButtonListener { public: LockView() - : unlock_button_( + : text_(new views::Label(base::ASCIIToUTF16("LOCKED!"))), + unlock_button_( views::MdTextButton::Create(this, base::ASCIIToUTF16("Unlock"))) { + text_->SetEnabledColor(SK_ColorRED); + AddChildView(text_); AddChildView(unlock_button_); } ~LockView() override = default; @@ -41,23 +45,24 @@ // Overridden from views::View: void OnPaint(gfx::Canvas* canvas) override { canvas->FillRect(GetLocalBounds(), SK_ColorYELLOW); - base::string16 text = base::ASCIIToUTF16("LOCKED!"); - int string_width = gfx::GetStringWidth(text, font_list_); - canvas->DrawStringRect(text, font_list_, SK_ColorRED, - gfx::Rect((width() - string_width) / 2, - (height() - font_list_.GetHeight()) / 2, - string_width, font_list_.GetHeight())); } + void Layout() override { gfx::Rect bounds = GetLocalBounds(); + gfx::Size ts = text_->GetPreferredSize(); + text_->SetBoundsRect(gfx::Rect((bounds.width() - ts.width()) / 2, + (bounds.height() - ts.height()) / 2, + ts.width(), ts.height())); + gfx::Size ps = unlock_button_->GetPreferredSize(); bounds.set_y(bounds.bottom() - ps.height() - 5); bounds.set_x((bounds.width() - ps.width()) / 2); bounds.set_size(ps); unlock_button_->SetBoundsRect(bounds); } + void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (details.is_add && details.child == this) unlock_button_->RequestFocus(); } @@ -73,7 +78,7 @@ GetWidget()->Close(); } - gfx::FontList font_list_; + views::Label* text_; views::Button* unlock_button_; DISALLOW_COPY_AND_ASSIGN(LockView);
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc index f1d0ef8..d1e823bd 100644 --- a/ash/shell_test_api.cc +++ b/ash/shell_test_api.cc
@@ -4,6 +4,7 @@ #include "ash/shell_test_api.h" +#include <memory> #include <utility> #include "ash/accelerators/accelerator_commands.h" @@ -16,13 +17,56 @@ #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/ws/window_service_owner.h" +#include "base/run_loop.h" #include "components/prefs/testing_pref_service.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/ws/window_service.h" #include "services/ws/window_tree.h" +#include "ui/aura/window_tree_host.h" +#include "ui/compositor/compositor.h" +#include "ui/compositor/compositor_observer.h" #include "ui/events/gesture_detection/gesture_configuration.h" namespace ash { +namespace { + +// Wait for a WindowTreeHost to no longer be holding pointer events. +class PointerMoveLoopWaiter : public ui::CompositorObserver { + public: + explicit PointerMoveLoopWaiter(aura::WindowTreeHost* window_tree_host) + : window_tree_host_(window_tree_host) { + window_tree_host_->compositor()->AddObserver(this); + } + + ~PointerMoveLoopWaiter() override { + window_tree_host_->compositor()->RemoveObserver(this); + } + + void Wait() { + // Use a while loop as it's possible for releasing the lock to trigger + // processing events, which again grabs the lock. + while (window_tree_host_->holding_pointer_moves()) { + run_loop_ = std::make_unique<base::RunLoop>( + base::RunLoop::Type::kNestableTasksAllowed); + run_loop_->Run(); + run_loop_.reset(); + } + } + + // ui::CompositorObserver: + void OnCompositingEnded(ui::Compositor* compositor) override { + if (run_loop_) + run_loop_->Quit(); + } + + private: + aura::WindowTreeHost* window_tree_host_; + std::unique_ptr<base::RunLoop> run_loop_; + + DISALLOW_COPY_AND_ASSIGN(PointerMoveLoopWaiter); +}; + +} // namespace ShellTestApi::ShellTestApi() : ShellTestApi(Shell::Get()) {} @@ -131,4 +175,13 @@ ui::GestureConfiguration::GetInstance()->set_min_fling_velocity(velocity); } +void ShellTestApi::WaitForNoPointerHoldLock( + WaitForNoPointerHoldLockCallback callback) { + aura::WindowTreeHost* primary_host = + Shell::GetPrimaryRootWindowController()->GetHost(); + if (primary_host->holding_pointer_moves()) + PointerMoveLoopWaiter(primary_host).Wait(); + std::move(callback).Run(); +} + } // namespace ash
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h index 97f815b..93e62afa 100644 --- a/ash/shell_test_api.h +++ b/ash/shell_test_api.h
@@ -63,6 +63,8 @@ void ToggleOverviewMode(ToggleOverviewModeCallback cb) override; void AddRemoveDisplay() override; void SetMinFlingVelocity(float velocity) override; + void WaitForNoPointerHoldLock( + WaitForNoPointerHoldLockCallback callback) override; private: Shell* shell_; // not owned
diff --git a/ash/system/message_center/arc/arc_notification_content_view.cc b/ash/system/message_center/arc/arc_notification_content_view.cc index 79db8beb..61a902e 100644 --- a/ash/system/message_center/arc/arc_notification_content_view.cc +++ b/ash/system/message_center/arc/arc_notification_content_view.cc
@@ -583,7 +583,7 @@ } void ArcNotificationContentView::ViewHierarchyChanged( - const views::View::ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { views::Widget* widget = GetWidget(); if (!details.is_add) {
diff --git a/ash/system/message_center/arc/arc_notification_content_view.h b/ash/system/message_center/arc/arc_notification_content_view.h index e9a2fe4..2ac137d7 100644 --- a/ash/system/message_center/arc/arc_notification_content_view.h +++ b/ash/system/message_center/arc/arc_notification_content_view.h
@@ -94,7 +94,7 @@ // views::NativeViewHost void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void Layout() override; void OnPaint(gfx::Canvas* canvas) override; void OnMouseEntered(const ui::MouseEvent& event) override;
diff --git a/ash/system/message_center/notifier_settings_view.cc b/ash/system/message_center/notifier_settings_view.cc index 7e7bc01..2924f87 100644 --- a/ash/system/message_center/notifier_settings_view.cc +++ b/ash/system/message_center/notifier_settings_view.cc
@@ -513,7 +513,7 @@ buttons_.clear(); - views::View* contents_view = new ScrollContentsView(); + auto contents_view = std::make_unique<ScrollContentsView>(); contents_view->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(0, kHorizontalMargin))); @@ -531,9 +531,10 @@ no_notifiers_view_->SetVisible(notifier_count == 0); top_label_->InvalidateLayout(); - scroller_->SetContents(contents_view); + auto* contents_view_ptr = scroller_->SetContents(std::move(contents_view)); - contents_view->SetBoundsRect(gfx::Rect(contents_view->GetPreferredSize())); + contents_view_ptr->SetBoundsRect( + gfx::Rect(contents_view_ptr->GetPreferredSize())); Layout(); }
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc index a3d67efd..8a4ca26 100644 --- a/ash/system/message_center/unified_message_center_view.cc +++ b/ash/system/message_center/unified_message_center_view.cc
@@ -270,7 +270,8 @@ // Need to set the transparent background explicitly, since ScrollView has // set the default opaque background color. - scroller_->SetContents(new ScrollerContentsView(message_list_view_, this)); + scroller_->SetContents( + std::make_unique<ScrollerContentsView>(message_list_view_, this)); scroller_->SetBackgroundColor(SK_ColorTRANSPARENT); scroller_->SetVerticalScrollBar(scroll_bar_); scroller_->set_draw_overflow_indicator(false);
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc index 51af065..6e646b9 100644 --- a/ash/system/tray/tray_bubble_view.cc +++ b/ash/system/tray/tray_bubble_view.cc
@@ -457,7 +457,7 @@ } void TrayBubbleView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) { details.parent->SetPaintToLayer(); details.parent->layer()->SetMasksToBounds(true);
diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h index 2df5d73..79258d80 100644 --- a/ash/system/tray/tray_bubble_view.h +++ b/ash/system/tray/tray_bubble_view.h
@@ -192,7 +192,7 @@ // Overridden from views::View. void ChildPreferredSizeChanged(View* child) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; private: // This reroutes receiving key events to the TrayBubbleView passed in the
diff --git a/ash/system/tray/tray_container.cc b/ash/system/tray/tray_container.cc index fedcb7c..7537d58 100644 --- a/ash/system/tray/tray_container.cc +++ b/ash/system/tray/tray_container.cc
@@ -42,7 +42,7 @@ } void TrayContainer::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.parent == this) PreferredSizeChanged(); }
diff --git a/ash/system/tray/tray_container.h b/ash/system/tray/tray_container.h index e07b593..1758e722 100644 --- a/ash/system/tray/tray_container.h +++ b/ash/system/tray/tray_container.h
@@ -27,7 +27,7 @@ void ChildPreferredSizeChanged(views::View* child) override; void ChildVisibilityChanged(View* child) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; gfx::Rect GetAnchorBoundsInScreen() const override; private:
diff --git a/ash/system/tray/tray_detailed_view.cc b/ash/system/tray/tray_detailed_view.cc index c58ff42..5eb98fb 100644 --- a/ash/system/tray/tray_detailed_view.cc +++ b/ash/system/tray/tray_detailed_view.cc
@@ -4,6 +4,8 @@ #include "ash/system/tray/tray_detailed_view.h" +#include <utility> + #include "ash/public/cpp/ash_view_ids.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/tray/detailed_view_delegate.h" @@ -141,7 +143,7 @@ } void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (!details.is_add && details.parent == this) { headers_.erase(std::remove_if(headers_.begin(), headers_.end(), [details](const Header& header) { @@ -313,11 +315,11 @@ void TrayDetailedView::CreateScrollableList() { DCHECK(!scroller_); - scroll_content_ = new ScrollContentsView(delegate_); + auto scroll_content = std::make_unique<ScrollContentsView>(delegate_); scroller_ = new views::ScrollView; scroller_->set_draw_overflow_indicator( delegate_->IsOverflowIndicatorEnabled()); - scroller_->SetContents(scroll_content_); + scroll_content_ = scroller_->SetContents(std::move(scroll_content)); // TODO(varkha): Make the sticky rows work with EnableViewPortLayer(). scroller_->SetBackgroundColor( delegate_->GetBackgroundColor(GetNativeTheme()));
diff --git a/ash/system/tray/tri_view.cc b/ash/system/tray/tri_view.cc index de1bd05..d08f9f07 100644 --- a/ash/system/tray/tri_view.cc +++ b/ash/system/tray/tri_view.cc
@@ -140,7 +140,7 @@ } void TriView::ViewHierarchyChanged( - const views::View::ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { views::View::ViewHierarchyChanged(details); if (!enable_hierarchy_changed_dcheck_) return;
diff --git a/ash/system/tray/tri_view.h b/ash/system/tray/tri_view.h index d557020..43e461fc 100644 --- a/ash/system/tray/tri_view.h +++ b/ash/system/tray/tri_view.h
@@ -124,7 +124,7 @@ protected: // View: void ViewHierarchyChanged( - const views::View::ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; const char* GetClassName() const override; private:
diff --git a/ash/system/unified/feature_pods_container_view.cc b/ash/system/unified/feature_pods_container_view.cc index 2ec92763..94c4356 100644 --- a/ash/system/unified/feature_pods_container_view.cc +++ b/ash/system/unified/feature_pods_container_view.cc
@@ -85,7 +85,7 @@ } void FeaturePodsContainerView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { UpdateChildVisibility(); }
diff --git a/ash/system/unified/feature_pods_container_view.h b/ash/system/unified/feature_pods_container_view.h index 1a5c1e81..faff3ea6 100644 --- a/ash/system/unified/feature_pods_container_view.h +++ b/ash/system/unified/feature_pods_container_view.h
@@ -37,7 +37,7 @@ gfx::Size CalculatePreferredSize() const override; void ChildVisibilityChanged(View* child) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void Layout() override; private:
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index b103fa98..17c265d 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -708,6 +708,18 @@ return; } + // Stop the current fade in animation if we shouldn't be animating. + if (wm::GetWindowState(window)->IsMinimized() && + animation_type == OVERVIEW_ANIMATION_NONE) { + views::Widget* minimized_widget = transform_window_.minimized_widget(); + if (minimized_widget) { + minimized_widget->GetNativeWindow() + ->layer() + ->GetAnimator() + ->StopAnimating(); + } + } + gfx::Transform transform = ScopedOverviewTransformWindow::GetTransformForRect( screen_rect, overview_item_bounds); ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings;
diff --git a/ash/wm/overview/scoped_overview_transform_window.cc b/ash/wm/overview/scoped_overview_transform_window.cc index 21a7dd3..748f225 100644 --- a/ash/wm/overview/scoped_overview_transform_window.cc +++ b/ash/wm/overview/scoped_overview_transform_window.cc
@@ -66,21 +66,6 @@ return ScopedOverviewTransformWindow::GridWindowFillMode::kNormal; } -OverviewAnimationType GetExitOverviewAnimationTypeForMinimizedWindow( - OverviewSession::EnterExitOverviewType type) { - // EnterExitOverviewType can only be set to kWindowMinimized in talbet mode. - // Fade out the minimized window without animation if switch from tablet mode - // to clamshell mode. - if (type == OverviewSession::EnterExitOverviewType::kWindowsMinimized) { - return Shell::Get() - ->tablet_mode_controller() - ->IsTabletModeWindowManagerEnabled() - ? OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER - : OVERVIEW_ANIMATION_NONE; - } - return OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT; -} - } // namespace class ScopedOverviewTransformWindow::LayerCachingAndFilteringObserver @@ -571,4 +556,24 @@ /*slide=*/false); } +OverviewAnimationType +ScopedOverviewTransformWindow::GetExitOverviewAnimationTypeForMinimizedWindow( + OverviewSession::EnterExitOverviewType type) { + // EnterExitOverviewType can only be set to kWindowMinimized in talbet mode. + // Fade out the minimized window without animation if switch from tablet mode + // to clamshell mode. + if (type == OverviewSession::EnterExitOverviewType::kWindowsMinimized) { + return Shell::Get() + ->tablet_mode_controller() + ->IsTabletModeWindowManagerEnabled() + ? OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER + : OVERVIEW_ANIMATION_NONE; + } + + DCHECK(overview_item_); + return overview_item_->should_animate_when_exiting() + ? OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT + : OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO; +} + } // namespace ash
diff --git a/ash/wm/overview/scoped_overview_transform_window.h b/ash/wm/overview/scoped_overview_transform_window.h index febea2e..e52cc2d 100644 --- a/ash/wm/overview/scoped_overview_transform_window.h +++ b/ash/wm/overview/scoped_overview_transform_window.h
@@ -192,6 +192,9 @@ void CreateMirrorWindowForMinimizedState(); + OverviewAnimationType GetExitOverviewAnimationTypeForMinimizedWindow( + OverviewSession::EnterExitOverviewType type); + // Makes Close() execute synchronously when used in tests. static void SetImmediateCloseForTests();
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index e7ec9f4..ae37a37 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -725,8 +725,8 @@ } // Do not snap the window if the activation change is caused by dragging a - // window's tabs around. - if (wm::IsDraggingTabs(gained_active)) + // window, regardless of tab drag or window drag. + if (wm::GetWindowState(gained_active)->is_dragged()) return; // Only windows in MRU list can be snapped.
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 4077bb0b..d2225a4 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/magnifier/docked_magnifier_controller.h" #include "ash/public/cpp/app_types.h" #include "ash/public/cpp/window_properties.h" +#include "ash/root_window_controller.h" #include "ash/screen_util.h" #include "ash/session/session_controller.h" #include "ash/session/test_session_controller_client.h" @@ -4409,4 +4410,51 @@ split_view_controller()->state()); } +// Tests the backdrop bounds during window drag. +TEST_F(SplitViewAppDraggingTest, BackdropBoundsDuringDrag) { + InitializeWindow(); + std::unique_ptr<aura::Window> window2 = CreateTestWindowWithWidget(true); + split_view_controller()->SnapWindow(window(), SplitViewController::LEFT); + split_view_controller()->SnapWindow(window2.get(), + SplitViewController::RIGHT); + EXPECT_EQ(window2.get(), wm::GetActiveWindow()); + + const aura::Window* default_container = + Shell::GetPrimaryRootWindowController()->GetContainer( + kShellWindowId_DefaultContainer); + + // Backdrop window should below two snapped windows and its bounds should be + // the same as the container bounds. + EXPECT_EQ(3U, default_container->children().size()); + EXPECT_EQ(window(), default_container->children()[1]); + EXPECT_EQ(window2.get(), default_container->children()[2]); + EXPECT_EQ(default_container->bounds(), + default_container->children()[0]->bounds()); + + // Start window drag and activate the dragged window during drag. + gfx::Point location(0, 10); + SendScrollStartAndUpdate(location); + wm::ActivateWindow(window()); + + aura::Window::Windows windows = default_container->children(); + auto it = std::find(windows.begin(), windows.end(), window2.get()); + // Backdrop window should be the window that just below the snapped |window2| + // and its bounds should be the same as the snapped window during drag. + aura::Window* backdrop_window = nullptr; + if (it != windows.begin()) + backdrop_window = *(--it); + DCHECK(backdrop_window); + EXPECT_EQ(window2->bounds(), backdrop_window->bounds()); + + // Backdrop should restore back to container bounds after drag. + EndScrollSequence(); + EXPECT_EQ(window(), wm::GetActiveWindow()); + windows = default_container->children(); + it = std::find(windows.begin(), windows.end(), window2.get()); + if (it != windows.begin()) + backdrop_window = *(--it); + DCHECK(backdrop_window); + EXPECT_EQ(backdrop_window->bounds(), default_container->bounds()); +} + } // namespace ash
diff --git a/ash/wm/test_child_modal_parent.cc b/ash/wm/test_child_modal_parent.cc index 98952e7..e8280731 100644 --- a/ash/wm/test_child_modal_parent.cc +++ b/ash/wm/test_child_modal_parent.cc
@@ -145,7 +145,7 @@ } void TestChildModalParent::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) { host_->Attach(modal_parent_->GetNativeView()); GetWidget()->GetNativeView()->SetName("Parent");
diff --git a/ash/wm/test_child_modal_parent.h b/ash/wm/test_child_modal_parent.h index 0370ddb..0fe1516 100644 --- a/ash/wm/test_child_modal_parent.h +++ b/ash/wm/test_child_modal_parent.h
@@ -46,7 +46,7 @@ // Overridden from views::View: void Layout() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // Overridden from ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ash/wm/window_mirror_view.cc b/ash/wm/window_mirror_view.cc index 9f130ed..f794b5a 100644 --- a/ash/wm/window_mirror_view.cc +++ b/ash/wm/window_mirror_view.cc
@@ -35,23 +35,6 @@ } } -// Removes 1 instance of an element from a multiset. -void EraseFromList(std::vector<aura::Window*>* targets, aura::Window* target) { - auto it = std::find(targets->begin(), targets->end(), target); - if (it != targets->end()) - targets->erase(it); -} - -void RemoveTargetWindowFromSource(aura::Window* target, aura::Window* source) { - if (!target || !source) - return; - std::vector<aura::Window*>* target_window_list = - source->GetProperty(aura::client::kMirrorWindowList); - if (!target_window_list) - return; - EraseFromList(target_window_list, target); -} - } // namespace WindowMirrorView::WindowMirrorView(aura::Window* source, @@ -64,7 +47,6 @@ WindowMirrorView::~WindowMirrorView() { // Make sure |source_| has outlived |this|. See crbug.com/681207 DCHECK(source_->layer()); - RemoveTargetWindowFromSource(target_, source_); } void WindowMirrorView::RecreateMirrorLayers() { @@ -108,30 +90,7 @@ InitLayerOwner(); } -void WindowMirrorView::NativeViewHierarchyChanged() { - View::NativeViewHierarchyChanged(); - DCHECK(GetWidget()); - UpdateSourceWindowProperty(); -} - void WindowMirrorView::AddedToWidget() { - UpdateSourceWindowProperty(); -} - -void WindowMirrorView::RemovedFromWidget() { - RemoveTargetWindowFromSource(target_, source_); - target_ = nullptr; -} - -void WindowMirrorView::UpdateSourceWindowProperty() { - DCHECK(GetWidget()); - std::vector<aura::Window*>* target_window_list = - source_->GetProperty(aura::client::kMirrorWindowList); - - // Remove 1 instance of |target_| from the list. - if (target_ && target_window_list) - EraseFromList(target_window_list, target_); - // Set and insert the new target window associated with this mirror view. target_ = GetWidget()->GetNativeWindow(); target_->TrackOcclusionState(); @@ -140,33 +99,18 @@ force_proxy_window_visible_.reset(); env_observer_.RemoveAll(); - // Allocate new memory for |target_window_list| here because as soon as a - // call is made to SetProperty, the previous memory will be deallocated. - auto temp_list = - target_window_list - ? std::make_unique<std::vector<aura::Window*>>(*target_window_list) - : std::make_unique<std::vector<aura::Window*>>(); + // Wait for window-occlusion tracker to be running before forcing visibility. + // This is done to minimize the amount of work during the initial animation + // when entering overview. In particular, telling the remote client it is + // visible is likely to result in a fair amount of work. + if (source_->env()->GetWindowOcclusionTracker()->IsPaused()) + env_observer_.Add(target_->env()); + else + ForceVisibilityAndOcclusion(); +} - temp_list->push_back(target_); - - // Set the property to trigger a call to OnWindowPropertyChanged() on all the - // window observer. - // NOTE: This will deallocate the current property value so make sure new - // memory has been allocated for the property value. - source_->SetProperty(aura::client::kMirrorWindowList, temp_list.release()); - - // If |source_| represents a remote client, it needs to be made visible, - // otherwise it won't produce frames. - if (target_ && NonClientFrameController::Get(source_)) { - // Wait for window-occlusion tracker to be running before forcing - // visibility. This is done to minimize the amount of work during the - // initial animation when entering overview. In particular, telling the - // remote client it is visible is likely to result in a fair amount of work. - if (source_->env()->GetWindowOcclusionTracker()->IsPaused()) - env_observer_.Add(target_->env()); - else - ForceVisibilityAndOcclusionForProxyWindow(); - } +void WindowMirrorView::RemovedFromWidget() { + target_ = nullptr; } void WindowMirrorView::InitLayerOwner() { @@ -212,25 +156,25 @@ return client_view->ConvertRectToWidget(client_view->GetLocalBounds()); } -void WindowMirrorView::ForceVisibilityAndOcclusionForProxyWindow() { - NonClientFrameController* frame_controller = - NonClientFrameController::Get(source_); - // Earlier checks ensure we only get here if there is a - // NonClientFrameController. - DCHECK(frame_controller); - // In order for the remote client to produce frames the client needs to think - // the window is visible. It may not actually be visible now, so force it. - force_proxy_window_visible_ = - frame_controller->top_level_proxy_window()->ForceVisible(); - - // Similarly, force the occlusion tracker to treat the source as visible. +void WindowMirrorView::ForceVisibilityAndOcclusion() { + // Force the occlusion tracker to treat the source as visible. force_occlusion_tracker_visible_ = std::make_unique<aura::WindowOcclusionTracker::ScopedForceVisible>( source_); + + NonClientFrameController* frame_controller = + NonClientFrameController::Get(source_); + if (frame_controller) { + // In order for the remote client to produce frames the client needs to + // think the window is visible. It may not actually be visible now, so force + // it. + force_proxy_window_visible_ = + frame_controller->top_level_proxy_window()->ForceVisible(); + } } void WindowMirrorView::OnWindowOcclusionTrackingResumed() { - ForceVisibilityAndOcclusionForProxyWindow(); + ForceVisibilityAndOcclusion(); env_observer_.RemoveAll(); }
diff --git a/ash/wm/window_mirror_view.h b/ash/wm/window_mirror_view.h index e43e637..15419f45 100644 --- a/ash/wm/window_mirror_view.h +++ b/ash/wm/window_mirror_view.h
@@ -48,18 +48,12 @@ void Layout() override; bool GetNeedsNotificationWhenVisibleBoundsChange() const override; void OnVisibleBoundsChanged() override; - void NativeViewHierarchyChanged() override; void AddedToWidget() override; void RemovedFromWidget() override; private: void InitLayerOwner(); - // Ensures that the |target_| window is in the list of mirror windows that is - // set as a property on the |source_| window. This method triggers the - // OnWindowPropertyChanged() on WindowObservers. - void UpdateSourceWindowProperty(); - // Gets the root of the layer tree that was lifted from |source_| (and is now // a child of |this->layer()|). ui::Layer* GetMirrorLayer(); @@ -68,7 +62,7 @@ // coordinate space. gfx::Rect GetClientAreaBounds() const; - void ForceVisibilityAndOcclusionForProxyWindow(); + void ForceVisibilityAndOcclusion(); // aura::EnvObserver: void OnWindowOcclusionTrackingResumed() override; @@ -87,8 +81,6 @@ // InitLayerOwner(). bool trilinear_filtering_on_init_; - // These are used when mirroring a window from a remote client (a proxy - // window from the window-service). std::unique_ptr<aura::WindowOcclusionTracker::ScopedForceVisible> force_occlusion_tracker_visible_; std::unique_ptr<ws::ScopedForceVisible> force_proxy_window_visible_;
diff --git a/ash/wm/window_mirror_view_unittest.cc b/ash/wm/window_mirror_view_unittest.cc index dba54fc..968c98c 100644 --- a/ash/wm/window_mirror_view_unittest.cc +++ b/ash/wm/window_mirror_view_unittest.cc
@@ -90,6 +90,26 @@ EXPECT_TRUE(client_root_test_helper.IsWindowForcedVisible()); } +TEST_F(WindowMirrorViewTest, LocalWindowOcclusionMadeVisible) { + auto widget = CreateTestWidget(); + widget->Hide(); + aura::Window* widget_window = widget->GetNativeWindow(); + widget_window->TrackOcclusionState(); + EXPECT_EQ(aura::Window::OcclusionState::HIDDEN, + widget_window->occlusion_state()); + + auto mirror_widget = CreateTestWidget(); + auto mirror_view = std::make_unique<WindowMirrorView>( + widget_window, /*trilinear_filtering_on_init=*/false); + mirror_widget->widget_delegate()->GetContentsView()->AddChildView( + mirror_view.get()); + + // Even though the widget is hidden, the occlusion state is considered + // visible. This is to ensure renderers still produce content. + EXPECT_EQ(aura::Window::OcclusionState::VISIBLE, + widget_window->occlusion_state()); +} + } // namespace } // namespace wm } // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn index 6e98ca4..804ca77f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -244,6 +244,8 @@ "debug/stack_trace.h", "debug/stack_trace_android.cc", "debug/stack_trace_win.cc", + "debug/task_trace.cc", + "debug/task_trace.h", "deferred_sequenced_task_runner.cc", "deferred_sequenced_task_runner.h", "enterprise_util.h", @@ -720,7 +722,6 @@ "task/cancelable_task_tracker.cc", "task/cancelable_task_tracker.h", "task/common/intrusive_heap.h", - "task/common/intrusive_heap_lazy_staleness_policy.h", "task/common/operations_controller.cc", "task/common/operations_controller.h", "task/common/task_annotator.cc", @@ -2124,6 +2125,10 @@ "synchronization/waitable_event_perftest.cc", "threading/thread_perftest.cc", ] + if (!is_ios) { + # iOS doesn't use the partition allocator, therefore it can't run this test. + sources += [ "allocator/partition_allocator/partition_alloc_perftest.cc" ] + } deps = [ ":base", "//base/test:test_support", @@ -2360,6 +2365,7 @@ "debug/leak_tracker_unittest.cc", "debug/proc_maps_linux_unittest.cc", "debug/stack_trace_unittest.cc", + "debug/task_trace_unittest.cc", "deferred_sequenced_task_runner_unittest.cc", "environment_unittest.cc", "feature_list_unittest.cc", @@ -2518,11 +2524,9 @@ "system/sys_info_unittest.cc", "system/system_monitor_unittest.cc", "task/cancelable_task_tracker_unittest.cc", - "task/common/intrusive_heap_lazy_staleness_policy_unittest.cc", "task/common/intrusive_heap_unittest.cc", "task/common/operations_controller_unittest.cc", "task/common/task_annotator_unittest.cc", - "task/common/test_utils.h", "task/lazy_task_runner_unittest.cc", "task/post_task_unittest.cc", "task/scoped_set_task_priority_for_current_thread_unittest.cc", @@ -3184,6 +3188,7 @@ "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", "//third_party/android_tools:android_support_chromium_java", + "//third_party/android_tools:android_test_base_java", "//third_party/android_tools:android_test_mock_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/junit",
diff --git a/base/allocator/partition_allocator/partition_alloc_perftest.cc b/base/allocator/partition_allocator/partition_alloc_perftest.cc new file mode 100644 index 0000000..541a932 --- /dev/null +++ b/base/allocator/partition_allocator/partition_alloc_perftest.cc
@@ -0,0 +1,162 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> +#include "base/allocator/partition_allocator/partition_alloc.h" +#include "base/time/time.h" +#include "base/timer/lap_timer.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace base { +namespace { + +// Change kTimeLimit to something higher if you need more time to capture a +// trace. +constexpr base::TimeDelta kTimeLimit = base::TimeDelta::FromSeconds(5); +constexpr int kWarmupRuns = 5; +constexpr int kTimeCheckInterval = 100000; + +// Size constants are mostly arbitrary, but try to simulate something like CSS +// parsing which consists of lots of relatively small objects. +constexpr int kMultiBucketMinimumSize = 24; +constexpr int kMultiBucketIncrement = 13; +// Final size is 24 + (13 * 22) = 310 bytes. +constexpr int kMultiBucketRounds = 22; + +class MemoryAllocationPerfTest : public testing::Test { + public: + MemoryAllocationPerfTest() + : timer_(kWarmupRuns, kTimeLimit, kTimeCheckInterval) {} + void SetUp() override { alloc_.init(); } + void TearDown() override { + alloc_.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages | + PartitionPurgeDiscardUnusedSystemPages); + } + LapTimer timer_; + PartitionAllocatorGeneric alloc_; +}; + +class MemoryAllocationPerfNode { + public: + MemoryAllocationPerfNode* GetNext() const { return next_; } + void SetNext(MemoryAllocationPerfNode* p) { next_ = p; } + static void FreeAll(MemoryAllocationPerfNode* first, + PartitionAllocatorGeneric& alloc) { + MemoryAllocationPerfNode* cur = first; + while (cur != nullptr) { + MemoryAllocationPerfNode* next = cur->GetNext(); + alloc.root()->Free(cur); + cur = next; + } + } + + private: + MemoryAllocationPerfNode* next_ = nullptr; +}; + +TEST_F(MemoryAllocationPerfTest, SingleBucket) { + timer_.Reset(); + MemoryAllocationPerfNode* first = reinterpret_cast<MemoryAllocationPerfNode*>( + alloc_.root()->Alloc(40, "<testing>")); + MemoryAllocationPerfNode* cur = first; + do { + MemoryAllocationPerfNode* next = + reinterpret_cast<MemoryAllocationPerfNode*>( + alloc_.root()->Alloc(40, "<testing>")); + CHECK_NE(next, nullptr); + cur->SetNext(next); + cur = next; + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + // next_ = nullptr only works if the class constructor is called (it's not + // called in this case because then we can allocate arbitrary-length + // payloads.) + cur->SetNext(nullptr); + + MemoryAllocationPerfNode::FreeAll(first, alloc_); + + perf_test::PrintResult("MemoryAllocationPerfTest", + " single bucket allocation (40 bytes)", "", + timer_.LapsPerSecond(), "runs/s", true); +} + +TEST_F(MemoryAllocationPerfTest, SingleBucketWithFree) { + timer_.Reset(); + // Allocate an initial element to make sure the bucket stays set up. + void* elem = alloc_.root()->Alloc(40, "<testing>"); + do { + void* cur = alloc_.root()->Alloc(40, "<testing>"); + CHECK_NE(cur, nullptr); + alloc_.root()->Free(cur); + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + alloc_.root()->Free(elem); + perf_test::PrintResult("MemoryAllocationPerfTest", + " single bucket allocation + free (40 bytes)", "", + timer_.LapsPerSecond(), "runs/s", true); +} + +TEST_F(MemoryAllocationPerfTest, MultiBucket) { + timer_.Reset(); + MemoryAllocationPerfNode* first = reinterpret_cast<MemoryAllocationPerfNode*>( + alloc_.root()->Alloc(40, "<testing>")); + MemoryAllocationPerfNode* cur = first; + do { + for (int i = 0; i < kMultiBucketRounds; i++) { + MemoryAllocationPerfNode* next = + reinterpret_cast<MemoryAllocationPerfNode*>(alloc_.root()->Alloc( + kMultiBucketMinimumSize + (i * kMultiBucketIncrement), + "<testing>")); + CHECK_NE(next, nullptr); + cur->SetNext(next); + cur = next; + } + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + cur->SetNext(nullptr); + + MemoryAllocationPerfNode::FreeAll(first, alloc_); + + perf_test::PrintResult("MemoryAllocationPerfTest", " multi-bucket allocation", + "", timer_.LapsPerSecond() * kMultiBucketRounds, + "runs/s", true); +} + +TEST_F(MemoryAllocationPerfTest, MultiBucketWithFree) { + timer_.Reset(); + std::vector<void*> elems; + // Do an initial round of allocation to make sure that the buckets stay in use + // (and aren't accidentally released back to the OS). + for (int i = 0; i < kMultiBucketRounds; i++) { + void* cur = alloc_.root()->Alloc( + kMultiBucketMinimumSize + (i * kMultiBucketIncrement), "<testing>"); + CHECK_NE(cur, nullptr); + elems.push_back(cur); + } + + do { + for (int i = 0; i < kMultiBucketRounds; i++) { + void* cur = alloc_.root()->Alloc( + kMultiBucketMinimumSize + (i * kMultiBucketIncrement), "<testing>"); + CHECK_NE(cur, nullptr); + alloc_.root()->Free(cur); + } + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + for (void* ptr : elems) { + alloc_.root()->Free(ptr); + } + + perf_test::PrintResult( + "MemoryAllocationPerfTest", " multi-bucket allocation + free", "", + timer_.LapsPerSecond() * kMultiBucketRounds, "runs/s", true); +} + +} // anonymous namespace + +} // namespace base
diff --git a/base/debug/task_trace.cc b/base/debug/task_trace.cc new file mode 100644 index 0000000..24cd69f --- /dev/null +++ b/base/debug/task_trace.cc
@@ -0,0 +1,69 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/task_trace.h" + +#include <algorithm> +#include <iostream> + +#include "base/pending_task.h" +#include "base/task/common/task_annotator.h" + +namespace base { +namespace debug { + +TaskTrace::TaskTrace() { + const PendingTask* current_task = TaskAnnotator::CurrentTaskForThread(); + if (!current_task) + return; + std::array<const void*, PendingTask::kTaskBacktraceLength + 1> task_trace; + task_trace[0] = current_task->posted_from.program_counter(); + std::copy(current_task->task_backtrace.begin(), + current_task->task_backtrace.end(), task_trace.begin() + 1); + size_t length = 0; + while (length < task_trace.size() && task_trace[length]) + ++length; + if (length == 0) + return; + stack_trace_.emplace(task_trace.data(), length); + trace_overflow_ = current_task->task_backtrace_overflow; +} + +bool TaskTrace::empty() const { + return !stack_trace_.has_value(); +} + +void TaskTrace::Print() const { + OutputToStream(&std::cerr); +} + +void TaskTrace::OutputToStream(std::ostream* os) const { + *os << "Task trace:" << std::endl; + if (!stack_trace_) { + *os << "No active task."; + return; + } + *os << *stack_trace_; + if (trace_overflow_) { + *os << "Task trace buffer limit hit, update " + "PendingTask::kTaskBacktraceLength to increase." + << std::endl; + } +} + +base::span<const void* const> TaskTrace::AddressesForTesting() const { + if (empty()) + return {}; + size_t count = 0; + const void* const* addresses = stack_trace_->Addresses(&count); + return {addresses, count}; +} + +std::ostream& operator<<(std::ostream& os, const TaskTrace& task_trace) { + task_trace.OutputToStream(&os); + return os; +} + +} // namespace debug +} // namespace base
diff --git a/base/debug/task_trace.h b/base/debug/task_trace.h new file mode 100644 index 0000000..d976624 --- /dev/null +++ b/base/debug/task_trace.h
@@ -0,0 +1,61 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DEBUG_TASK_TRACE_H_ +#define BASE_DEBUG_TASK_TRACE_H_ + +#include <iosfwd> + +#include "base/base_export.h" +#include "base/containers/span.h" +#include "base/debug/stack_trace.h" +#include "base/optional.h" + +namespace base { +namespace debug { + +// Provides a snapshot of which places in the code posted tasks with a FROM_HERE +// that led to the TaskTrace() constructor call. +// +// Example usage: +// TaskTrace().Print(); +// +// Example output: +// Task trace: +// #0 content::ServiceWorkerContextWrapper::DidCheckHasServiceWorker() +// #1 content::ServiceWorkerStorage::FindForDocumentInDB() +// #2 content::ServiceWorkerStorage::FindRegistrationForDocument() +// #3 content::ServiceWorkerContextWrapper::CheckHasServiceWorker() +// #4 content::ManifestIconDownloader::ScaleIcon() +// Task trace buffer limit hit, update PendingTask::kTaskBacktraceLength to +// increase. +class BASE_EXPORT TaskTrace { + public: + TaskTrace(); + + // Whether there is any trace data. + bool empty() const; + + // Outputs to stderr via OutputToStream. + void Print() const; + + // Outputs trace to |os|, may be called when empty() is true. + void OutputToStream(std::ostream* os) const; + + // Returns the list of addresses in the task trace for testing. + base::span<const void* const> AddressesForTesting() const; + + private: + base::Optional<StackTrace> stack_trace_; + bool trace_overflow_ = false; +}; + +// Forwards to TaskTrace::OutputToStream. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, + const TaskTrace& task_trace); + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_TASK_TRACE_H_
diff --git a/base/debug/task_trace_unittest.cc b/base/debug/task_trace_unittest.cc new file mode 100644 index 0000000..d7c5933 --- /dev/null +++ b/base/debug/task_trace_unittest.cc
@@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/task_trace.h" + +#include <ostream> + +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace debug { + +TEST(TaskTraceTest, NoTask) { + TaskTrace task_trace; + EXPECT_TRUE(task_trace.empty()); + EXPECT_EQ(task_trace.AddressesForTesting().size(), 0ul); +} + +class ThreeTasksTest { + public: + ThreeTasksTest() {} + + void Run() { + task_runner.PostTask(FROM_HERE, base::BindOnce(&ThreeTasksTest::TaskA, + base::Unretained(this))); + task_environment.RunUntilIdle(); + } + + void TaskA() { + TaskTrace task_trace; + EXPECT_FALSE(task_trace.empty()); + base::span<const void* const> addresses = task_trace.AddressesForTesting(); + EXPECT_EQ(addresses.size(), 1ul); + task_a_address = addresses[0]; + task_runner.PostTask(FROM_HERE, base::BindOnce(&ThreeTasksTest::TaskB, + base::Unretained(this))); + } + + void TaskB() { + TaskTrace task_trace; + EXPECT_FALSE(task_trace.empty()); + base::span<const void* const> addresses = task_trace.AddressesForTesting(); + EXPECT_EQ(addresses.size(), 2ul); + task_b_address = addresses[0]; + EXPECT_EQ(addresses[1], task_a_address); + task_runner.PostTask(FROM_HERE, base::BindOnce(&ThreeTasksTest::TaskC, + base::Unretained(this))); + } + + void TaskC() { + TaskTrace task_trace; + EXPECT_FALSE(task_trace.empty()); + base::span<const void* const> addresses = task_trace.AddressesForTesting(); + EXPECT_EQ(addresses.size(), 3ul); + EXPECT_EQ(addresses[1], task_b_address); + EXPECT_EQ(addresses[2], task_a_address); + } + + private: + base::test::ScopedTaskEnvironment task_environment; + base::SingleThreadTaskRunner& task_runner = + *task_environment.GetMainThreadTaskRunner(); + + const void* task_a_address = nullptr; + const void* task_b_address = nullptr; +}; + +TEST(TaskTraceTest, ThreeTasks) { + ThreeTasksTest().Run(); +} + +} // namespace debug +} // namespace base
diff --git a/base/logging.cc b/base/logging.cc index 58f3d15f..52720c4 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -92,6 +92,7 @@ #include "base/debug/alias.h" #include "base/debug/debugger.h" #include "base/debug/stack_trace.h" +#include "base/debug/task_trace.h" #include "base/lazy_instance.h" #include "base/posix/eintr_wrapper.h" #include "base/strings/string_piece.h" @@ -585,9 +586,12 @@ !defined(OS_AIX) if (severity_ == LOG_FATAL && !base::debug::BeingDebugged()) { // Include a stack trace on a fatal, unless a debugger is attached. - base::debug::StackTrace trace; + base::debug::StackTrace stack_trace; stream_ << std::endl; // Newline to separate from log message. - trace.OutputToStream(&stream_); + stack_trace.OutputToStream(&stream_); + base::debug::TaskTrace task_trace; + if (!task_trace.empty()) + task_trace.OutputToStream(&stream_); } #endif stream_ << std::endl;
diff --git a/base/pending_task.h b/base/pending_task.h index f736421..a609a910 100644 --- a/base/pending_task.h +++ b/base/pending_task.h
@@ -54,9 +54,10 @@ // if the task hasn't been inserted in a sequence yet. TimeTicks queue_time; - // Chain of up-to-four symbols of the parent tasks which led to this one being - // posted. - std::array<const void*, 4> task_backtrace = {}; + // Chain of symbols of the parent tasks which led to this one being posted. + static constexpr size_t kTaskBacktraceLength = 4; + std::array<const void*, kTaskBacktraceLength> task_backtrace = {}; + bool task_backtrace_overflow = false; // Secondary sort key for run time. int sequence_num = 0;
diff --git a/base/profiler/native_stack_sampler_mac.cc b/base/profiler/native_stack_sampler_mac.cc index 907a6a0a..d9009be6 100644 --- a/base/profiler/native_stack_sampler_mac.cc +++ b/base/profiler/native_stack_sampler_mac.cc
@@ -256,6 +256,16 @@ ProfileBuilder* profile_builder) override; private: + // Suspends the thread with |thread_handle|, copies its stack, register + // context, and current metadata and resumes the thread. Returns true on + // success. + static bool CopyStack(mach_port_t thread_port, + const void* base_address, + StackBuffer* stack_buffer, + ProfileBuilder* profile_builder, + x86_thread_state64_t* thread_state, + uintptr_t* stack_top); + // Walks the stack represented by |thread_state|, calling back to the // provided lambda for each frame. std::vector<Frame> WalkStack(const x86_thread_state64_t& thread_state, @@ -306,47 +316,59 @@ void NativeStackSamplerMac::RecordStackFrames(StackBuffer* stack_buffer, ProfileBuilder* profile_builder) { x86_thread_state64_t thread_state; + uintptr_t stack_top; - // Copy the stack. - - uintptr_t new_stack_top = 0; - { - // IMPORTANT NOTE: Do not do ANYTHING in this in this scope that might - // allocate memory, including indirectly via use of DCHECK/CHECK or other - // logging statements. Otherwise this code can deadlock on heap locks in the - // default heap acquired by the target thread before it was suspended. - ScopedSuspendThread suspend_thread(thread_port_); - if (!suspend_thread.was_successful()) - return; - - if (!GetThreadState(thread_port_, &thread_state)) - return; - - auto stack_top = reinterpret_cast<uintptr_t>(thread_stack_base_address_); - uintptr_t stack_bottom = thread_state.__rsp; - if (stack_bottom >= stack_top) - return; - - uintptr_t stack_size = stack_top - stack_bottom; - if (stack_size > stack_buffer->size()) - return; - - profile_builder->RecordMetadata(); - - CopyStackAndRewritePointers( - reinterpret_cast<uintptr_t*>(stack_buffer->buffer()), - reinterpret_cast<uintptr_t*>(stack_bottom), - reinterpret_cast<uintptr_t*>(stack_top), &thread_state); - - new_stack_top = - reinterpret_cast<uintptr_t>(stack_buffer->buffer()) + stack_size; - } // ScopedSuspendThread + bool success = + CopyStack(thread_port_, thread_stack_base_address_, stack_buffer, + profile_builder, &thread_state, &stack_top); + if (!success) + return; if (test_delegate_) test_delegate_->OnPreStackWalk(); // Walk the stack and record it. - profile_builder->OnSampleCompleted(WalkStack(thread_state, new_stack_top)); + profile_builder->OnSampleCompleted(WalkStack(thread_state, stack_top)); +} + +// static +bool NativeStackSamplerMac::CopyStack(mach_port_t thread_port, + const void* base_address, + StackBuffer* stack_buffer, + ProfileBuilder* profile_builder, + x86_thread_state64_t* thread_state, + uintptr_t* stack_top) { + // IMPORTANT NOTE: Do not do ANYTHING in this in this scope that might + // allocate memory, including indirectly via use of DCHECK/CHECK or other + // logging statements. Otherwise this code can deadlock on heap locks acquired + // by the target thread before it was suspended. + + ScopedSuspendThread suspend_thread(thread_port); + if (!suspend_thread.was_successful()) + return false; + + if (!GetThreadState(thread_port, thread_state)) + return false; + + auto top = reinterpret_cast<uintptr_t>(base_address); + uintptr_t bottom = thread_state->__rsp; + if (bottom >= top) + return false; + + uintptr_t stack_size = top - bottom; + if (stack_size > stack_buffer->size()) + return false; + + profile_builder->RecordMetadata(); + + CopyStackAndRewritePointers( + reinterpret_cast<uintptr_t*>(stack_buffer->buffer()), + reinterpret_cast<uintptr_t*>(bottom), reinterpret_cast<uintptr_t*>(top), + thread_state); + + *stack_top = reinterpret_cast<uintptr_t>(stack_buffer->buffer()) + stack_size; + + return true; } std::vector<Frame> NativeStackSamplerMac::WalkStack(
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc index faca41c..67d9cd9 100644 --- a/base/profiler/native_stack_sampler_win.cc +++ b/base/profiler/native_stack_sampler_win.cc
@@ -157,52 +157,6 @@ #endif } -// Walks the stack represented by |context| from the current frame downwards, -// recording the instruction pointer and associated module for each frame. -std::vector<Frame> RecordStack(ModuleCache* module_cache, CONTEXT* context) { -#ifdef _WIN64 - std::vector<Frame> stack; - - // Reserve enough memory for most stacks, to avoid repeated - // allocations. Approximately 99.9% of recorded stacks are 128 frames or - // fewer. - stack.reserve(128); - - Win32StackFrameUnwinder frame_unwinder; - while (ContextPC(context)) { - const ModuleCache::Module* const module = - module_cache->GetModuleForAddress(ContextPC(context)); - - if (!module) { - // There's no loaded module containing the instruction pointer. This can - // be due to executing code that is not in a module. In particular, - // runtime-generated code associated with third-party injected DLLs - // typically is not in a module. It can also be due to the the module - // having been unloaded since we recorded the stack. In the latter case - // the function unwind information was part of the unloaded module, so - // it's not possible to unwind further. - // - // If a module was found, it's still theoretically possible for the - // detected module module to be different than the one that was loaded - // when the stack was copied (i.e. if the module was unloaded and a - // different module loaded in overlapping memory). This likely would cause - // a crash, but has not been observed in practice. - break; - } - - // Record the current frame. - stack.emplace_back(ContextPC(context), module); - - if (!frame_unwinder.TryUnwind(context, module)) - break; - } - - return stack; -#else - return {}; -#endif -} - // ScopedDisablePriorityBoost ------------------------------------------------- // Disables priority boost on a thread for the lifetime of the object. @@ -292,80 +246,6 @@ return result != 0 && (memory_info.Protect & PAGE_GUARD); } -// Suspends the thread with |thread_handle|, copies its stack and resumes the -// thread, then records the stack frames and associated modules into |stack|. -// -// IMPORTANT NOTE: No allocations from the default heap may occur in the -// ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or -// other logging statements. Otherwise this code can deadlock on heap locks in -// the default heap acquired by the target thread before it was suspended. -void SuspendThreadAndRecordStack( - HANDLE thread_handle, - const void* base_address, - void* stack_copy_buffer, - size_t stack_copy_buffer_size, - ModuleCache* module_cache, - ProfileBuilder* profile_builder, - NativeStackSamplerTestDelegate* test_delegate) { - CONTEXT thread_context = {0}; - thread_context.ContextFlags = CONTEXT_FULL; - // The stack bounds are saved to uintptr_ts for use outside - // ScopedSuspendThread, as the thread's memory is not safe to dereference - // beyond that point. - const auto top = reinterpret_cast<uintptr_t>(base_address); - uintptr_t bottom = 0u; - - { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), - "SuspendThread"); - { - ScopedSuspendThread suspend_thread(thread_handle); - - if (!suspend_thread.was_successful()) - return; - - if (!::GetThreadContext(thread_handle, &thread_context)) - return; - -#if defined(ARCH_CPU_X86_64) - bottom = thread_context.Rsp; -#elif defined(ARCH_CPU_ARM64) - bottom = thread_context.Sp; -#else - bottom = thread_context.Esp; -#endif - - if ((top - bottom) > stack_copy_buffer_size) - return; - - // Dereferencing a pointer in the guard page in a thread that doesn't own - // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a - // crash. This occurs very rarely, but reliably over the population. - if (PointsToGuardPage(bottom)) - return; - - profile_builder->RecordMetadata(); - - CopyMemoryFromStack(stack_copy_buffer, - reinterpret_cast<const void*>(bottom), top - bottom); - } - } - - if (test_delegate) - test_delegate->OnPreStackWalk(); - - { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), - "RecordStack"); - - RewritePointersToStackMemory(top, bottom, &thread_context, - stack_copy_buffer); - - profile_builder->OnSampleCompleted( - RecordStack(module_cache, &thread_context)); - } -} - } // namespace // NativeStackSamplerWin ------------------------------------------------------ @@ -382,6 +262,21 @@ ProfileBuilder* profile_builder) override; private: + // Suspends the thread with |thread_handle|, copies its stack, register + // context, and current metadata and resumes the thread. Returns true on + // success. + static bool CopyStack(HANDLE thread_handle, + const void* base_address, + StackBuffer* stack_buffer, + ProfileBuilder* profile_builder, + CONTEXT* thread_context); + + // Walks the stack represented by |thread_context|, recording and returning + // the frames. + std::vector<Frame> WalkStack(CONTEXT* thread_context); + + std::vector<Frame> RecordStack(CONTEXT* context); + win::ScopedHandle thread_handle_; ModuleCache* module_cache_; @@ -412,9 +307,126 @@ "NativeStackSamplerWin::RecordStackFrames"); DCHECK(stack_buffer); - SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, - stack_buffer->buffer(), stack_buffer->size(), - module_cache_, profile_builder, test_delegate_); + CONTEXT thread_context = {0}; + thread_context.ContextFlags = CONTEXT_FULL; + bool success = CopyStack(thread_handle_.Get(), thread_stack_base_address_, + stack_buffer, profile_builder, &thread_context); + if (!success) + return; + + if (test_delegate_) + test_delegate_->OnPreStackWalk(); + + profile_builder->OnSampleCompleted(WalkStack(&thread_context)); +} + +// Suspends the thread with |thread_handle|, copies its stack, register context, +// and current metadata and resumes the thread. Returns true on success. +// +// IMPORTANT NOTE: No allocations from the default heap may occur in the +// ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or +// other logging statements. Otherwise this code can deadlock on heap locks in +// the default heap acquired by the target thread before it was suspended. +// +// static +bool NativeStackSamplerWin::CopyStack(HANDLE thread_handle, + const void* base_address, + StackBuffer* stack_buffer, + ProfileBuilder* profile_builder, + CONTEXT* thread_context) { + // The stack bounds are saved to uintptr_ts for use outside + // ScopedSuspendThread, as the thread's memory is not safe to dereference + // beyond that point. + const auto top = reinterpret_cast<uintptr_t>(base_address); + uintptr_t bottom = 0u; + + { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), + "SuspendThread"); + { + ScopedSuspendThread suspend_thread(thread_handle); + + if (!suspend_thread.was_successful()) + return false; + + if (!::GetThreadContext(thread_handle, thread_context)) + return false; + +#if defined(ARCH_CPU_X86_64) + bottom = thread_context->Rsp; +#elif defined(ARCH_CPU_ARM64) + bottom = thread_context->Sp; +#else + bottom = thread_context->Esp; +#endif + + if ((top - bottom) > stack_buffer->size()) + return false; + + // Dereferencing a pointer in the guard page in a thread that doesn't own + // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a + // crash. This occurs very rarely, but reliably over the population. + if (PointsToGuardPage(bottom)) + return false; + + profile_builder->RecordMetadata(); + + CopyMemoryFromStack(stack_buffer->buffer(), + reinterpret_cast<const void*>(bottom), top - bottom); + } + } + + RewritePointersToStackMemory(top, bottom, thread_context, + stack_buffer->buffer()); + + return true; +} + +std::vector<Frame> NativeStackSamplerWin::WalkStack(CONTEXT* thread_context) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug"), "WalkStack"); + return RecordStack(thread_context); +} + +// Walks the stack represented by |context| from the current frame downwards, +// recording the instruction pointer and associated module for each frame. +std::vector<Frame> NativeStackSamplerWin::RecordStack(CONTEXT* context) { + std::vector<Frame> stack; + + // Reserve enough memory for most stacks, to avoid repeated + // allocations. Approximately 99.9% of recorded stacks are 128 frames or + // fewer. + stack.reserve(128); + + Win32StackFrameUnwinder frame_unwinder; + while (ContextPC(context)) { + const ModuleCache::Module* const module = + module_cache_->GetModuleForAddress(ContextPC(context)); + + if (!module) { + // There's no loaded module containing the instruction pointer. This can + // be due to executing code that is not in a module. In particular, + // runtime-generated code associated with third-party injected DLLs + // typically is not in a module. It can also be due to the the module + // having been unloaded since we recorded the stack. In the latter case + // the function unwind information was part of the unloaded module, so + // it's not possible to unwind further. + // + // If a module was found, it's still theoretically possible for the + // detected module module to be different than the one that was loaded + // when the stack was copied (i.e. if the module was unloaded and a + // different module loaded in overlapping memory). This likely would cause + // a crash, but has not been observed in practice. + break; + } + + // Record the current frame. + stack.emplace_back(ContextPC(context), module); + + if (!frame_unwinder.TryUnwind(context, module)) + break; + } + + return stack; } // NativeStackSampler ---------------------------------------------------------
diff --git a/base/profiler/win32_stack_frame_unwinder.h b/base/profiler/win32_stack_frame_unwinder.h index 0fe08e8..4fbdb1d 100644 --- a/base/profiler/win32_stack_frame_unwinder.h +++ b/base/profiler/win32_stack_frame_unwinder.h
@@ -26,17 +26,17 @@ using PRUNTIME_FUNCTION = RUNTIME_FUNCTION*; #endif // !defined(_WIN64) -#if defined(ARCH_CPU_64_BITS) inline ULONG64 ContextPC(CONTEXT* context) { #if defined(ARCH_CPU_X86_64) return context->Rip; +#elif defined(ARCH_CPU_X86) + return context->Eip; #elif defined(ARCH_CPU_ARM64) return context->Pc; #else -#error Unsupported Windows 64-bit Arch +#error Unsupported Windows Arch #endif } -#endif // Instances of this class are expected to be created and destroyed for each // stack unwinding. This class is not used while the target thread is suspended,
diff --git a/base/run_loop.h b/base/run_loop.h index f9674e1..92bc09c9 100644 --- a/base/run_loop.h +++ b/base/run_loop.h
@@ -82,8 +82,8 @@ // are present. // WARNING #2: This may return too early! For example, if used to run until an // incoming event has occurred but that event depends on a task in - // a different queue -- e.g. a system event. - // Per the warnings below, this tends to lead to flaky tests; prefer + // a different queue -- e.g. another TaskRunner or a system event. + // Per the warnings above, this tends to lead to flaky tests; prefer // QuitClosure()+Run() when at all possible. void RunUntilIdle();
diff --git a/base/task/common/intrusive_heap.h b/base/task/common/intrusive_heap.h index e791db95..084afcaf 100644 --- a/base/task/common/intrusive_heap.h +++ b/base/task/common/intrusive_heap.h
@@ -13,7 +13,7 @@ namespace base { namespace internal { -template <typename T, typename StalenessPolicy> +template <typename T> class IntrusiveHeap; // Intended as an opaque wrapper around |index_|. @@ -24,7 +24,7 @@ bool IsValid() const { return index_ != 0u; } private: - template <typename T, typename StalenessPolicy> + template <typename T> friend class IntrusiveHeap; HeapHandle(size_t index) : index_(index) {} @@ -32,21 +32,6 @@ size_t index_; }; -template <typename T> -struct DefaultStalenessPolicy { - // Mark a node if it's stale, upon bubble-up or bubble-down - void MarkIfStale(T& t, size_t old_pos, size_t new_pos) {} - - // Unmark a node as being stale - void Unmark(size_t position) {} - - // Inform the client when the heap is resized - void HeapResized(size_t size) {} - - // Obtain the number of known stale nodes - size_t NumKnownStaleNodes() const { return 0; } -}; - // A standard min-heap with the following assumptions: // 1. T has operator <= // 2. T has method void SetHeapHandle(HeapHandle handle) @@ -58,16 +43,10 @@ // // The reason IntrusiveHeap exists is to provide similar performance to // std::priority_queue while allowing removal of arbitrary elements. -// -// The StalenessPolicy allows clients to specify nodes that do not need to be -// in the heap, without explicitly deleting them. This enables appropriate -// action to be taken when there are many unnecessary nodes in the heap. -template <typename T, typename StalenessPolicy = DefaultStalenessPolicy<T>> +template <typename T> class IntrusiveHeap { public: - IntrusiveHeap() : nodes_(kMinimumHeapSize), size_(0) { - staleness_policy_.HeapResized(kMinimumHeapSize); - } + IntrusiveHeap() : nodes_(kMinimumHeapSize), size_(0) {} ~IntrusiveHeap() { for (size_t i = 1; i <= size_; i++) { @@ -79,16 +58,11 @@ size_t size() const { return size_; } - size_t NumKnownStaleNodes() const { - return staleness_policy_.NumKnownStaleNodes(); - } - void Clear() { for (size_t i = 1; i <= size_; i++) { MakeHole(i); } nodes_.resize(kMinimumHeapSize); - staleness_policy_.HeapResized(kMinimumHeapSize); size_ = 0; } @@ -101,18 +75,14 @@ DCHECK_GE(size_, 1u); MakeHole(1u); size_t top_index = size_--; - if (!empty()) { - staleness_policy_.Unmark(top_index); + if (!empty()) MoveHoleDownAndFillWithLeafElement(1u, std::move(nodes_[top_index])); - } } void insert(T&& element) { size_++; - if (size_ >= nodes_.size()) { + if (size_ >= nodes_.size()) nodes_.resize(nodes_.size() * 2); - staleness_policy_.HeapResized(nodes_.size()); - } // Notionally we have a hole in the tree at index |size_|, move this up // to find the right insertion point. MoveHoleUpAndFillWithElement(size_, std::move(element)); @@ -125,7 +95,6 @@ size_t top_index = size_--; if (empty() || top_index == handle.index_) return; - staleness_policy_.Unmark(top_index); if (nodes_[handle.index_] <= nodes_[top_index]) { MoveHoleDownAndFillWithLeafElement(handle.index_, std::move(nodes_[top_index])); @@ -166,7 +135,6 @@ }; friend class IntrusiveHeapTest; - friend class IntrusiveHeapLazyStalenessPolicyTest; size_t MoveHole(size_t new_hole_pos, size_t old_hole_pos) { DCHECK_GT(new_hole_pos, 0u); @@ -176,8 +144,6 @@ DCHECK_NE(old_hole_pos, new_hole_pos); nodes_[old_hole_pos] = std::move(nodes_[new_hole_pos]); nodes_[old_hole_pos].SetHeapHandle(HeapHandle(old_hole_pos)); - staleness_policy_.MarkIfStale(nodes_[old_hole_pos], new_hole_pos, - old_hole_pos); return new_hole_pos; } @@ -186,7 +152,6 @@ DCHECK_GT(index, 0u); DCHECK_LE(index, size_); nodes_[index].ClearHeapHandle(); - staleness_policy_.Unmark(index); } void FillHole(size_t hole, T&& element) { @@ -194,7 +159,6 @@ DCHECK_LE(hole, size_); nodes_[hole] = std::move(element); nodes_[hole].SetHeapHandle(HeapHandle(hole)); - staleness_policy_.MarkIfStale(nodes_[hole], 0u, hole); DCHECK(std::is_heap(begin(), end(), CompareNodes)); } @@ -260,7 +224,6 @@ std::vector<T> nodes_; // NOTE we use 1-based indexing size_t size_; - StalenessPolicy staleness_policy_; }; } // namespace internal
diff --git a/base/task/common/intrusive_heap_lazy_staleness_policy.h b/base/task/common/intrusive_heap_lazy_staleness_policy.h deleted file mode 100644 index 8461746..0000000 --- a/base/task/common/intrusive_heap_lazy_staleness_policy.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_COMMON_INTRUSIVE_HEAP_LAZY_STALENESS_POLICY_H_ -#define BASE_TASK_COMMON_INTRUSIVE_HEAP_LAZY_STALENESS_POLICY_H_ - -#include <vector> - -namespace base { -namespace internal { - -// Discovers stale nodes upon bubble-up or bubble-down. -// T must implement IsStale() in order to use this policy. -template <typename T> -struct LazyStalenessPolicy { - LazyStalenessPolicy() : num_known_stale_nodes_(0) {} - - ~LazyStalenessPolicy() = default; - - void MarkIfStale(T& t, size_t old_pos, size_t new_pos) { - if (!t.IsStale()) { - Unmark(new_pos); - return; - } - - Unmark(old_pos); - if (!is_stale_[new_pos]) - num_known_stale_nodes_++; - - is_stale_[new_pos] = true; - } - - void Unmark(size_t position) { - if (position == 0 || !is_stale_[position]) - return; - - is_stale_[position] = false; - num_known_stale_nodes_--; - } - - void HeapResized(size_t size) { is_stale_.resize(size); } - - size_t NumKnownStaleNodes() const { return num_known_stale_nodes_; } - - private: - friend class IntrusiveHeapLazyStalenessPolicyTest; - - size_t num_known_stale_nodes_; - std::vector<bool> is_stale_; -}; - -} // namespace internal -} // namespace base - -#endif // BASE_TASK_COMMON_INTRUSIVE_HEAP_LAZY_STALENESS_POLICY_H_
diff --git a/base/task/common/intrusive_heap_lazy_staleness_policy_unittest.cc b/base/task/common/intrusive_heap_lazy_staleness_policy_unittest.cc deleted file mode 100644 index a628d88..0000000 --- a/base/task/common/intrusive_heap_lazy_staleness_policy_unittest.cc +++ /dev/null
@@ -1,403 +0,0 @@ -// Copyright 2016 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 <vector> - -#include "base/task/common/intrusive_heap.h" -#include "base/task/common/intrusive_heap_lazy_staleness_policy.h" -#include "base/task/common/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace internal { - -using TestElementStalenessPolicy = LazyStalenessPolicy<test::TestElement>; - -class IntrusiveHeapLazyStalenessPolicyTest : public testing::Test { - protected: - bool HeapIsNodeStaleAtPosition( - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap, - size_t position) { - return heap.staleness_policy_.is_stale_[position]; - } -}; - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessNoStaleElements) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - heap.insert({3, nullptr}); - heap.insert({23, nullptr}); - - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); - - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessClear) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - - size_t stale_positions[3] = {1, 2, 4}; - for (auto stale_position : stale_positions) { - const_cast<test::TestElement*>(heap.begin() + stale_position - 1)->stale = - true; - } - - heap.insert({1, nullptr}); - heap.Clear(); - - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessPop) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - heap.insert({2, nullptr, true}); - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - heap.Pop(); - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessInsert) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - - size_t stale_positions[4] = {1, 2, 4, 7}; - for (auto stale_position : stale_positions) { - const_cast<test::TestElement*>(heap.begin() + stale_position - 1)->stale = - true; - } - - // Heap: - // - // 2 - // / \ - // 7 9 - // /\ /\ - // 10 8 15 22 - // - // 2, 7, 10, 22 are stale. - - heap.insert({1, nullptr}); - - // Inserting 1 moves 2, 7 and 10. Hence, 2, 7 and 10 are known stale - // nodes after the insertion. 22 has not been detected. - - size_t stale_count = 0; - for (size_t i = 1; i <= heap.size(); i++) { - bool stale_node = (heap.begin() + i - 1)->stale; - bool marked_stale = HeapIsNodeStaleAtPosition(heap, i); - if (!stale_node) - EXPECT_FALSE(marked_stale); - if (marked_stale) - stale_count++; - } - - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, 1u)); - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, 2u)); - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, 3u)); - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, 4u)); - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, 5u)); - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, 6u)); - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, 7u)); - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, 8u)); - EXPECT_EQ(3u, stale_count); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessErase) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - HeapHandle index7; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, nullptr}); - heap.insert({7, &index7}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - - const_cast<test::TestElement&>(heap.at(index7)).stale = true; - - // Heap: - // - // 2 - // / \ - // 7 9 - // /\ /\ - // 10 8 15 22 - // - // 7 is stale, but not marked stale by the heap. - - heap.insert({1, nullptr}); - - // Heap: - // - // 1 - // / \ - // 2 9 - // /\ /\ - // 7 8 15 22 - // / - // 10 - // - // 7 is a known stale node after insertion. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - heap.erase(index7); - - // Heap: - // - // 1 - // / \ - // 2 9 - // /\ /\ - // 10 8 15 22 - // - // No stale nodes remain in the heap. - - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessReplaceMinWithMin) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - heap.insert({2, nullptr, true}); - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - heap.ReplaceMin({1, nullptr}); - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, - LazyStalenessReplaceMinBubbleDown) { - HeapHandle index7; - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, nullptr}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({7, &index7}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - heap.insert({2, nullptr, true}); - - // Heap: - // - // 2 - // / \ - // 8 7 - // / \ / \ - // 10 15 22 9 - // - // 2 is a known stale node. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - const_cast<test::TestElement&>(heap.at(index7)).stale = true; - heap.ReplaceMin({23, nullptr}); - - // Heap: - // - // 7 - // / \ - // 8 9 - // / \ / \ - // 10 15 22 23 - // - // 7 is a known stale node, as it was detected when bubbling-down 23. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, 1u)); - for (size_t i = 2; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessChangeKeyInPlace) { - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - HeapHandle index9; - - heap.insert({9, &index9, true}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - heap.insert({2, nullptr}); - - // Heap: - // - // 2 - // / \ - // 8 7 - // / \ / \ - // 10 15 22 9 - // - // 9 is a known stale node. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - heap.ChangeKey(index9, {14, nullptr}); - - // Heap: - // - // 2 - // / \ - // 8 7 - // / \ / \ - // 10 15 22 14 - // - // No stale nodes remain in the heap. - - EXPECT_EQ(0u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessChangeKeyBubbleDown) { - HeapHandle index9; - HeapHandle index15; - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, &index9, true}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, nullptr}); - heap.insert({7, nullptr}); - heap.insert({15, &index15}); - heap.insert({22, nullptr}); - - // Heap: - // - // 2 - // / \ - // 7 9 - // /\ /\ - // 10 8 15 22 - // - // 9 is a known stale node. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - const_cast<test::TestElement&>(heap.at(index15)).stale = true; - heap.ChangeKey(index9, {23, nullptr}); - - // Heap: - // - // 2 - // / \ - // 7 15 - // /\ /\ - // 10 8 23 22 - // - // 15 is a known stale node, as it was detected when bubbling-down 23. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) { - if (i == 3u) - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, i)); - else - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); - } -} - -TEST_F(IntrusiveHeapLazyStalenessPolicyTest, LazyStalenessChangeKeyBubbleUp) { - HeapHandle index9; - HeapHandle index2; - IntrusiveHeap<test::TestElement, TestElementStalenessPolicy> heap; - - heap.insert({9, &index9, true}); - heap.insert({10, nullptr}); - heap.insert({8, nullptr}); - heap.insert({2, &index2}); - heap.insert({7, nullptr}); - heap.insert({15, nullptr}); - heap.insert({22, nullptr}); - - // Heap: - // - // 2 - // / \ - // 7 9 - // /\ /\ - // 10 8 15 22 - // - // 9 is a known stale node. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - const_cast<test::TestElement&>(heap.at(index2)).stale = true; - heap.ChangeKey(index9, {1, nullptr}); - - // Heap: - // - // 1 - // / \ - // 7 2 - // /\ /\ - // 10 8 15 22 - // - // 2 is a known stale node, as it was detected when bubbling-up 1. - - EXPECT_EQ(1u, heap.NumKnownStaleNodes()); - - for (size_t i = 1; i <= heap.size(); i++) { - if (i == 3u) - EXPECT_TRUE(HeapIsNodeStaleAtPosition(heap, i)); - else - EXPECT_FALSE(HeapIsNodeStaleAtPosition(heap, i)); - } -} - -} // namespace internal -} // namespace base
diff --git a/base/task/common/intrusive_heap_unittest.cc b/base/task/common/intrusive_heap_unittest.cc index 357873f..0d2add60 100644 --- a/base/task/common/intrusive_heap_unittest.cc +++ b/base/task/common/intrusive_heap_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/task/common/intrusive_heap.h" -#include "base/task/common/test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -11,23 +10,43 @@ namespace base { namespace internal { +namespace { + +struct TestElement { + int key; + HeapHandle* handle; + + bool operator<=(const TestElement& other) const { return key <= other.key; } + + void SetHeapHandle(HeapHandle h) { + if (handle) + *handle = h; + } + + void ClearHeapHandle() { + if (handle) + *handle = HeapHandle(); + } +}; + +} // namespace + class IntrusiveHeapTest : public testing::Test { protected: - static bool CompareNodes(const test::TestElement& a, - const test::TestElement& b) { - return IntrusiveHeap<test::TestElement>::CompareNodes(a, b); + static bool CompareNodes(const TestElement& a, const TestElement& b) { + return IntrusiveHeap<TestElement>::CompareNodes(a, b); } }; TEST_F(IntrusiveHeapTest, Basic) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; EXPECT_TRUE(heap.empty()); EXPECT_EQ(0u, heap.size()); } TEST_F(IntrusiveHeapTest, Clear) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index1; heap.insert({11, &index1}); @@ -43,7 +62,7 @@ HeapHandle index1; { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; heap.insert({11, &index1}); EXPECT_EQ(1u, heap.size()); @@ -54,7 +73,7 @@ } TEST_F(IntrusiveHeapTest, Min) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; heap.insert({9, nullptr}); heap.insert({10, nullptr}); @@ -71,7 +90,7 @@ } TEST_F(IntrusiveHeapTest, InsertAscending) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 50; i++) heap.insert({i, nullptr}); @@ -81,7 +100,7 @@ } TEST_F(IntrusiveHeapTest, InsertDescending) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 50; i++) heap.insert({50 - i, nullptr}); @@ -96,7 +115,7 @@ HeapHandle index3; HeapHandle index2; HeapHandle index1; - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; EXPECT_FALSE(index1.IsValid()); EXPECT_FALSE(index2.IsValid()); @@ -120,7 +139,7 @@ } TEST_F(IntrusiveHeapTest, Pop) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index1; HeapHandle index2; @@ -142,7 +161,7 @@ } TEST_F(IntrusiveHeapTest, PopMany) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 500; i++) heap.insert({i, nullptr}); @@ -157,7 +176,7 @@ } TEST_F(IntrusiveHeapTest, Erase) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index12; @@ -185,7 +204,7 @@ } TEST_F(IntrusiveHeapTest, ReplaceMin) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 500; i++) heap.insert({500 - i, nullptr}); @@ -199,7 +218,7 @@ } TEST_F(IntrusiveHeapTest, ReplaceMinWithNonLeafNode) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 50; i++) { heap.insert({i, nullptr}); @@ -226,7 +245,7 @@ HeapHandle index[100]; for (int j = -1; j <= 201; j += 2) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (size_t i = 0; i < 100; i++) { heap.insert({static_cast<int>(i) * 2, &index[i]}); } @@ -245,7 +264,7 @@ } TEST_F(IntrusiveHeapTest, ChangeKeyUp) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index[10]; for (size_t i = 0; i < 10; i++) { @@ -264,7 +283,7 @@ } TEST_F(IntrusiveHeapTest, ChangeKeyUpButDoesntMove) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index[10]; for (size_t i = 0; i < 10; i++) { @@ -283,7 +302,7 @@ } TEST_F(IntrusiveHeapTest, ChangeKeyDown) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index[10]; for (size_t i = 0; i < 10; i++) { @@ -302,7 +321,7 @@ } TEST_F(IntrusiveHeapTest, ChangeKeyDownButDoesntMove) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; HeapHandle index[10]; for (size_t i = 0; i < 10; i++) { @@ -324,7 +343,7 @@ HeapHandle index[100]; for (int j = -1; j <= 201; j += 2) { - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (size_t i = 0; i < 100; i++) { heap.insert({static_cast<int>(i) * 2, &index[i]}); } @@ -343,7 +362,7 @@ } TEST_F(IntrusiveHeapTest, CompareNodes) { - test::TestElement five{5, nullptr}, six{6, nullptr}; + TestElement five{5, nullptr}, six{6, nullptr}; // Check that we have a strict comparator, otherwise std::is_heap() // (used in DCHECK) may fail. See http://crbug.com/661080. @@ -355,7 +374,7 @@ TEST_F(IntrusiveHeapTest, At) { HeapHandle index[10]; - IntrusiveHeap<test::TestElement> heap; + IntrusiveHeap<TestElement> heap; for (int i = 0; i < 10; i++) heap.insert({static_cast<int>(i ^ (i + 1)), &index[i]});
diff --git a/base/task/common/task_annotator.cc b/base/task/common/task_annotator.cc index ae33dae0..5b74def 100644 --- a/base/task/common/task_annotator.cc +++ b/base/task/common/task_annotator.cc
@@ -30,6 +30,10 @@ } // namespace +const PendingTask* TaskAnnotator::CurrentTaskForThread() { + return GetTLSForCurrentPendingTask()->Get(); +} + TaskAnnotator::TaskAnnotator() = default; TaskAnnotator::~TaskAnnotator() = default; @@ -42,21 +46,25 @@ DCHECK(task_queue_name); TRACE_EVENT_WITH_FLOW1( TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), trace_event_name, - TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), TRACE_EVENT_FLAG_FLOW_OUT, + TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), + TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_DISALLOW_POSTTASK, "task_queue_name", task_queue_name); DCHECK(!pending_task->task_backtrace[0]) << "Task backtrace was already set, task posted twice??"; - if (!pending_task->task_backtrace[0]) { - const PendingTask* parent_task = GetTLSForCurrentPendingTask()->Get(); - if (parent_task) { - pending_task->task_backtrace[0] = - parent_task->posted_from.program_counter(); - std::copy(parent_task->task_backtrace.begin(), - parent_task->task_backtrace.end() - 1, - pending_task->task_backtrace.begin() + 1); - } - } + if (pending_task->task_backtrace[0]) + return; + + const PendingTask* parent_task = GetTLSForCurrentPendingTask()->Get(); + if (!parent_task) + return; + pending_task->task_backtrace[0] = parent_task->posted_from.program_counter(); + std::copy(parent_task->task_backtrace.begin(), + parent_task->task_backtrace.end() - 1, + pending_task->task_backtrace.begin() + 1); + pending_task->task_backtrace_overflow = + parent_task->task_backtrace_overflow || + parent_task->task_backtrace.back() != nullptr; } void TaskAnnotator::RunTask(const char* trace_event_name, @@ -70,13 +78,18 @@ TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), trace_event_name, TRACE_ID_MANGLE(GetTaskTraceID(*pending_task)), TRACE_EVENT_FLAG_FLOW_IN); + // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event + // to determine long tasks. + // See https://crbug.com/681863 and https://crbug.com/874982 + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "RunTask"); + // Before running the task, store the task backtrace with the chain of // PostTasks that resulted in this call and deliberately alias it to ensure // it is on the stack if the task crashes. Be careful not to assume that the // variable itself will have the expected value when displayed by the // optimizer in an optimized build. Look at a memory dump of the stack. static constexpr int kStackTaskTraceSnapshotSize = - std::tuple_size<decltype(pending_task->task_backtrace)>::value + 3; + PendingTask::kTaskBacktraceLength + 3; std::array<const void*, kStackTaskTraceSnapshotSize> task_backtrace; // Store a marker to locate |task_backtrace| content easily on a memory
diff --git a/base/task/common/task_annotator.h b/base/task/common/task_annotator.h index ac4abf9..4a19cdfd 100644 --- a/base/task/common/task_annotator.h +++ b/base/task/common/task_annotator.h
@@ -24,6 +24,8 @@ virtual void BeforeRunTask(const PendingTask* pending_task) = 0; }; + static const PendingTask* CurrentTaskForThread(); + TaskAnnotator(); ~TaskAnnotator();
diff --git a/base/task/common/task_annotator_unittest.cc b/base/task/common/task_annotator_unittest.cc index 176a19f..697d968 100644 --- a/base/task/common/task_annotator_unittest.cc +++ b/base/task/common/task_annotator_unittest.cc
@@ -125,7 +125,8 @@ Lock on_before_run_task_lock_; Location last_posted_from_ = {}; - std::array<const void*, 4> last_task_backtrace_ = {}; + std::array<const void*, PendingTask::kTaskBacktraceLength> + last_task_backtrace_ = {}; DISALLOW_COPY_AND_ASSIGN(TaskAnnotatorBacktraceIntegrationTest); };
diff --git a/base/task/common/test_utils.h b/base/task/common/test_utils.h deleted file mode 100644 index c294c40..0000000 --- a/base/task/common/test_utils.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_COMMON_TEST_UTILS_H_ -#define BASE_TASK_COMMON_TEST_UTILS_H_ - -#include "base/task/common/intrusive_heap.h" - -namespace base { -namespace internal { -namespace test { - -struct TestElement { - int key; - HeapHandle* handle; - bool stale = false; - - bool operator<=(const TestElement& other) const { return key <= other.key; } - - void SetHeapHandle(HeapHandle h) { - if (handle) - *handle = h; - } - - void ClearHeapHandle() { - if (handle) - *handle = HeapHandle(); - } - - bool IsStale() { return stale; } -}; - -} // namespace test -} // namespace internal -} // namespace base - -#endif // BASE_TASK_COMMON_TEST_UTILS_H_
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc index c98c988..20f5277 100644 --- a/base/task/sequence_manager/thread_controller_impl.cc +++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -194,10 +194,6 @@ { TRACE_TASK_EXECUTION("ThreadControllerImpl::RunTask", *task); - // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event - // to determine long tasks. - // See https://crbug.com/681863 and https://crbug.com/874982 - TRACE_EVENT0("devtools.timeline", "RunTask"); task_annotator_.RunTask("ThreadControllerImpl::RunTask", &*task); }
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index 2a87cc21..edb4411 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -332,10 +332,6 @@ work_id_provider_->IncrementWorkId(); TRACE_TASK_EXECUTION("ThreadController::Task", *task); - // Trace-parsing tools (DevTools, Lighthouse, etc) consume this event - // to determine long tasks. - // See https://crbug.com/681863 and https://crbug.com/874982 - TRACE_EVENT0("devtools.timeline", "RunTask"); task_annotator_.RunTask("ThreadController::Task", &*task); *ran_task = true;
diff --git a/base/task/task_scheduler/delayed_task_manager.cc b/base/task/task_scheduler/delayed_task_manager.cc index af32362..0f5bede5 100644 --- a/base/task/task_scheduler/delayed_task_manager.cc +++ b/base/task/task_scheduler/delayed_task_manager.cc
@@ -8,8 +8,6 @@ #include "base/bind.h" #include "base/logging.h" -#include "base/metrics/histogram_functions.h" -#include "base/strings/string_util.h" #include "base/task/post_task.h" #include "base/task/task_scheduler/task.h" #include "base/task_runner.h" @@ -17,16 +15,6 @@ namespace base { namespace internal { -// The UMA histogram that logs a lower-bound number of cancelled tasks in the -// manager. -const char kNumCancelledDelayedTasksHistogram[] = - "TaskScheduler.NumCancelledDelayedTasks"; - -// The UMA histogram that logs a lower-bound percentage of cancelled tasks in -// the manager. -const char kNumPercentCancelledDelayedTasksHistogram[] = - "TaskScheduler.PercentCancelledDelayedTasks"; - DelayedTaskManager::DelayedTask::DelayedTask() = default; DelayedTaskManager::DelayedTask::DelayedTask(Task task, @@ -54,17 +42,11 @@ scheduled_ = true; } -bool DelayedTaskManager::DelayedTask::IsStale() const { - return !task.task.MaybeValid(); -} - DelayedTaskManager::DelayedTaskManager( - StringPiece histogram_label, std::unique_ptr<const TickClock> tick_clock) : process_ripe_tasks_closure_( BindRepeating(&DelayedTaskManager::ProcessRipeTasks, Unretained(this))), - histogram_label_(histogram_label), tick_clock_(std::move(tick_clock)) { DCHECK(tick_clock_); } @@ -107,23 +89,6 @@ ScheduleProcessRipeTasksOnServiceThread(process_ripe_tasks_time); } -void DelayedTaskManager::ReportHeartbeatMetrics() const { - size_t num_cancelled_tasks = delayed_task_queue_.NumKnownStaleNodes(); - size_t num_tasks = delayed_task_queue_.size(); - int percent_cancelled_tasks = - (num_tasks == 0) - ? 0 - : static_cast<int>((100 * num_cancelled_tasks) / num_tasks); - - UmaHistogramCounts100( - JoinString({kNumCancelledDelayedTasksHistogram, histogram_label_}, "."), - static_cast<int>(num_cancelled_tasks)); - UmaHistogramPercentage( - JoinString({kNumPercentCancelledDelayedTasksHistogram, histogram_label_}, - "."), - percent_cancelled_tasks); -} - void DelayedTaskManager::ProcessRipeTasks() { std::vector<DelayedTask> ripe_delayed_tasks; TimeTicks process_ripe_tasks_time;
diff --git a/base/task/task_scheduler/delayed_task_manager.h b/base/task/task_scheduler/delayed_task_manager.h index 63640a0d..0e0fd3b 100644 --- a/base/task/task_scheduler/delayed_task_manager.h +++ b/base/task/task_scheduler/delayed_task_manager.h
@@ -6,7 +6,6 @@ #define BASE_TASK_TASK_SCHEDULER_DELAYED_TASK_MANAGER_H_ #include <memory> -#include <string> #include <utility> #include "base/base_export.h" @@ -14,10 +13,8 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/strings/string_piece.h" #include "base/synchronization/atomic_flag.h" #include "base/task/common/intrusive_heap.h" -#include "base/task/common/intrusive_heap_lazy_staleness_policy.h" #include "base/task/task_scheduler/scheduler_lock.h" #include "base/task/task_scheduler/task.h" #include "base/time/default_tick_clock.h" @@ -38,8 +35,7 @@ using PostTaskNowCallback = OnceCallback<void(Task task)>; // |tick_clock| can be specified for testing. - DelayedTaskManager(StringPiece histogram_label = "", - std::unique_ptr<const TickClock> tick_clock = + DelayedTaskManager(std::unique_ptr<const TickClock> tick_clock = std::make_unique<DefaultTickClock>()); ~DelayedTaskManager(); @@ -53,8 +49,6 @@ // |task| is ripe for execution. void AddDelayedTask(Task task, PostTaskNowCallback post_task_now_callback); - void ReportHeartbeatMetrics() const; - private: struct DelayedTask { DelayedTask(); @@ -84,9 +78,6 @@ // Required by IntrusiveHeap. void ClearHeapHandle() {} - // Required by LazyStalenessPolicy. - bool IsStale() const; - private: bool scheduled_ = false; DISALLOW_COPY_AND_ASSIGN(DelayedTask); @@ -108,15 +99,11 @@ const RepeatingClosure process_ripe_tasks_closure_; - // Used to label histograms for this class. - const std::string histogram_label_; - const std::unique_ptr<const TickClock> tick_clock_; scoped_refptr<TaskRunner> service_thread_task_runner_; - IntrusiveHeap<DelayedTask, LazyStalenessPolicy<DelayedTask>> - delayed_task_queue_; + IntrusiveHeap<DelayedTask> delayed_task_queue_; // Synchronizes access to |delayed_task_queue_| and the setting of // |service_thread_task_runner|. Once |service_thread_task_runner_| is set,
diff --git a/base/task/task_scheduler/delayed_task_manager_unittest.cc b/base/task/task_scheduler/delayed_task_manager_unittest.cc index 816233f4..1ea05f99 100644 --- a/base/task/task_scheduler/delayed_task_manager_unittest.cc +++ b/base/task/task_scheduler/delayed_task_manager_unittest.cc
@@ -13,7 +13,6 @@ #include "base/synchronization/waitable_event.h" #include "base/task/task_scheduler/task.h" #include "base/test/bind_test_util.h" -#include "base/test/metrics/histogram_tester.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread.h" #include "base/time/time.h" @@ -50,7 +49,6 @@ protected: TaskSchedulerDelayedTaskManagerTest() : delayed_task_manager_( - "Test", service_thread_task_runner_->DeprecatedGetMockTickClock()), task_(ConstructMockedTask( mock_task_, @@ -215,16 +213,5 @@ service_thread_task_runner_->FastForwardBy(kLongDelay); } -TEST_F(TaskSchedulerDelayedTaskManagerTest, ReportHeartbeatMetrics) { - HistogramTester tester; - delayed_task_manager_.ReportHeartbeatMetrics(); - EXPECT_FALSE( - tester.GetAllSamples("TaskScheduler.NumCancelledDelayedTasks.Test") - .empty()); - EXPECT_FALSE( - tester.GetAllSamples("TaskScheduler.PercentCancelledDelayedTasks.Test") - .empty()); -} - } // namespace internal } // namespace base
diff --git a/base/task/task_scheduler/platform_native_worker_pool_win.cc b/base/task/task_scheduler/platform_native_worker_pool_win.cc index 8859f1a4..cbdc498 100644 --- a/base/task/task_scheduler/platform_native_worker_pool_win.cc +++ b/base/task/task_scheduler/platform_native_worker_pool_win.cc
@@ -125,6 +125,12 @@ return priority_queue_.PopSequence(); } +void PlatformNativeWorkerPoolWin::UpdateSortKey( + SequenceAndTransaction sequence_and_transaction) { + ScopedWorkersExecutor executor(this); + UpdateSortKeyImpl(&executor, std::move(sequence_and_transaction)); +} + void PlatformNativeWorkerPoolWin::PushSequenceAndWakeUpWorkers( SequenceAndTransaction sequence_and_transaction) { ScopedWorkersExecutor executor(this);
diff --git a/base/task/task_scheduler/platform_native_worker_pool_win.h b/base/task/task_scheduler/platform_native_worker_pool_win.h index 48e9cc7e..71845ac7 100644 --- a/base/task/task_scheduler/platform_native_worker_pool_win.h +++ b/base/task/task_scheduler/platform_native_worker_pool_win.h
@@ -53,6 +53,7 @@ void* scheduler_worker_pool_windows_impl, PTP_WORK); // SchedulerWorkerPool: + void UpdateSortKey(SequenceAndTransaction sequence_and_transaction) override; void PushSequenceAndWakeUpWorkers( SequenceAndTransaction sequence_and_transaction) override; void EnsureEnoughWorkersLockRequired(BaseScopedWorkersExecutor* executor)
diff --git a/base/task/task_scheduler/scheduler_worker_pool.cc b/base/task/task_scheduler/scheduler_worker_pool.cc index 5765b69..96cd114 100644 --- a/base/task/task_scheduler/scheduler_worker_pool.cc +++ b/base/task/task_scheduler/scheduler_worker_pool.cc
@@ -96,15 +96,6 @@ } } -void SchedulerWorkerPool::UpdateSortKey( - SequenceAndTransaction sequence_and_transaction) { - // TODO(fdoray): A worker should be woken up when the priority of a - // BEST_EFFORT task is increased and |num_running_best_effort_tasks_| is - // equal to |max_best_effort_tasks_|. - AutoSchedulerLock auto_lock(lock_); - priority_queue_.UpdateSortKey(std::move(sequence_and_transaction)); -} - bool SchedulerWorkerPool::RemoveSequence(scoped_refptr<Sequence> sequence) { AutoSchedulerLock auto_lock(lock_); return priority_queue_.RemoveSequence(std::move(sequence)); @@ -131,6 +122,14 @@ } } +void SchedulerWorkerPool::UpdateSortKeyImpl( + BaseScopedWorkersExecutor* executor, + SequenceAndTransaction sequence_and_transaction) { + AutoSchedulerLock auto_lock(lock_); + priority_queue_.UpdateSortKey(std::move(sequence_and_transaction)); + EnsureEnoughWorkersLockRequired(executor); +} + void SchedulerWorkerPool::PushSequenceAndWakeUpWorkersImpl( BaseScopedWorkersExecutor* executor, SequenceAndTransaction sequence_and_transaction) {
diff --git a/base/task/task_scheduler/scheduler_worker_pool.h b/base/task/task_scheduler/scheduler_worker_pool.h index 977f3d57..d5cb31e 100644 --- a/base/task/task_scheduler/scheduler_worker_pool.h +++ b/base/task/task_scheduler/scheduler_worker_pool.h
@@ -55,15 +55,19 @@ // Returns true if the worker pool is registered in TLS. bool IsBoundToCurrentThread() const; - // Updates the position of the Sequence in |sequence_and_transaction| in - // |shared_priority_queue| based on the Sequence's current traits. - void UpdateSortKey(SequenceAndTransaction sequence_and_transaction); - // Removes |sequence| from |priority_queue_|. Returns true if successful, or // false if |sequence| is not currently in |priority_queue_|, such as when a // worker is running a task from it. bool RemoveSequence(scoped_refptr<Sequence> sequence); + // Updates the position of the Sequence in |sequence_and_transaction| in + // this pool's PriorityQueue based on the Sequence's current traits. + // + // Implementations should instantiate a concrete ScopedWorkersExecutor and + // invoke UpdateSortKeyImpl(). + virtual void UpdateSortKey( + SequenceAndTransaction sequence_and_transaction) = 0; + // Pushes the Sequence in |sequence_and_transaction| into this pool's // PriorityQueue and wakes up workers as appropriate. // @@ -135,7 +139,9 @@ SequenceAndTransaction sequence_and_transaction) EXCLUSIVE_LOCKS_REQUIRED(lock_); - // Must be invoked by implementations of PushSequenceAndWakeUpWorkers(). + // Must be invoked by implementations of the corresponding non-Impl() methods. + void UpdateSortKeyImpl(BaseScopedWorkersExecutor* executor, + SequenceAndTransaction sequence_and_transaction); void PushSequenceAndWakeUpWorkersImpl( BaseScopedWorkersExecutor* executor, SequenceAndTransaction sequence_and_transaction);
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.cc b/base/task/task_scheduler/scheduler_worker_pool_impl.cc index 1394d39..e961e30 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.cc
@@ -442,6 +442,12 @@ DCHECK(workers_.empty()); } +void SchedulerWorkerPoolImpl::UpdateSortKey( + SequenceAndTransaction sequence_and_transaction) { + ScopedWorkersExecutor executor(this); + UpdateSortKeyImpl(&executor, std::move(sequence_and_transaction)); +} + void SchedulerWorkerPoolImpl::PushSequenceAndWakeUpWorkers( SequenceAndTransaction sequence_and_transaction) { ScopedWorkersExecutor executor(this);
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.h b/base/task/task_scheduler/scheduler_worker_pool_impl.h index 9a16d1a..96d5e21 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.h
@@ -154,6 +154,7 @@ ThreadBlockUnblockPremature); // SchedulerWorkerPool: + void UpdateSortKey(SequenceAndTransaction sequence_and_transaction) override; void PushSequenceAndWakeUpWorkers( SequenceAndTransaction sequence_and_transaction) override; void EnsureEnoughWorkersLockRequired(BaseScopedWorkersExecutor* executor)
diff --git a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc index 945481b7..b138c34 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
@@ -6,11 +6,13 @@ #include <memory> +#include "base/barrier_closure.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" #include "base/memory/ref_counted.h" #include "base/task/task_scheduler/delayed_task_manager.h" +#include "base/task/task_scheduler/scheduler_sequenced_task_runner.h" #include "base/task/task_scheduler/scheduler_worker_pool_impl.h" #include "base/task/task_scheduler/scheduler_worker_pool_params.h" #include "base/task/task_scheduler/task_tracker.h" @@ -18,10 +20,13 @@ #include "base/task/task_scheduler/test_utils.h" #include "base/task/task_traits.h" #include "base/task_runner.h" +#include "base/test/bind_test_util.h" #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" +#include "base/threading/scoped_blocking_call.h" #include "base/threading/simple_thread.h" #include "base/threading/thread.h" +#include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -334,6 +339,67 @@ task_tracker_.FlushForTesting(); } +// Verify that the maximum number of BEST_EFFORT tasks that can run concurrently +// in a pool does not affect Sequences with a priority that was increased from +// BEST_EFFORT to USER_BLOCKING. +TEST_P(TaskSchedulerWorkerPoolTest, UpdatePriorityBestEffortToUserBlocking) { + StartWorkerPool(); + + SchedulerLock num_tasks_running_lock; + std::unique_ptr<ConditionVariable> num_tasks_running_cv = + num_tasks_running_lock.CreateConditionVariable(); + size_t num_tasks_running = 0; + + // Post |kMaxTasks| BEST_EFFORT tasks that block until they all start running. + std::vector<scoped_refptr<SchedulerSequencedTaskRunner>> task_runners; + + for (size_t i = 0; i < kMaxTasks; ++i) { + task_runners.push_back(MakeRefCounted<SchedulerSequencedTaskRunner>( + TaskTraits(TaskPriority::BEST_EFFORT), + &mock_scheduler_task_runner_delegate_)); + task_runners.back()->PostTask( + FROM_HERE, BindLambdaForTesting([&]() { + // Increment the number of tasks running. + { + AutoSchedulerLock auto_lock(num_tasks_running_lock); + ++num_tasks_running; + } + num_tasks_running_cv->Broadcast(); + + // Wait until all posted tasks are running. + AutoSchedulerLock auto_lock(num_tasks_running_lock); + while (num_tasks_running < kMaxTasks) { + ScopedClearBlockingObserverForTesting clear_blocking_observer; + ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives; + num_tasks_running_cv->Wait(); + } + })); + } + + // Wait until |kMaxBestEffort| tasks start running. + { + AutoSchedulerLock auto_lock(num_tasks_running_lock); + while (num_tasks_running < kMaxBestEffortTasks) + num_tasks_running_cv->Wait(); + } + + // Update the priority of all TaskRunners to USER_BLOCKING. + for (size_t i = 0; i < kMaxTasks; ++i) + task_runners[i]->UpdatePriority(TaskPriority::USER_BLOCKING); + + // Wait until all posted tasks start running. This should not block forever, + // even in a pool that enforces a maximum number of concurrent BEST_EFFORT + // tasks lower than |kMaxTasks|. + static_assert(kMaxBestEffortTasks < kMaxTasks, ""); + { + AutoSchedulerLock auto_lock(num_tasks_running_lock); + while (num_tasks_running < kMaxTasks) + num_tasks_running_cv->Wait(); + } + + task_tracker_.FlushForTesting(); +} + INSTANTIATE_TEST_SUITE_P(GenericParallel, TaskSchedulerWorkerPoolTest, ::testing::Values(PoolExecutionType{
diff --git a/base/task/task_scheduler/task_scheduler_impl.cc b/base/task/task_scheduler/task_scheduler_impl.cc index f8c1eac..f4f7e57 100644 --- a/base/task/task_scheduler/task_scheduler_impl.cc +++ b/base/task/task_scheduler/task_scheduler_impl.cc
@@ -52,7 +52,6 @@ task_tracker_.get(), BindRepeating(&TaskSchedulerImpl::ReportHeartbeatMetrics, Unretained(this)))), - delayed_task_manager_(histogram_label), single_thread_task_runner_manager_(task_tracker_->GetTrackedRef(), &delayed_task_manager_), tracked_ref_factory_(this) {
diff --git a/base/task/task_scheduler/test_utils.cc b/base/task/task_scheduler/test_utils.cc index aa99eee0..4b1f71f9 100644 --- a/base/task/task_scheduler/test_utils.cc +++ b/base/task/task_scheduler/test_utils.cc
@@ -143,7 +143,12 @@ void MockSchedulerTaskRunnerDelegate::UpdatePriority( scoped_refptr<Sequence> sequence, - TaskPriority priority) {} + TaskPriority priority) { + auto sequence_and_transaction = + SequenceAndTransaction::FromSequence(std::move(sequence)); + sequence_and_transaction.transaction.UpdatePriority(priority); + worker_pool_->UpdateSortKey(std::move(sequence_and_transaction)); +} void MockSchedulerTaskRunnerDelegate::SetWorkerPool( SchedulerWorkerPool* worker_pool) {
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h index 5613c1e2..2716eea 100644 --- a/base/test/scoped_task_environment.h +++ b/base/test/scoped_task_environment.h
@@ -162,6 +162,20 @@ // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the // TaskScheduler's non-delayed queues are empty. + // While RunUntilIdle() is quite practical and sometimes even necessary -- for + // example, to flush all tasks bound to Unretained() state before destroying + // test members -- it should be used with caution per the following warnings: + // + // WARNING #1: This may run long (flakily timeout) and even never return! Do + // not use this when repeating tasks such as animated web pages + // are present. + // WARNING #2: This may return too early! For example, if used to run until an + // incoming event has occurred but that event depends on a task in + // a different queue -- e.g. a standalone base::Thread or a system + // event. + // + // As such, prefer RunLoop::Run() with an explicit RunLoop::QuitClosure() when + // possible. void RunUntilIdle(); // Only valid for instances with a MOCK_TIME MainThreadType. Fast-forwards
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index b9904c8..eaaffc5 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -110,6 +110,7 @@ class OutputDevice; } namespace blink { +class SourceStream; class VideoFrameResourceProvider; } namespace cc { @@ -381,6 +382,7 @@ // Allowed usage: friend class SimpleThread; friend class base::GetAppOutputScopedAllowBaseSyncPrimitives; + friend class blink::SourceStream; friend class chrome_cleaner::SystemReportComponent; friend class content::BrowserMainLoop; friend class content::BrowserProcessSubThread;
diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h index 6837eb9..638cde3 100644 --- a/base/trace_event/common/trace_event_common.h +++ b/base/trace_event/common/trace_event_common.h
@@ -1080,6 +1080,7 @@ #define TRACE_EVENT_FLAG_HAS_PROCESS_ID (static_cast<unsigned int>(1 << 11)) #define TRACE_EVENT_FLAG_HAS_LOCAL_ID (static_cast<unsigned int>(1 << 12)) #define TRACE_EVENT_FLAG_HAS_GLOBAL_ID (static_cast<unsigned int>(1 << 13)) +#define TRACE_EVENT_FLAG_DISALLOW_POSTTASK (static_cast<unsigned int>(1 << 14)) #define TRACE_EVENT_FLAG_SCOPE_MASK \ (static_cast<unsigned int>(TRACE_EVENT_FLAG_SCOPE_OFFSET | \
diff --git a/base/values.cc b/base/values.cc index 035aa235..69d66ff 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -339,8 +339,14 @@ } base::Optional<double> Value::FindDoubleKey(StringPiece key) const { - const Value* result = FindKeyOfType(key, Type::DOUBLE); - return result ? base::make_optional(result->double_value_) : base::nullopt; + const Value* result = FindKey(key); + if (result) { + if (result->is_int()) + return base::make_optional(static_cast<double>(result->int_value_)); + if (result->is_double()) + return base::make_optional(result->double_value_); + } + return base::nullopt; } const std::string* Value::FindStringKey(StringPiece key) const {
diff --git a/base/values.h b/base/values.h index e31cadd8..6f2cd3c 100644 --- a/base/values.h +++ b/base/values.h
@@ -200,6 +200,8 @@ // function's name. base::Optional<bool> FindBoolKey(StringPiece key) const; base::Optional<int> FindIntKey(StringPiece key) const; + // Note FindDoubleKey() will auto-convert INTEGER keys to their double + // value, for consistency with GetDouble(). base::Optional<double> FindDoubleKey(StringPiece key) const; // |FindStringKey| returns |nullptr| if value is not found or not a string.
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index b23fd83..7c545c0 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -674,7 +674,7 @@ const Value dict(std::move(storage)); EXPECT_EQ(base::nullopt, dict.FindDoubleKey("null")); EXPECT_EQ(base::nullopt, dict.FindDoubleKey("bool")); - EXPECT_EQ(base::nullopt, dict.FindDoubleKey("int")); + EXPECT_NE(base::nullopt, dict.FindDoubleKey("int")); EXPECT_NE(base::nullopt, dict.FindDoubleKey("double")); EXPECT_EQ(base::nullopt, dict.FindDoubleKey("string")); EXPECT_EQ(base::nullopt, dict.FindDoubleKey("blob"));
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 480cdb5..d2e58eb 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -1023,9 +1023,11 @@ system_library_deps = deps.Direct('system_java_library') direct_library_deps = deps.Direct('java_library') - group_deps = deps.All('group') + direct_group_deps = deps.Direct('group') + all_group_deps = deps.All('group') all_library_deps = deps.All('java_library') all_resources_deps = deps.All('android_resources') + all_classpath_library_deps = classpath_deps.All('java_library') # Initialize some common config. # Any value that needs to be queryable by dependents must go within deps_info. @@ -1188,7 +1190,7 @@ if srcjar: owned_resource_srcjars.add(srcjar) - for c in all_library_deps: + for c in itertools.chain(all_library_deps, all_classpath_library_deps): if c['requires_android']: owned_resource_dirs.difference_update(c['owned_resources_dirs']) owned_resource_zips.difference_update(c['owned_resources_zips']) @@ -1252,11 +1254,12 @@ javac_full_classpath = [ c['unprocessed_jar_path'] for c in all_library_deps] - for dep in group_deps: + for dep in direct_group_deps: javac_classpath.extend(dep.get('extra_classpath_jars', [])) - javac_full_classpath.extend(dep.get('extra_classpath_jars', [])) javac_interface_classpath.extend( dep.get('extra_classpath_interface_jars', [])) + for dep in all_group_deps: + javac_full_classpath.extend(dep.get('extra_classpath_jars', [])) javac_full_interface_classpath.extend( dep.get('extra_classpath_interface_jars', [])) @@ -1331,7 +1334,7 @@ p for p in c.get('proguard_configs', []) if p not in all_configs) extra_jars.extend( p for p in c.get('extra_classpath_jars', []) if p not in extra_jars) - for c in group_deps: + for c in all_group_deps: extra_jars.extend( p for p in c.get('extra_classpath_jars', []) if p not in extra_jars) if options.type == 'android_app_bundle':
diff --git a/build/android/stacktrace/crashpad_stackwalker.py b/build/android/stacktrace/crashpad_stackwalker.py index 02024c9..f33d19eb 100755 --- a/build/android/stacktrace/crashpad_stackwalker.py +++ b/build/android/stacktrace/crashpad_stackwalker.py
@@ -74,8 +74,9 @@ default_library_name = 'libmonochrome.so' dumper_path = os.path.join(build_path, 'minidump_dump') if not os.access(dumper_path, os.X_OK): - logging.warning('Cannot extract library name from dump, default to: %s', - default_library_name) + logging.warning( + 'Cannot extract library name from dump because %s is not found, ' + 'default to: %s', dumper_path, default_library_name) return [default_library_name] p = subprocess.Popen([dumper_path, dump_path], stdout=subprocess.PIPE,
diff --git a/build/config/android/chrome_version.gni b/build/config/android/chrome_version.gni index 966a9abc..afa4c56 100644 --- a/build/config/android/chrome_version.gni +++ b/build/config/android/chrome_version.gni
@@ -26,7 +26,7 @@ } else if (target_cpu == "mipsel") { _arch_preference = 20 } else if (target_cpu == "arm64") { - _arch_preference = 50 + _arch_preference = 30 } else if (target_cpu == "x64") { _arch_preference = 60 } else {
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 24169e5..d85585f2 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -231,6 +231,10 @@ # Enable the chrome build for devices without touchscreens. notouch_build = false + + # Move Trichrome assets to the shared library APK. This will be removed + # once P builds are no longer supported. https://crbug.com/943637 + trichrome_shared_assets = android_sdk_release == "q" } if (notouch_build && defined(extra_keymappings)) {
diff --git a/build/config/c++/BUILD.gn b/build/config/c++/BUILD.gn index a596d58..84b1af4 100644 --- a/build/config/c++/BUILD.gn +++ b/build/config/c++/BUILD.gn
@@ -57,11 +57,7 @@ } } - defines += [ - "CR_LIBCXX_REVISION=$libcxx_svn_revision", - "CR_LIBCXXABI_REVISION=$libcxxabi_svn_revision", - "_LIBCPP_ENABLE_NODISCARD", - ] + defines += [ "_LIBCPP_ENABLE_NODISCARD" ] if (is_win) { # Intentionally not using libc++abi on Windows because libc++abi only @@ -86,6 +82,8 @@ "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir), ] + defines += [ "CR_LIBCXX_REVISION=$libcxx_svn_revision" ] + # Make sure we don't link against the system libstdc++ or libc++. if (is_clang) { # //build/config/android:runtime_library adds -nostdlib, which suppresses
diff --git a/build/config/c++/c++.gni b/build/config/c++/c++.gni index 5d45ff1..b444656 100644 --- a/build/config/c++/c++.gni +++ b/build/config/c++/c++.gni
@@ -10,10 +10,8 @@ # standard library support. # Don't check in changes that set this to false for more platforms; doing so # is not supported. - # TODO(https://crbug.com/942939): Re-enable libc++ on Windows with libfuzzer. use_custom_libcxx = - is_fuchsia || is_android || is_mac || - (is_win && is_clang && !use_libfuzzer) || + is_fuchsia || is_android || is_mac || (is_win && is_clang) || (is_linux && (!is_chromeos || default_toolchain != "//build/toolchain/cros:target"))
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index ba79429f9..0856cffa5 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -119,7 +119,7 @@ # Turn this on to use ghash feature of lld for faster debug link on Windows. # http://blog.llvm.org/2018/01/improving-link-time-on-windows-with.html - use_ghash = false + use_ghash = true # Whether to enable ThinLTO optimizations. Turning ThinLTO optimizations on # can substantially increase link time and binary size, but they generally
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3039828..30a9d14 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -7696e56135d224c79c9e7dddeb1011e87bbd68f1 \ No newline at end of file +e4d6115c51ae86eedf493f0746088711929eb53f \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index db4eeffc..c14a9ab 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0b1b5975d80a743b37a1e91b73e04126dbd37fe9 \ No newline at end of file +7774f66f87ee66307e0277bf2d6f99614cb67ada \ No newline at end of file
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn index 79dce34..41aaf08 100644 --- a/build/secondary/third_party/android_tools/BUILD.gn +++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -36,15 +36,13 @@ } template("android_test_jar_with_manifest") { - _library_name = invoker.library_name - _manifest_output_path = "$target_gen_dir/$target_name/AndroidManifest.xml" _manifest_target = "${target_name}__manifest" jinja_template(_manifest_target) { testonly = true input = "//build/secondary/third_party/android_tools/AndroidManifest.xml.jinja2" output = _manifest_output_path - variables = [ "library_name=$_library_name" ] + variables = [ "library_name=${invoker.library_name}" ] } _resources_target = "${target_name}__resources" @@ -60,8 +58,7 @@ deps = [ ":$_resources_target", ] - input_jars_paths = - [ "${android_sdk}/optional/android.test.${_library_name}.jar" ] + input_jars_paths = [ "${android_sdk}/optional/${invoker.jar_name}" ] } } @@ -71,12 +68,15 @@ # available to be linked against but aren't linked by default. android_test_jar_with_manifest("android_test_base_java") { library_name = "base" + jar_name = "android.test.base.jar" } android_test_jar_with_manifest("android_test_mock_java") { library_name = "mock" + jar_name = "android.test.mock.jar" } android_test_jar_with_manifest("android_test_runner_java") { library_name = "runner" + jar_name = "android.test.runner.jar" } android_library("android_support_chromium_java") {
diff --git a/buildtools/DEPS b/buildtools/DEPS index 5de08b5..5cda918 100644 --- a/buildtools/DEPS +++ b/buildtools/DEPS
@@ -18,7 +18,7 @@ # When changing these, also update the svn revisions in deps_revisions.gni 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917', - 'libcxx_revision': 'a50f5035629b7621e92acef968403f71b7d48553', + 'libcxx_revision': '9009625c821e9580bfece732c25bac1cc9c5a7c2', 'libcxxabi_revision': '0d529660e32d77d9111912d73f2c74fc5fa2a858', 'libunwind_revision': '69d9b84cca8354117b9fe9705a4430d789ee599b', }
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 99a53dc4..0222020f 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -3,10 +3,7 @@ # found in the LICENSE file. declare_args() { - # The svn revisions that belong to the git hashes in DEPS. Used to cause full - # rebuilds on libc++ rolls. - clang_format_svn_revision = "346566" - libcxx_svn_revision = "355829" - libcxxabi_svn_revision = "354284" - libunwind_svn_revision = "348981" + # The libc++ svn revision that belongs to the git hash in DEPS. Used to cause + # full rebuilds on libc++ rolls. + libcxx_svn_revision = "356574" }
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc index 5b54d9b..108c332 100644 --- a/cc/animation/animation_host.cc +++ b/cc/animation/animation_host.cc
@@ -662,6 +662,11 @@ false /* needs_completion */); } +bool AnimationHost::IsImplOnlyScrollAnimating() const { + DCHECK(scroll_offset_animations_impl_); + return scroll_offset_animations_impl_->IsAnimating(); +} + void AnimationHost::AddToTicking(scoped_refptr<Animation> animation) { DCHECK(!base::ContainsValue(ticking_animations_, animation)); ticking_animations_.push_back(animation);
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h index 9927f36..0713f5d 100644 --- a/cc/animation/animation_host.h +++ b/cc/animation/animation_host.h
@@ -173,6 +173,8 @@ void ScrollAnimationAbort() override; + bool IsImplOnlyScrollAnimating() const override; + // This should only be called from the main thread. ScrollOffsetAnimations& scroll_offset_animations() const;
diff --git a/cc/animation/scroll_offset_animations_impl.cc b/cc/animation/scroll_offset_animations_impl.cc index ec4bafb..896e174 100644 --- a/cc/animation/scroll_offset_animations_impl.cc +++ b/cc/animation/scroll_offset_animations_impl.cc
@@ -59,7 +59,6 @@ DCHECK(scroll_offset_animation_->animation_timeline()); ReattachScrollOffsetAnimationIfNeeded(element_id); - scroll_offset_animation_->AddKeyframeModel(std::move(keyframe_model)); } @@ -183,6 +182,29 @@ TRACE_EVENT_SCOPE_THREAD); } +bool ScrollOffsetAnimationsImpl::IsAnimating() const { + if (!scroll_offset_animation_->has_element_animations()) + return false; + + KeyframeModel* keyframe_model = + scroll_offset_animation_->GetKeyframeModel(TargetProperty::SCROLL_OFFSET); + if (!keyframe_model) + return false; + + switch (keyframe_model->run_state()) { + case KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY: + case KeyframeModel::STARTING: + case KeyframeModel::RUNNING: + case KeyframeModel::PAUSED: + return true; + case KeyframeModel::WAITING_FOR_DELETION: + case KeyframeModel::FINISHED: + case KeyframeModel::ABORTED: + case KeyframeModel::ABORTED_BUT_NEEDS_COMPLETION: + return false; + } +} + void ScrollOffsetAnimationsImpl::ReattachScrollOffsetAnimationIfNeeded( ElementId element_id) { if (scroll_offset_animation_->element_id() != element_id) {
diff --git a/cc/animation/scroll_offset_animations_impl.h b/cc/animation/scroll_offset_animations_impl.h index 311f62e..39d72f1 100644 --- a/cc/animation/scroll_offset_animations_impl.h +++ b/cc/animation/scroll_offset_animations_impl.h
@@ -70,6 +70,8 @@ std::unique_ptr<AnimationCurve> curve) override { } + bool IsAnimating() const; + private: void ReattachScrollOffsetAnimationIfNeeded(ElementId element_id);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index e94360c..7bf58fe 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -319,7 +319,6 @@ task_graph_runner_(task_graph_runner), id_(id), consecutive_frame_with_damage_count_(settings.damaged_frame_limit), - scroll_animating_latched_element_id_(kInvalidElementId), // It is safe to use base::Unretained here since we will outlive the // ImageAnimationController. image_animation_controller_(GetTaskRunner(), @@ -2599,6 +2598,8 @@ } base::Optional<viz::HitTestRegionList> LayerTreeHostImpl::BuildHitTestData() { + TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildHitTestData"); + if (!settings_.build_hit_test_data) return {}; @@ -3802,6 +3803,7 @@ InputHandler::ScrollStatus scroll_status; scroll_status.main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; + deferred_scroll_end_state_.reset(); ScrollTree& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.CurrentlyScrollingNode(); if (scroll_node) { @@ -3826,6 +3828,7 @@ scroll_status = ScrollBegin(scroll_state, WHEEL); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { scroll_animating_latched_element_id_ = ElementId(); + scroll_animating_overscroll_target_element_id_ = ElementId(); ScrollStateData scroll_state_end_data; scroll_state_end_data.is_ending = true; ScrollState scroll_state_end(scroll_state_end_data); @@ -4029,7 +4032,30 @@ break; } } + // Set overscroll event target since neither an ongoing scroll animation has + // been updated nor a new scroll animation has been created for the current + // GSU. + if (!scroll_animating_latched_element_id_) { + // When no scroll animation has been created during the current scroll + // sequence (i.e. scroll_animating_latched_element_id_ == ElementId()) we + // need to set last_scroller_element_id_ here since scrollEnd won't get + // called. + last_scroller_element_id_ = scroll_node->element_id; + // We will send the overscroll events to viewport or the last element in + // the cut chain when no scroll animation has been created during the + // current scroll sequence. + scroll_animating_overscroll_target_element_id_ = scroll_node->element_id; + } else { + // When a scroll animation has been created during the current scroll + // sequence, the overscroll events target should be the element that + // scrolling is latched to. + scroll_animating_overscroll_target_element_id_ = + scroll_animating_latched_element_id_; + } + overscroll_delta_for_main_thread_ += pending_delta; + client_->SetNeedsCommitOnImplThread(); } + scroll_state.set_is_ending(true); ScrollEndImpl(&scroll_state); if (scroll_status.thread == SCROLL_ON_IMPL_THREAD) { @@ -4622,22 +4648,30 @@ DCHECK(scroll_state); DCHECK(scroll_state->delta_x() == 0 && scroll_state->delta_y() == 0); + // In smooth-scrolling path when the GSE arrives after scroll animation + // completion, CurrentlyScrollingNode() is already cleared due to + // ScrollEndImpl call inside ScrollOffsetAnimationFinished. In this case + // last_scroller_element_id_ is already set in the same ScrollEndImpl call and + // we should not reset it here. + if (!last_scroller_element_id_ && CurrentlyScrollingNode()) + last_scroller_element_id_ = CurrentlyScrollingNode()->element_id; + DistributeScrollDelta(scroll_state); browser_controls_offset_manager_->ScrollEnd(); ClearCurrentlyScrollingNode(); } void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) { - scroll_gesture_did_end_ = true; - last_scroller_element_id_ = CurrentlyScrollingNode() - ? CurrentlyScrollingNode()->element_id - : ElementId(); - client_->SetNeedsCommitOnImplThread(); - - if (should_snap && SnapAtScrollEnd()) + if ((should_snap && SnapAtScrollEnd()) || + mutator_host_->IsImplOnlyScrollAnimating()) { + DCHECK(!deferred_scroll_end_state_.has_value()); + deferred_scroll_end_state_ = *scroll_state; return; - + } + deferred_scroll_end_state_.reset(); ScrollEndImpl(scroll_state); + scroll_gesture_did_end_ = true; + client_->SetNeedsCommitOnImplThread(); } void LayerTreeHostImpl::MouseDown() { @@ -4826,11 +4860,20 @@ scroll_info->scroll_latched_element_id = last_scroller_element_id_; last_scroller_element_id_ = ElementId(); } else { - // Send the element id of the currently scrolling node. - auto* node = - active_tree_->property_trees()->scroll_tree.CurrentlyScrollingNode(); + // In scroll animation path CurrentlyScrollingNode does not exist during + // overscrolling. Use the explicitly stored overscroll target instead. scroll_info->scroll_latched_element_id = - node ? node->element_id : ElementId(); + scroll_animating_overscroll_target_element_id_; + scroll_animating_overscroll_target_element_id_ = ElementId(); + + if (!scroll_info->scroll_latched_element_id) { + // In non-animating scroll path the overscroll target is always the + // CurrentlyScrollingNode. + ScrollNode* node = + active_tree_->property_trees()->scroll_tree.CurrentlyScrollingNode(); + scroll_info->scroll_latched_element_id = + node ? node->element_id : ElementId(); + } } if (browser_controls_manager()) { @@ -5627,10 +5670,24 @@ void LayerTreeHostImpl::ScrollOffsetAnimationFinished() { TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollOffsetAnimationFinished"); + // ScrollOffsetAnimationFinished is called in two cases: 1- smooth scrolling + // animation is over (is_animating_for_snap_ == false). 2- snap scroll + // animation is over (is_animating_for_snap_ == true). When smooth scroll + // animation is over we should check and run snap scroll animation if needed. + if (!is_animating_for_snap_ && SnapAtScrollEnd()) + return; + + // Call scrollEnd with the deferred scroll end state when the scroll animation + // completes after GSE arrival. + if (deferred_scroll_end_state_.has_value()) { + ScrollEnd(&deferred_scroll_end_state_.value(), false); + return; + } + // TODO(majidvp): We should pass in the original starting scroll position here ScrollStateData scroll_state_data; ScrollState scroll_state(scroll_state_data); - ScrollEnd(&scroll_state, !is_animating_for_snap_); + ScrollEndImpl(&scroll_state); } void LayerTreeHostImpl::NotifyAnimationWorkletStateChange(
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 7cac46c..2a30132 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -1076,6 +1076,19 @@ // in SetPropertyTrees. ElementId scroll_animating_latched_element_id_; + // In scroll animation path CurrentlyScrollingNode does not exist when there + // is no ongoing scroll animation (e.g. during overscrolling). In this case we + // need to explicitly store the element id of the overscroll event target. The + // overscroll event target is either the element that scroll animation is + // latched to (scroll_animating_latched_element_id_) when any scrolling has + // happened during the current scroll sequence or the last element in the + // scroll chain when no scrolling has happened during the current scroll + // sequence. TODO(input-dev): Decouple CurrentlyScrollingNode life cycle from + // scroll animation life cycle to use CurrentlyScrollingNode instead of both + // scroll_animating_latched_element_id_ and + // scroll_animating_overscroll_target_element_id_. https://crbug.com/940508 + ElementId scroll_animating_overscroll_target_element_id_; + // These completion states to be transfered to the main thread when we // begin main frame. The pair represents a request id and the completion (ie // success) state. @@ -1141,12 +1154,19 @@ const PaintImage::GeneratorClientId paint_image_generator_client_id_; // Set to true when a scroll gesture being handled on the compositor has + // ended. i.e. When a GSE has arrived and any ongoing scroll animation has // ended. bool scroll_gesture_did_end_; // Set in ScrollEnd before clearing the currently scrolling node. This is // used to send the scrollend DOM event when scrolling has happened on CC. ElementId last_scroller_element_id_; + + // Scroll animation can finish either before or after GSE arrival. + // deferred_scroll_end_state_ is set when the GSE has arrvied before scroll + // animation completion. ScrollEnd will get called with this deferred state + // once the animation is over. + base::Optional<ScrollState> deferred_scroll_end_state_; }; } // namespace cc
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h index 21551b9..7ab32e3e 100644 --- a/cc/trees/mutator_host.h +++ b/cc/trees/mutator_host.h
@@ -134,6 +134,9 @@ virtual void ScrollAnimationAbort() = 0; + // True when there is an ongoing scroll animation on Impl. + virtual bool IsImplOnlyScrollAnimating() const = 0; + virtual size_t CompositedAnimationsCount() const = 0; virtual size_t MainThreadAnimationsCount() const = 0; virtual bool CurrentFrameHadRAF() const = 0;
diff --git a/chrome/VERSION b/chrome/VERSION index d75976d..0f6666f 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=75 MINOR=0 -BUILD=3740 +BUILD=3741 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 2d6e5f9..b655242 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -453,8 +453,8 @@ } } -# This is a list of all our base module java dependencies. New features should -# be added to this list. +# This is a list of all base module java dependencies. New features should be +# added to this list. java_group("chrome_all_java") { deps = [ ":chrome_java", @@ -463,6 +463,16 @@ ] } +# This is a list of all base module jni headers. New features should add their +# own jni target to this list. +group("jni_headers") { + public_deps = [ + ":chrome_jni_headers", + "//chrome/android/features/autofill_assistant:jni_headers", + "//chrome/android/features/media_router:jni_headers", + ] +} + android_library("bundle_canary_java") { java_files = [ "//base/android/java/src/org/chromium/base/BundleCanary.java" ] deps = [ @@ -1010,43 +1020,17 @@ java_group("chrome_public_non_pak_assets") { deps = [ "//chrome/android/webapk/libs/runtime_library:runtime_library_assets", - "//third_party/icu:icu_assets", ] - if (use_v8_context_snapshot) { - deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ] - } else { - deps += [ "//v8:v8_external_startup_data_assets" ] - } } -# TODO(estevenson): Remove this target once these assets move to -# trichrome_library_apk. -if (android_64bit_target_cpu) { - android_assets("v8_snapshot_secondary_abi_assets") { - _secondary_abi_out_dir = - get_label_info("//v8($android_secondary_abi_toolchain)", "root_out_dir") - sources = [ - "$_secondary_abi_out_dir/natives_blob.bin", - ] - if (use_v8_context_snapshot) { - renaming_sources = [ "$_secondary_abi_out_dir/v8_context_snapshot.bin" ] - renaming_destinations = [ "v8_context_snapshot_32.bin" ] - } else { - renaming_sources = [ "$_secondary_abi_out_dir/snapshot_blob.bin" ] - renaming_destinations = [ "snapshot_blob_32.bin" ] - } - disable_compression = true +java_group("chrome_public_v8_assets") { + if (use_v8_context_snapshot) { deps = [ - "//tools/v8_context_snapshot($android_secondary_abi_toolchain)", - "//v8($android_secondary_abi_toolchain)", + "//tools/v8_context_snapshot:v8_context_snapshot_assets", ] - } - - java_group("chrome_public_secondary_abi_non_pak_assets") { + } else { deps = [ - ":v8_snapshot_secondary_abi_assets", - "//chrome/android/webapk/libs/runtime_library:runtime_library_assets", - "//third_party/icu:icu_assets", + "//v8:v8_external_startup_data_assets", ] } } @@ -1514,6 +1498,8 @@ ":chrome_public_apk_resources", ":chrome_public_base_module_java", ":chrome_public_non_pak_assets", + ":chrome_public_v8_assets", + "//third_party/icu:icu_assets", ] generate_jni("test_support_jni_headers") { @@ -1540,6 +1526,7 @@ "//base:base_java_test_support", "//components/offline_items_collection/core:core_java", "//components/sync:test_support_proto_java", + "//content/public/android:content_java", "//content/public/test/android:content_java_test_support", "//third_party/android_deps:com_google_protobuf_protobuf_lite_java", "//third_party/junit", @@ -2212,25 +2199,11 @@ use_trichrome_library = true } -generate_jni("jni_headers") { +generate_jni("chrome_jni_headers") { sources = [ - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsModel.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderDelegate.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBox.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxModel.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDelegate.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestDelegate.java", - "features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestModel.java", + # Files under a feature's public/ dir are included in chrome_java's source + # files, so include these files in chrome_jni_headers. "features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java", - "features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", - "features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", - "features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", - "features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", "java/src/org/chromium/chrome/browser/AfterStartupTaskUtils.java", "java/src/org/chromium/chrome/browser/AppHooks.java", "java/src/org/chromium/chrome/browser/ApplicationLifetime.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 32147a1..00f7177 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -155,7 +155,9 @@ if (!_is_monochrome && !_is_trichrome) { deps += [ + "//chrome/android:chrome_public_v8_assets", "//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so", + "//third_party/icu:icu_assets", ] if (!defined(loadable_modules)) { loadable_modules = [] @@ -286,7 +288,10 @@ loadable_modules = [] secondary_abi_loadable_modules = [] - _deps = [ "//components/crash/android:handler_java" ] + _deps = [ + "//components/crash/android:handler_java", + "//chrome/android:chrome_public_non_pak_assets", + ] if (is_monochrome) { if (invoker.target_type == "android_app_bundle_module") { @@ -320,7 +325,6 @@ "//android_webview:monochrome_webview_assets", "//android_webview/apk:webview_license_activity_java", "//android_webview/glue", - "//chrome/android:chrome_public_non_pak_assets", "//chrome/android:monochrome_java", "//chrome/android/monochrome:monochrome_license_provider_java", "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline", @@ -342,6 +346,10 @@ _pak_prefix = "monochrome" } if (is_trichrome) { + if (!trichrome_shared_assets) { + _deps += [ "//android_webview:monochrome_webview_assets" ] + } + # Include placeholder libraries to make Chrome multiarch in the same way # as Monochrome, even though Chrome only runs with one of the two # bitnesses. This allows the "32-bit" and "64-bit" versions of Chrome to @@ -351,12 +359,6 @@ if (android_64bit_target_cpu && build_apk_secondary_abi) { secondary_native_lib_placeholders = [ "libdummy.so" ] } - if (android_64bit_target_cpu) { - _deps += - [ "//chrome/android:chrome_public_secondary_abi_non_pak_assets" ] - } else { - _deps += [ "//chrome/android:chrome_public_non_pak_assets" ] - } min_sdk_version = 28 _pak_prefix = "trichrome_chrome" }
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index bac2bd62..bbffdbc 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -6,6 +6,26 @@ import("//build/config/android/rules.gni") import("//chrome/common/features.gni") +# The animated_poodle_java target is overridden downstream and used +# instead of this one if the enable_chrome_android_internal flag is +# enabled. +android_library("animated_poodle_java") { + deps = [ + ":animated_poodle_resources", + "//base:base_java", + "//chrome/android:chrome_java", + "//third_party/android_deps:android_support_v7_appcompat_java", + ] + + java_files = [ "java/src/org/chromium/chrome/browser/" + + "autofill_assistant/header/AnimatedPoodle.java" ] +} + +android_resources("animated_poodle_resources") { + resource_dirs = [ "java/res_poodle" ] + custom_package = "org.chromium.chrome.autofill_assistant.poodle" +} + android_library("java") { deps = [ ":java_resources", @@ -21,6 +41,13 @@ "//third_party/blink/public/mojom:android_mojo_bindings_java", "//ui/android:ui_java", ] + + if (enable_chrome_android_internal) { + deps += [ "//clank/features/autofill_assistant:animated_poodle_java" ] + } else { + deps += [ ":animated_poodle_java" ] + } + java_files = [ "java/src/org/chromium/chrome/browser/autofill_assistant/AbstractListObserver.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java", @@ -63,6 +90,24 @@ ] } +generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderDelegate.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBox.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/infobox/AssistantInfoBoxModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDelegate.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestDelegate.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestModel.java", + ] + jni_package = "autofill_assistant" +} + android_library("test_java") { testonly = true
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml index c781029..58de6501 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml
@@ -4,29 +4,22 @@ found in the LICENSE file. --> <merge xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="56dp" android:gravity="center_vertical" android:orientation="horizontal" - android:paddingStart="24dp" + android:paddingStart="19dp" android:paddingEnd="24dp"> - <ImageView - android:layout_width="24dp" - android:layout_height="24dp" - app:srcCompat="@drawable/ic_autofill_assistant_24dp" - tools:ignore="ContentDescription" /> - <TextView android:id="@+id/status_message" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:gravity="center_vertical" - android:paddingStart="24dp" + android:paddingStart="19dp" android:paddingEnd="24dp" android:maxLines="4" android:ellipsize="end" @@ -45,7 +38,9 @@ <org.chromium.chrome.browser.widget.MaterialProgressBar android:id="@+id/progress_bar" android:layout_width="match_parent" - android:layout_height="6dp" + android:layout_height="2dp" + android:layout_marginStart="@dimen/autofill_assistant_bottombar_horizontal_spacing" + android:layout_marginEnd="@dimen/autofill_assistant_bottombar_horizontal_spacing" app:colorBackground="@color/modern_grey_100" app:colorProgress="@color/modern_blue_600"/> </merge>
diff --git a/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml b/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml index 4caeae3..3bc1141 100644 --- a/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml +++ b/chrome/android/features/autofill_assistant/java/res/values-v17/dimens.xml
@@ -6,4 +6,6 @@ <dimen name="autofill_assistant_bottombar_horizontal_spacing">24dp</dimen> <dimen name="autofill_assistant_bottombar_vertical_spacing">20dp</dimen> <dimen name="autofill_assistant_details_image_size">48dp</dimen> + <dimen name="autofill_assistant_poodle_size">24dp</dimen> + <dimen name="autofill_assistant_poodle_view_size">34dp</dimen> </resources>
diff --git a/chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_24dp.xml b/chrome/android/features/autofill_assistant/java/res_poodle/drawable/ic_autofill_assistant_24dp.xml similarity index 100% rename from chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_24dp.xml rename to chrome/android/features/autofill_assistant/java/res_poodle/drawable/ic_autofill_assistant_24dp.xml
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedPoodle.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedPoodle.java new file mode 100644 index 0000000..0995630 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedPoodle.java
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.autofill_assistant.header; + +import android.content.Context; +import android.support.v7.content.res.AppCompatResources; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import org.chromium.chrome.autofill_assistant.poodle.R; + +/** + * Represents a poodle that can be animated. This default implementation is a static poodle, the + * actual animation is implemented downstream and replaces this one. The correct version will be + * determined at compile time via build rules. + * + * <p>Warning: do not rename this class or change the signature of the non-private methods + * (including constructor) without adapting the associated downstream code. + */ +/* package */ class AnimatedPoodle { + private final ImageView mView; + + /** + * Create an AnimatedPoodle whose View will have a width and height of {@code viewSizePx} + * pixels that displays a centered poodle with a width and height of {@code poodleSizePx} + * pixels. + */ + /* package */ AnimatedPoodle(Context context, int viewSizePx, int poodleSizePx) { + mView = new ImageView(context); + mView.setImageDrawable( + AppCompatResources.getDrawable(context, R.drawable.ic_autofill_assistant_24dp)); + mView.setLayoutParams(new ViewGroup.LayoutParams(viewSizePx, viewSizePx)); + + int padding = (viewSizePx - poodleSizePx) / 2; + mView.setPadding(padding, padding, padding, padding); + } + + /** Get the view associated to this animated poodle. */ + /* package */ View getView() { + return mView; + } + + /** Enable or disable the spin animation. */ + /* package */ void setSpinEnabled(boolean enabled) { + // Do nothing. + } +} \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java index 5e20763..eb5e898b 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java
@@ -6,7 +6,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.view.View; @@ -23,21 +22,15 @@ class AnimatedProgressBar { // The number of ms the progress bar would take to go from 0 to 100%. private static final int PROGRESS_BAR_SPEED_MS = 3_000; - private static final int PROGRESS_BAR_PULSING_DURATION_MS = 1_000; private final MaterialProgressBar mProgressBar; - private final int mNormalColor; - private final int mPulsedColor; private boolean mIsRunningProgressAnimation; private int mLastProgress; private Queue<ValueAnimator> mPendingIncreaseAnimations = new ArrayDeque<>(); - private ValueAnimator mPulseAnimation; - AnimatedProgressBar(MaterialProgressBar progressBar, int normalColor, int pulsedColor) { + AnimatedProgressBar(MaterialProgressBar progressBar) { mProgressBar = progressBar; - mNormalColor = normalColor; - mPulsedColor = pulsedColor; } public void show() { @@ -82,31 +75,4 @@ progressAnimation.start(); } } - - public void enablePulsing() { - if (mPulseAnimation == null) { - mPulseAnimation = ValueAnimator.ofInt(mNormalColor, mPulsedColor); - mPulseAnimation.setDuration(PROGRESS_BAR_PULSING_DURATION_MS); - mPulseAnimation.setEvaluator(new ArgbEvaluator()); - mPulseAnimation.setRepeatCount(ValueAnimator.INFINITE); - mPulseAnimation.setRepeatMode(ValueAnimator.REVERSE); - mPulseAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR); - mPulseAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationCancel(Animator animation) { - mProgressBar.setProgressColor(mNormalColor); - } - }); - mPulseAnimation.addUpdateListener( - animation -> mProgressBar.setProgressColor((int) animation.getAnimatedValue())); - mPulseAnimation.start(); - } - } - - public void disablePulsing() { - if (mPulseAnimation != null) { - mPulseAnimation.cancel(); - mPulseAnimation = null; - } - } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java index 86c521986..ab878a0 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java
@@ -6,18 +6,36 @@ import android.content.Context; import android.view.View; +import android.view.ViewGroup; +import org.chromium.chrome.autofill_assistant.R; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; /** * Coordinator for the header of the Autofill Assistant. */ public class AssistantHeaderCoordinator { - public AssistantHeaderCoordinator(Context context, View root, AssistantHeaderModel model) { + public AssistantHeaderCoordinator(Context context, ViewGroup root, AssistantHeaderModel model) { + // Create the poodle and insert it before the status message. We have to create a view + // bigger than the desired poodle size (24dp) because the actual downstream implementation + // needs extra space for the animation. + AnimatedPoodle poodle = new AnimatedPoodle(context, + context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_poodle_view_size), + context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_poodle_size)); + addPoodle(root, poodle.getView()); + // Bind view and mediator through the model. AssistantHeaderViewBinder.ViewHolder viewHolder = - new AssistantHeaderViewBinder.ViewHolder(context, root); + new AssistantHeaderViewBinder.ViewHolder(root, poodle); AssistantHeaderViewBinder viewBinder = new AssistantHeaderViewBinder(); PropertyModelChangeProcessor.create(model, viewHolder, viewBinder); } + + private void addPoodle(ViewGroup root, View poodleView) { + View statusMessage = root.findViewById(R.id.status_message); + ViewGroup parent = (ViewGroup) statusMessage.getParent(); + parent.addView(poodleView, parent.indexOfChild(statusMessage)); + } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java index 8e3e091..af378cf 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java
@@ -29,13 +29,13 @@ public static final WritableBooleanPropertyKey PROGRESS_VISIBLE = new WritableBooleanPropertyKey(); - static final WritableBooleanPropertyKey PROGRESS_PULSING = new WritableBooleanPropertyKey(); + static final WritableBooleanPropertyKey SPIN_POODLE = new WritableBooleanPropertyKey(); static final WritableObjectPropertyKey<Runnable> FEEDBACK_BUTTON_CALLBACK = new WritableObjectPropertyKey<>(); public AssistantHeaderModel() { - super(STATUS_MESSAGE, FEEDBACK_VISIBLE, PROGRESS, PROGRESS_VISIBLE, PROGRESS_PULSING, + super(STATUS_MESSAGE, FEEDBACK_VISIBLE, PROGRESS, PROGRESS_VISIBLE, SPIN_POODLE, FEEDBACK_BUTTON_CALLBACK); } @@ -55,8 +55,8 @@ } @CalledByNative - private void setProgressPulsingEnabled(boolean enabled) { - set(PROGRESS_PULSING, enabled); + private void setSpinPoodle(boolean enabled) { + set(SPIN_POODLE, enabled); } @CalledByNative
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java index fee16812..1663e02 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.autofill_assistant.header; -import android.content.Context; import android.view.View; import android.widget.TextView; @@ -24,15 +23,15 @@ * A wrapper class that holds the different views of the header. */ static class ViewHolder { + final AnimatedPoodle mPoodle; final TextView mStatusMessage; final AnimatedProgressBar mProgressBar; final View mFeedbackButton; - public ViewHolder(Context context, View headerView) { + public ViewHolder(View headerView, AnimatedPoodle poodle) { + mPoodle = poodle; mStatusMessage = headerView.findViewById(R.id.status_message); - mProgressBar = new AnimatedProgressBar(headerView.findViewById(R.id.progress_bar), - context.getResources().getColor(R.color.modern_blue_600), - context.getResources().getColor(R.color.modern_blue_600_alpha_38_opaque)); + mProgressBar = new AnimatedProgressBar(headerView.findViewById(R.id.progress_bar)); mFeedbackButton = headerView.findViewById(R.id.feedback_button); } } @@ -54,12 +53,8 @@ } else { view.mProgressBar.hide(); } - } else if (AssistantHeaderModel.PROGRESS_PULSING == propertyKey) { - if (model.get(AssistantHeaderModel.PROGRESS_PULSING)) { - view.mProgressBar.enablePulsing(); - } else { - view.mProgressBar.disablePulsing(); - } + } else if (AssistantHeaderModel.SPIN_POODLE == propertyKey) { + view.mPoodle.setSpinEnabled(model.get(AssistantHeaderModel.SPIN_POODLE)); } else if (AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK == propertyKey) { Runnable listener = model.get(AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK); view.mFeedbackButton.setOnClickListener(unusedView -> listener.run());
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AutofillAssistantPaymentRequest.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AutofillAssistantPaymentRequest.java index 6d0e766..172e010 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AutofillAssistantPaymentRequest.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AutofillAssistantPaymentRequest.java
@@ -412,20 +412,25 @@ // Address is complete and user was in the "Add flow": add an item to // the list. mShippingAddressesSection.addAndSelectItem(editedAddress); + mDelegate.onShippingAddressChanged(editedAddress.getProfile()); } if (mContactSection != null) { // Update |mContactSection| with the new/edited address, which will // update an existing item or add a new one to the end of the list. mContactSection.addOrUpdateWithAutofillAddress(editedAddress); + mDelegate.onContactInfoChanged( + (AutofillContact) mContactSection.getSelectedItem()); mUI.updateSection( PaymentRequestUI.DataType.CONTACT_DETAILS, mContactSection); } } - - mUI.updateSection(PaymentRequestUI.DataType.SHIPPING_ADDRESSES, - mShippingAddressesSection); } + + // If |editedAddress| is null, the user has cancelled out of the "Add flow". No + // action to take (if an address was selected in the UI, it will stay selected). + mUI.updateSection( + PaymentRequestUI.DataType.SHIPPING_ADDRESSES, mShippingAddressesSection); } }); } @@ -447,6 +452,7 @@ // Contact is complete and we were in the "Add flow": add an item to the // list. mContactSection.addAndSelectItem(editedContact); + mDelegate.onContactInfoChanged(editedContact); } // If contact is complete and (toEdit != null), no action needed: the contact // was already selected in the UI. @@ -476,6 +482,7 @@ } else if (toEdit == null) { // Card is complete and we were in the "Add flow": add an item to the list. mPaymentMethodsSection.addAndSelectItem(editedCard); + mDelegate.onCreditCardChanged(editedCard.getCard()); } // If card is complete and (toEdit != null), no action needed: the card was // already selected in the UI.
diff --git a/chrome/android/features/media_router/BUILD.gn b/chrome/android/features/media_router/BUILD.gn index ed861e05..ddd9fb9 100644 --- a/chrome/android/features/media_router/BUILD.gn +++ b/chrome/android/features/media_router/BUILD.gn
@@ -65,6 +65,16 @@ ] } +generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", + "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", + "java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", + "java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", + ] + jni_package = "media_router" +} + android_library("test_java") { testonly = true
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index 13529d7..e3621c8 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -34,6 +34,7 @@ "java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripToolbarViewProperties.java", "java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewBinder.java", "java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewHolder.java", + "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java", ] classpath_deps = [
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java index 5cfb57b..126c0ca 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java
@@ -25,7 +25,8 @@ R.string.bottom_tab_grid_new_tab, R.plurals.bottom_tab_grid_title_placeholder, R.string.iph_tab_groups_tap_to_see_another_tab_accessibility_text, R.string.accessibility_bottom_tab_strip_expand_tab_sheet, - R.layout.bottom_tab_strip_toolbar, R.drawable.tabstrip_selected}; + R.layout.bottom_tab_strip_toolbar, R.drawable.tabstrip_selected, + R.drawable.tabstrip_favicon_background}; private SilenceLintErrors() {} }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java index 5f559ba1..5c2e8de1 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
@@ -58,7 +58,7 @@ item.get(TabProperties.TAB_CLOSED_LISTENER).run(holder.getTabId()); }); } else if (TabProperties.FAVICON == propertyKey) { - holder.favicon.setImageBitmap(item.get(TabProperties.FAVICON)); + holder.favicon.setImageDrawable(item.get(TabProperties.FAVICON)); } else if (TabProperties.THUMBNAIL_FETCHER == propertyKey) { TabListMediator.ThumbnailFetcher fetcher = item.get(TabProperties.THUMBNAIL_FETCHER); if (fetcher == null) return;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index 3115bd8..b323f842 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -80,7 +80,9 @@ mTabModelObserver = new EmptyTabModelObserver() { @Override public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) { - if (getRelatedTabsForId(lastId).contains(tab)) return; + if (type == TabSelectionType.FROM_CLOSE + || getRelatedTabsForId(lastId).contains(tab)) + return; resetTabStripWithRelatedTabsForId(tab.getId()); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java index 0073f95..fc83adeb 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -15,7 +15,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; -import org.chromium.chrome.browser.favicon.FaviconHelper; import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; @@ -107,8 +106,11 @@ mRecyclerView.setHasFixedSize(true); - mMediator = new TabListMediator(Profile.getLastUsedProfile(), tabListModel, context, - tabModelSelector, tabContentManager, new FaviconHelper(), componentName); + TabListFaviconProvider mTabListFaviconProvider = + new TabListFaviconProvider(context, Profile.getLastUsedProfile()); + + mMediator = new TabListMediator(tabListModel, tabModelSelector, tabContentManager, + mTabListFaviconProvider, componentName); } /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java new file mode 100644 index 0000000..ce8fcd5 --- /dev/null +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
@@ -0,0 +1,105 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_management; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.v7.content.res.AppCompatResources; + +import org.chromium.base.Callback; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.favicon.FaviconHelper; +import org.chromium.chrome.browser.native_page.NativePageFactory; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.util.ViewUtils; + +/** + * Provider for processed favicons in Tab list. + */ +public class TabListFaviconProvider { + private static Drawable sGlobeDrawable; + private static Drawable sChromeDrawable; + private final int mFaviconSize; + private final Profile mProfile; + private final FaviconHelper mFaviconHelper; + + /** + * Construct the provider that provides favicons for tab list. + * @param context The context to use for accessing {@link android.content.res.Resources} + * @param profile The profile to use for getting favicons. + */ + public TabListFaviconProvider(Context context, Profile profile) { + mFaviconSize = context.getResources().getDimensionPixelSize(R.dimen.default_favicon_size); + mProfile = profile; + mFaviconHelper = new FaviconHelper(); + if (sGlobeDrawable == null) { + Drawable globeDrawable = + AppCompatResources.getDrawable(context, R.drawable.ic_globe_24dp); + Bitmap globeBitmap = + Bitmap.createBitmap(mFaviconSize, mFaviconSize, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(globeBitmap); + globeDrawable.setBounds(0, 0, mFaviconSize, mFaviconSize); + globeDrawable.draw(canvas); + sGlobeDrawable = processBitmap(globeBitmap); + } + if (sChromeDrawable == null) { + Bitmap chromeBitmap = + BitmapFactory.decodeResource(context.getResources(), R.drawable.chromelogo16); + sChromeDrawable = processBitmap(chromeBitmap); + } + } + + private Drawable processBitmap(Bitmap bitmap) { + return ViewUtils.createRoundedBitmapDrawable( + Bitmap.createScaledBitmap(bitmap, mFaviconSize, mFaviconSize, true), + ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS); + } + + /** + * @return The scaled rounded Globe Drawable as default favicon. + */ + public Drawable getDefaultFaviconDrawable() { + return sGlobeDrawable; + } + + /** + * Asynchronously get the processed favicon Drawable. + * @param url The URL whose favicon is requested. + * @param isIncognito Whether the tab is incognito or not. + * @param faviconCallback The callback that requests for favicon. + */ + public void getFaviconForUrlAsync( + String url, boolean isIncognito, Callback<Drawable> faviconCallback) { + if (NativePageFactory.isNativePageUrl(url, isIncognito)) { + faviconCallback.onResult(sChromeDrawable); + } else { + mFaviconHelper.getLocalFaviconImageForURL( + mProfile, url, mFaviconSize, (image, iconUrl) -> { + if (image == null) return; + Drawable drawable = processBitmap(image); + faviconCallback.onResult(drawable); + }); + } + } + + /** + * Synchronously get the processed favicon Drawable. + * @param url The URL whose favicon is requested. + * @param isIncognito Whether the tab is in cognito or not. + * @param icon The favicon that was received. + * @return The processed favicon. + */ + public Drawable getFaviconForUrlSync(String url, boolean isIncognito, Bitmap icon) { + if (icon == null) { + boolean isNativeUrl = NativePageFactory.isNativePageUrl(url, isIncognito); + return isNativeUrl ? sChromeDrawable : sGlobeDrawable; + } else { + return processBitmap(icon); + } + } +}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 60c3dba5..d859691c 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -4,20 +4,17 @@ package org.chromium.chrome.browser.tasks.tab_management; -import android.content.Context; import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import org.chromium.base.Callback; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; -import org.chromium.chrome.browser.favicon.FaviconHelper; -import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.native_page.NativePageFactory; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabFavicon; import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -25,6 +22,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.tabmodel.TabSelectionType; +import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.modelutil.PropertyModel; import java.util.ArrayList; @@ -61,12 +59,10 @@ mThumbnailProvider.getTabThumbnailWithCallback(mTab, callback); } } - private final int mFaviconSize; - private final FaviconHelper mFaviconHelper; + private final TabListFaviconProvider mTabListFaviconProvider; private final TabListModel mModel; private final TabModelSelector mTabModelSelector; private final TabContentManager mTabContentManager; - private final Profile mProfile; private final String mComponentName; private final TabActionListener mTabSelectedListener = new TabActionListener() { @@ -121,6 +117,16 @@ private final TabObserver mTabObserver = new EmptyTabObserver() { @Override + public void onDidStartNavigation(Tab tab, NavigationHandle navigationHandle) { + if (NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncognito())) return; + if (navigationHandle.isSameDocument() || !navigationHandle.isInMainFrame()) return; + if (mModel.indexFromId(tab.getId()) == TabModel.INVALID_TAB_INDEX) return; + mModel.get(mModel.indexFromId(tab.getId())) + .set(TabProperties.FAVICON, + mTabListFaviconProvider.getDefaultFaviconDrawable()); + } + + @Override public void onTitleUpdated(Tab updatedTab) { int index = mModel.indexFromId(updatedTab.getId()); if (index == TabModel.INVALID_TAB_INDEX) return; @@ -131,7 +137,9 @@ public void onFaviconUpdated(Tab updatedTab, Bitmap icon) { int index = mModel.indexFromId(updatedTab.getId()); if (index == TabModel.INVALID_TAB_INDEX) return; - mModel.get(index).set(TabProperties.FAVICON, icon); + Drawable drawable = mTabListFaviconProvider.getFaviconForUrlSync( + updatedTab.getUrl(), updatedTab.isIncognito(), icon); + mModel.get(index).set(TabProperties.FAVICON, drawable); } }; @@ -146,22 +154,19 @@ * Construct the Mediator with the given Models and observing hooks from the given * ChromeActivity. * @param model The Model to keep state about a list of {@link Tab}s. - * @param context The context to use for accessing {@link android.content.res.Resources} * @param tabModelSelector {@link TabModelSelector} that will provide and receive signals about * the tabs concerned. * @param tabContentManager {@link TabContentManager} to provide screenshot related details. * @param componentName This is a unique string to identify different components. */ - public TabListMediator(Profile profile, TabListModel model, Context context, - TabModelSelector tabModelSelector, TabContentManager tabContentManager, - FaviconHelper faviconHelper, String componentName) { - mFaviconSize = context.getResources().getDimensionPixelSize(R.dimen.tab_grid_favicon_size); + public TabListMediator(TabListModel model, TabModelSelector tabModelSelector, + TabContentManager tabContentManager, TabListFaviconProvider tabListFaviconProvider, + String componentName) { mTabModelSelector = tabModelSelector; mTabContentManager = tabContentManager; mModel = model; - mFaviconHelper = faviconHelper; - mProfile = profile; + mTabListFaviconProvider = tabListFaviconProvider; mComponentName = componentName; mTabModelObserver = new EmptyTabModelObserver() { @@ -243,7 +248,8 @@ new PropertyModel.Builder(TabProperties.ALL_KEYS_TAB_GRID) .with(TabProperties.TAB_ID, tab.getId()) .with(TabProperties.TITLE, tab.getTitle()) - .with(TabProperties.FAVICON, TabFavicon.getBitmap(tab)) + .with(TabProperties.FAVICON, + mTabListFaviconProvider.getDefaultFaviconDrawable()) .with(TabProperties.IS_SELECTED, isSelected) .with(TabProperties.TAB_SELECTED_LISTENER, mTabSelectedListener) .with(TabProperties.TAB_CLOSED_LISTENER, mTabClosedListener) @@ -253,11 +259,16 @@ } else { mModel.add(index, tabInfo); } - mFaviconHelper.getLocalFaviconImageForURL( - mProfile, tab.getUrl(), mFaviconSize, (image, iconUrl) -> { - if (mModel.indexFromId(tab.getId()) == Tab.INVALID_TAB_ID) return; - mModel.get(mModel.indexFromId(tab.getId())).set(TabProperties.FAVICON, image); - }); + + Callback<Drawable> faviconCallback = drawable -> { + int modelIndex = mModel.indexFromId(tab.getId()); + if (modelIndex != Tab.INVALID_TAB_ID && drawable != null) { + mModel.get(modelIndex).set(TabProperties.FAVICON, drawable); + } + }; + mTabListFaviconProvider.getFaviconForUrlAsync( + tab.getUrl(), tab.isIncognito(), faviconCallback); + ThumbnailFetcher callback = new ThumbnailFetcher(mTabContentManager::getTabThumbnailWithCallback, tab); tabInfo.set(TabProperties.THUMBNAIL_FETCHER, callback);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java index e12668dc..14d6d10 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.browser.tasks.tab_management; -import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -24,7 +24,7 @@ public static final WritableObjectPropertyKey<TabListMediator.TabActionListener> TAB_CLOSED_LISTENER = new WritableObjectPropertyKey<>(); - public static final WritableObjectPropertyKey<Bitmap> FAVICON = + public static final WritableObjectPropertyKey<Drawable> FAVICON = new WritableObjectPropertyKey<>(); public static final WritableObjectPropertyKey<TabListMediator.ThumbnailFetcher>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewBinder.java index 83320d5..a26896a 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabStripViewBinder.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.tasks.tab_management; -import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; @@ -12,7 +11,6 @@ import android.widget.FrameLayout; import org.chromium.chrome.R; -import org.chromium.chrome.browser.util.ViewUtils; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -56,14 +54,11 @@ R.string.accessibility_tabstrip_tab, title)); } } else if (TabProperties.FAVICON == propertyKey) { - Bitmap favicon = item.get(TabProperties.FAVICON); - if (favicon == null) return; - int faviconSize = holder.itemView.getContext().getResources().getDimensionPixelSize( - R.dimen.default_favicon_size); - Drawable drawable = ViewUtils.createRoundedBitmapDrawable( - Bitmap.createScaledBitmap(favicon, faviconSize, faviconSize, true), - ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS); - holder.button.setImageDrawable(drawable); + Drawable faviconDrawable = item.get(TabProperties.FAVICON); + holder.button.setBackgroundResource(R.drawable.tabstrip_favicon_background); + if (faviconDrawable != null) { + holder.button.setImageDrawable(faviconDrawable); + } } else if (TabProperties.TAB_ID == propertyKey) { holder.setTabId(item.get(TabProperties.TAB_ID)); }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index ed640e9..255f1a7 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -10,7 +10,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -18,9 +20,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.view.View; import org.junit.After; @@ -33,12 +35,12 @@ import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; +import org.chromium.base.Callback; import org.chromium.base.UserDataHost; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.favicon.FaviconHelper; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tabmodel.TabLaunchType; @@ -57,7 +59,6 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class TabListMediatorUnitTest { - private static final int MOCK_FAVICON_SIZE = 10; private static final String TAB1_TITLE = "Tab1"; private static final String TAB2_TITLE = "Tab2"; private static final String TAB3_TITLE = "Tab3"; @@ -75,19 +76,15 @@ @Mock TabModel mTabModel; @Mock - Context mContext; - @Mock - Resources mResources; - @Mock - FaviconHelper mFaviconHelper; - @Mock - Profile mProfile; + TabListFaviconProvider mTabListFaviconProvider; @Captor ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor; @Captor ArgumentCaptor<FaviconHelper.FaviconImageCallback> mFaviconCallbackCaptor; @Captor ArgumentCaptor<TabObserver> mTabObserverCaptor; + @Captor + ArgumentCaptor<Callback<Drawable>> mCallbackCaptor; private Tab mTab1; private Tab mTab2; @@ -108,12 +105,6 @@ tabModelList.add(mTabModel); doNothing().when(mTabContentManager).getTabThumbnailWithCallback(any(), any()); - doReturn(mResources).when(mContext).getResources(); - doReturn(MOCK_FAVICON_SIZE).when(mResources).getDimensionPixelSize(anyInt()); - doReturn(true) - .when(mFaviconHelper) - .getLocalFaviconImageForURL( - any(), any(), anyInt(), mFaviconCallbackCaptor.capture()); doReturn(mTabModel).when(mTabModelSelector).getCurrentModel(); doReturn(tabModelList).when(mTabModelSelector).getModels(); doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider(); @@ -126,10 +117,13 @@ doNothing().when(mTab1).addObserver(mTabObserverCaptor.capture()); doReturn(0).when(mTabModel).index(); doReturn(2).when(mTabModel).getCount(); + doNothing() + .when(mTabListFaviconProvider) + .getFaviconForUrlAsync(anyString(), anyBoolean(), mCallbackCaptor.capture()); mModel = new TabListModel(); - mMediator = new TabListMediator(mProfile, mModel, mContext, mTabModelSelector, - mTabContentManager, mFaviconHelper, getClass().getSimpleName()); + mMediator = new TabListMediator(mModel, mTabModelSelector, mTabContentManager, + mTabListFaviconProvider, getClass().getSimpleName()); } @After @@ -257,8 +251,8 @@ tabs.add(mTabModel.getTabAt(i)); } mMediator.resetWithListOfTabs(tabs); - for (FaviconHelper.FaviconImageCallback callback : mFaviconCallbackCaptor.getAllValues()) { - callback.onFaviconAvailable(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888), null); + for (Callback<Drawable> callback : mCallbackCaptor.getAllValues()) { + callback.onResult(new ColorDrawable(Color.RED)); } assertThat(mModel.size(), equalTo(2)); @@ -269,8 +263,8 @@ assertThat(mModel.get(0).get(TabProperties.TITLE), equalTo(TAB1_TITLE)); assertThat(mModel.get(1).get(TabProperties.TITLE), equalTo(TAB2_TITLE)); - assertThat(mModel.get(0).get(TabProperties.FAVICON), instanceOf(Bitmap.class)); - assertThat(mModel.get(1).get(TabProperties.FAVICON), instanceOf(Bitmap.class)); + assertThat(mModel.get(0).get(TabProperties.FAVICON), instanceOf(Drawable.class)); + assertThat(mModel.get(1).get(TabProperties.FAVICON), instanceOf(Drawable.class)); assertThat(mModel.get(0).get(TabProperties.IS_SELECTED), equalTo(true)); assertThat(mModel.get(1).get(TabProperties.IS_SELECTED), equalTo(false));
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java index 3a204e0..4cae074 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
@@ -10,6 +10,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.modules.ModuleInstallUi; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.components.module_installer.Module; import org.chromium.components.module_installer.OnModuleInstallFinishedListener; import java.util.ArrayList; @@ -88,11 +89,11 @@ @VisibleForTesting public static void setAlwaysUseFallbackDelegate(boolean useFallbackDelegate) { - // TODO(bsheedy): Change this to an "assert sDelegateProvider == null" once we change the - // restriction checking code to use the Daydream API directly so that a delegate provider - // doesn't get created during pre-test setup. + // TODO(crbug.com/944216): Remove this method and call Module.setForceUninstalled("vr") + // directly once we change the restriction checking code to use the Daydream API directly so + // that a delegate provider doesn't get created during pre-test setup. sDelegateProvider = null; - sAlwaysUseFallbackDelegate = useFallbackDelegate; + Module.setForceUninstalled("vr"); } /* package */ static void installModule(OnModuleInstallFinishedListener onFinishedListener) { @@ -116,7 +117,7 @@ private static VrDelegateProvider getDelegateProvider() { if (sDelegateProvider == null) { - if (sAlwaysUseFallbackDelegate || !VrModule.isInstalled()) { + if (!VrModule.isInstalled()) { sDelegateProvider = new VrDelegateProviderFallback(); } else { sDelegateProvider = VrModule.getImpl();
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java index 723b42e2..ce4f278a 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -684,7 +684,8 @@ } } Point size = new Point(contentWidth, contentHeight); - mContentVirtualDisplay.update(size, dpr, dip / dpr, null, null, null, null, null, null); + mContentVirtualDisplay.update( + size, dpr, dip / dpr, null, null, null, null, null, null, null, null); if (mTab != null && mTab.getWebContents() != null) { mTab.getWebContents().setSize(contentWidth, contentHeight); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedDebuggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedDebuggingBridge.java index 2d695a58..6148d76 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedDebuggingBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedDebuggingBridge.java
@@ -4,8 +4,10 @@ package org.chromium.chrome.browser.feed; +import com.google.android.libraries.feed.api.requestmanager.RequestManager; import com.google.android.libraries.feed.api.scope.FeedProcessScope; import com.google.android.libraries.feed.common.logging.Dumper; +import com.google.android.libraries.feed.host.logging.RequestReason; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -38,4 +40,18 @@ return "Unable to dump FeedProcessScope"; } } + + @CalledByNative + static void triggerRefresh() { + FeedProcessScope feedProcessScope = FeedProcessScopeFactory.getFeedProcessScope(); + + // Do nothing if Feed is disabled. + if (feedProcessScope == null) return; + + RequestManager requestManager = feedProcessScope.getRequestManager(); + + // Trigger a refresh with the default consumer, so notification goes to the + // FeedSchedulerHost and last fetch status and time will be updated. + requestManager.triggerRefresh(RequestReason.HOST_REQUESTED); + } }
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 3bc7acc..1e9eac10 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -890,13 +890,6 @@ {% endif %} </receiver> - {% if channel in ['default'] %} - <!-- Not used at this point --> - <service android:name="org.chromium.chrome.browser.browserservices.ClearDataService" - android:exported="false"> - </service> - {% endif %} - <activity android:name="org.chromium.chrome.browser.browserservices.ClearDataDialogActivity" android:theme="@style/Theme.Chromium.ClearDataDialogActivity" android:exported="false"/>
diff --git a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected index 0d4cc1fd..5e4ddfff 100644 --- a/chrome/android/java/monochrome_public_apk.AndroidManifest.expected +++ b/chrome/android/java/monochrome_public_apk.AndroidManifest.expected
@@ -1462,9 +1462,6 @@ android:name="org.chromium.chrome.browser.browseractions.BrowserActionsService"/> <service android:exported="false" - android:name="org.chromium.chrome.browser.browserservices.ClearDataService"/> - <service - android:exported="false" android:name="org.chromium.chrome.browser.crash.ChromeMinidumpUploadJobService" android:permission="android.permission.BIND_JOB_SERVICE"/> <service
diff --git a/chrome/android/java/res/drawable/ic_book_round.xml b/chrome/android/java/res/drawable/ic_book_round.xml index a80ae5d2..9156e0c 100644 --- a/chrome/android/java/res/drawable/ic_book_round.xml +++ b/chrome/android/java/res/drawable/ic_book_round.xml
@@ -7,10 +7,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:targetApi="21" - android:height="24dp" android:viewportHeight="36" + android:height="24dp" android:viewportHeight="37" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" - android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" - android:pathData="M24,8L12,8C10.9,8 10,8.9 10,10L10,26C10,27.1 10.9,28 12,28L24,28C25.1,28 26,27.1 26,26L26,10C26,8.9 25.1,8 24,8ZM12,10L17,10L17,18L14.5,16.5L12,18L12,10Z" /> + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" + android:pathData="M18,1L18,1C27.9411,1 36,9.0589 36,19L36,19C36,28.9411 27.9411,37 18,37L18,37C8.0589,37 0,28.9411 0,19L0,19C-0,9.0589 8.0589,1 18,1Z" /> + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" + android:pathData="M24,9L12,9C10.9,9 10,9.9 10,11L10,27C10,28.1 10.9,29 12,29L24,29C25.1,29 26,28.1 26,27L26,11C26,9.9 25.1,9 24,9Z" /> + <path android:fillColor="@color/light_active_color" android:fillType="nonZero" + android:pathData="M24,27l-12,0l0,-16l2,0l0,8l2.5,-1.5l2.5,1.5l0,-8l5,0z" /> </vector> +
diff --git a/chrome/android/java/res/drawable/ic_equals_sign_round.xml b/chrome/android/java/res/drawable/ic_equals_sign_round.xml index b94618d2..65d2b6a9 100644 --- a/chrome/android/java/res/drawable/ic_equals_sign_round.xml +++ b/chrome/android/java/res/drawable/ic_equals_sign_round.xml
@@ -9,8 +9,8 @@ tools:targetApi="21" android:height="24dp" android:viewportHeight="36" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" android:pathData="M10,14L26,14L26,17L10,17L10,14ZM10,19L26,19L26,22L10,22L10,19Z" /> </vector>
diff --git a/chrome/android/java/res/drawable/ic_event_round.xml b/chrome/android/java/res/drawable/ic_event_round.xml index 87a69403..c49d5cbd 100644 --- a/chrome/android/java/res/drawable/ic_event_round.xml +++ b/chrome/android/java/res/drawable/ic_event_round.xml
@@ -2,15 +2,18 @@ <!-- Copyright 2019 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:targetApi="21" android:height="24dp" android:viewportHeight="36" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" - android:pathData="M23,18L18,18L18,23L23,23L23,18ZM22,7L22,9L14,9L14,7L12,7L12,9L11,9C9.89,9 9.01,9.9 9.01,11L9,25C9,26.1 9.89,27 11,27L25,27C26.1,27 27,26.1 27,25L27,11C27,9.9 26.1,9 25,9L24,9L24,7L22,7ZM25,25L11,25L11,14L25,14L25,25Z" /> + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" + android:pathData="M25,10L24,10L24,8L22,8L22,10L14,10L14,8L12,8L12,10L11,10C9.89,10 9.01,10.9 9.01,12L9,26C9,27.1 9.89,28 11,28L25,28C26.1,28 27,27.1 27,26L27,12C27,10.9 26.1,10 25,10Z" /> + <path android:fillColor="@color/light_active_color" android:fillType="nonZero" + android:pathData="M25,26l-14,0l0,-10l14,0z" /> + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" + android:pathData="M20.5,19L20.5,19C19.12,19 18,20.12 18,21.5L18,21.5C18,22.88 19.12,24 20.5,24L20.5,24C21.88,24 23,22.88 23,21.5L23,21.5C23,20.12 21.88,19 20.5,19Z" /> </vector>
diff --git a/chrome/android/java/res/drawable/ic_loop_round.xml b/chrome/android/java/res/drawable/ic_loop_round.xml index 3a54b769..4861e9a 100644 --- a/chrome/android/java/res/drawable/ic_loop_round.xml +++ b/chrome/android/java/res/drawable/ic_loop_round.xml
@@ -9,8 +9,8 @@ tools:targetApi="21" android:height="24dp" android:viewportHeight="36" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" android:pathData="M18,12L18,15L22,11L18,7L18,10C13.58,10 10,13.58 10,18C10,19.57 10.46,21.03 11.24,22.26L12.7,20.8C12.25,19.97 12,19.01 12,18C12,14.69 14.69,12 18,12ZM24.76,13.74L23.3,15.2C23.74,16.04 24,16.99 24,18C24,21.31 21.31,24 18,24L18,21L14,25L18,29L18,26C22.42,26 26,22.42 26,18C26,16.43 25.54,14.97 24.76,13.74Z" /> </vector>
diff --git a/chrome/android/java/res/drawable/ic_swap_vert_round.xml b/chrome/android/java/res/drawable/ic_swap_vert_round.xml index 532e868..74ec025 100644 --- a/chrome/android/java/res/drawable/ic_swap_vert_round.xml +++ b/chrome/android/java/res/drawable/ic_swap_vert_round.xml
@@ -9,8 +9,8 @@ tools:targetApi="21" android:height="24dp" android:viewportHeight="36" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" android:pathData="M22,23.01L22,16L20,16L20,23.01L17,23.01L21,27L25,23.01L22,23.01ZM15,9L11,12.99L14,12.99L14,20L16,20L16,12.99L19,12.99L15,9Z" /> </vector>
diff --git a/chrome/android/java/res/drawable/ic_wb_sunny_round.xml b/chrome/android/java/res/drawable/ic_wb_sunny_round.xml index 1c4a74b..4c24397c 100644 --- a/chrome/android/java/res/drawable/ic_wb_sunny_round.xml +++ b/chrome/android/java/res/drawable/ic_wb_sunny_round.xml
@@ -9,8 +9,8 @@ tools:targetApi="21" android:height="24dp" android:viewportHeight="36" android:viewportWidth="36" android:width="24dp"> - <path android:fillColor="@color/default_icon_color_blue" android:fillType="evenOdd" + <path android:fillColor="@color/light_active_color" android:fillType="evenOdd" android:pathData="M18,0L18,0C27.9411,-0 36,8.0589 36,18L36,18C36,27.9411 27.9411,36 18,36L18,36C8.0589,36 0,27.9411 0,18L0,18C-0,8.0589 8.0589,0 18,0Z" /> - <path android:fillColor="#FFFFFF" android:fillType="nonZero" + <path android:fillColor="@color/default_icon_color_inverse" android:fillType="nonZero" android:pathData="M12.76,11.29L10.96,9.5L9.55,10.91L11.34,12.7L12.76,11.29ZM10,16.95L7,16.95L7,18.95L10,18.95L10,16.95ZM19,7L17,7L17,9.95L19,9.95L19,7ZM26.45,10.91L25.04,9.5L23.25,11.29L24.66,12.7L26.45,10.91ZM23.24,24.61L25.03,26.41L26.44,25L24.64,23.21L23.24,24.61ZM26,16.95L26,18.95L29,18.95L29,16.95L26,16.95ZM18,11.95C14.69,11.95 12,14.64 12,17.95C12,21.26 14.69,23.95 18,23.95C21.31,23.95 24,21.26 24,17.95C24,14.64 21.31,11.95 18,11.95ZM17,28.9L19,28.9L19,25.95L17,25.95L17,28.9ZM9.55,24.99L10.96,26.4L12.75,24.6L11.34,23.19L9.55,24.99Z" /> </vector>
diff --git a/chrome/android/java/res/drawable/logo_partly_cloudy.xml b/chrome/android/java/res/drawable/logo_partly_cloudy.xml new file mode 100644 index 0000000..8b484acc --- /dev/null +++ b/chrome/android/java/res/drawable/logo_partly_cloudy.xml
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<vector android:height="24dp" android:viewportHeight="36" + android:viewportWidth="36" android:width="24dp" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt" + xmlns:tools="http://schemas.android.com/tools" + tools:targetApi="21"> + <path android:fillColor="#D9D9D9" android:fillType="nonZero" + android:pathData="M31.143,24.2C31.2227,23.9095 31.2635,23.6098 31.2645,23.3086C31.2628,21.7387 30.199,20.367 28.6741,19.9687C27.1493,19.5703 25.5463,20.2454 24.7711,21.6123C23.7316,20.7741 22.301,20.6053 21.0935,21.1783C19.8861,21.7513 19.1167,22.9643 19.1157,24.2963C19.1166,24.5067 19.1365,24.7166 19.1752,24.9235C19.1132,24.9235 19.0537,24.9235 18.9917,24.9235C17.3958,24.9221 16.083,26.175 16.0165,27.763L32.9529,27.763C32.9775,27.5995 32.9907,27.4345 32.9926,27.2691C32.9973,25.9831 32.2848,24.8008 31.143,24.2L31.143,24.2Z" + /> + <path android:fillColor="#FFE05A" android:fillType="nonZero" + android:pathData="M18.3719,24.2247C18.3968,22.763 19.1836,21.4196 20.4487,20.6782C21.7138,19.9369 23.2752,19.9044 24.5702,20.5926C25.3732,19.6503 26.5524,19.1083 27.7934,19.1111L27.9595,19.1111C28.4556,15.1787 26.5433,11.3318 23.1024,9.3405C19.6615,7.3492 15.3586,7.5991 12.1736,9.9753L12.3025,9.9753C14.1614,9.9793 15.7111,11.3932 15.8777,13.237C17.6034,13.5325 18.8653,15.0216 18.8678,16.7654L18.8678,16.8938L18.8355,17.6346L8.2066,17.6346L8.2066,17.8815C8.2068,22.2585 11.0998,26.1133 15.3149,27.3531C15.5377,25.7569 16.7758,24.49 18.3719,24.2247Z" + /> + <path android:fillColor="#D9D9D9" android:fillType="nonZero" + android:pathData="M15.2727,13.9259C15.2207,13.9259 15.1711,13.9259 15.1215,13.9259C15.1379,13.8031 15.147,13.6794 15.1488,13.5556C15.1504,12.15 14.1192,10.9548 12.7237,10.7447C11.3282,10.5346 9.9884,11.3728 9.5727,12.716C9.128,12.2293 8.498,11.9514 7.8372,11.9506L7.7107,11.9506C6.3414,11.9506 5.2314,13.0561 5.2314,14.4198C5.2316,14.5856 5.2482,14.751 5.281,14.9136C4.153,14.9505 3.2098,15.779 3.0322,16.8889L18.124,16.8889C18.124,16.8469 18.124,16.8074 18.124,16.7654C18.124,15.1972 16.8474,13.9259 15.2727,13.9259Z" + /> +</vector>
diff --git a/chrome/android/java/res/drawable/logo_partly_cloudy_light.xml b/chrome/android/java/res/drawable/logo_partly_cloudy_light.xml deleted file mode 100644 index 1238f7a..0000000 --- a/chrome/android/java/res/drawable/logo_partly_cloudy_light.xml +++ /dev/null
@@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2019 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<vector - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - xmlns:tools="http://schemas.android.com/tools" - tools:targetApi="21" - android:height="24dp" android:viewportHeight="48" - android:viewportWidth="48" android:width="24dp"> - <path android:fillColor="#FDD835" android:pathData="M24,24m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"/> - <path android:fillAlpha="0.1" android:fillColor="#FFFFFF" android:pathData="M24,4.25c11,0 19.93,8.89 20,19.88c0,-0.04 0,-0.08 0,-0.12c0,-11.05 -8.95,-20 -20,-20S4,12.95 4,24c0,0.04 0,0.08 0,0.12C4.07,13.14 13,4.25 24,4.25z"/> - <path android:fillAlpha="0.1" android:fillColor="#BF360C" android:pathData="M44,23.88C43.93,34.86 35,43.75 24,43.75S4.07,34.86 4,23.88c0,0.04 0,0.08 0,0.12c0,11.05 8.95,20 20,20s20,-8.95 20,-20C44,23.96 44,23.92 44,23.88z"/> - <group> - <clip-path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z M 0,0"/> - <path android:pathData="M44.25,36.69l-10.59,-10.349998l-28.13,10.150002l0.0,7.5099983l38.72,0.0z"> - <aapt:attr name="android:fillColor"> - <gradient android:endX="27.1957" android:endY="44.8146" - android:startX="21.0923" android:startY="32.9892" android:type="linear"> - <item android:color="#19BF360C" android:offset="0"/> - <item android:color="#05BF360C" android:offset="1"/> - </gradient> - </aapt:attr> - </path> - </group> - <group> - <clip-path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z M 0,0"/> - <path android:fillAlpha="0.1" android:fillColor="#212121" android:pathData="M28,39.75H14.01 c-6.59,0,-11.93,-5.31,-12,-11.88c0,0.04,0,0.08,0,0.12c0,6.63,5.37,12,12,12H28c4.42,0,8,-3.58,8,-8c0,-0.04,0,-0.08,0,-0.12 C35.93,36.24,32.38,39.75,28,39.75z"/> - </group> - <group> - <clip-path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z M 0,0"/> - <path android:fillColor="#EEEEEE" android:pathData="M28,24h-2.67c-1.65,-4.66,-6.09,-8,-11.31,-8c-6.63,0,-12,5.37,-12,12s5.37,12,12,12H28 c4.42,0,8,-3.58,8,-8C36,27.58,32.42,24,28,24z"/> - </group> - <group> - <clip-path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z M 0,0"/> - <path android:fillAlpha="0.1" android:fillColor="#BF360C" android:pathData="M28,40H14.01 c-6.59,0,-11.93,-5.31,-12,-11.88c0,0.04,0,0.08,0,0.12c0,6.63,5.37,12,12,12H28c4.42,0,8,-3.58,8,-8c0,-0.04,0,-0.08,0,-0.12 C35.93,36.49,32.38,40,28,40z"/> - </group> - <group> - <clip-path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z M 0,0"/> - <path android:fillAlpha="0.2" android:fillColor="#FFFFFF" android:pathData="M14.01,16.25c5.22,0,9.67,3.34,11.31,8H28c4.38,0,7.93,3.51,8,7.88 c0,-0.04,0,-0.08,0,-0.12c0,-4.42,-3.58,-8,-8,-8h-2.67c-1.65,-4.66,-6.09,-8,-11.31,-8c-6.63,0,-12,5.37,-12,12c0,0.04,0,0.08,0,0.12 C2.08,21.56,7.43,16.25,14.01,16.25z"/> - </group> - <path android:pathData="M24,4C13.95,4 5.63,11.42 4.22,21.07c-1.39,1.96 -2.2,4.35 -2.2,6.93c0,5.84 4.18,10.71 9.71,11.78C15.11,42.42 19.37,44 24,44c11.05,0 20,-8.95 20,-20C44,12.95 35.05,4 24,4z"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="9.8293" android:centerY="9.8583" - android:gradientRadius="40.0515" android:type="radial"> - <item android:color="#19FFFFFF" android:offset="0"/> - <item android:color="#00FFFFFF" android:offset="1"/> - </gradient> - </aapt:attr> - </path> -</vector>
diff --git a/chrome/android/java/res/drawable/tabstrip_favicon_background.xml b/chrome/android/java/res/drawable/tabstrip_favicon_background.xml new file mode 100644 index 0000000..445c96ca --- /dev/null +++ b/chrome/android/java/res/drawable/tabstrip_favicon_background.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<layer-list +xmlns:android="http://schemas.android.com/apk/res/android" > + <item + android:left="8dp" + android:top="8dp" + android:right="8dp" + android:bottom="8dp"> + <shape + android:shape="oval"> + <solid android:color="@color/modern_grey_100" /> + </shape> + </item> +</layer-list> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/clear_browsing_data_tabs.xml b/chrome/android/java/res/layout/clear_browsing_data_tabs.xml index 8da6de0..8b6ad5f 100644 --- a/chrome/android/java/res/layout/clear_browsing_data_tabs.xml +++ b/chrome/android/java/res/layout/clear_browsing_data_tabs.xml
@@ -23,7 +23,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:tabTextColor="@color/disabled_text_color" - app:tabSelectedTextColor="@color/clear_browsing_data_selected_tab_color" + app:tabSelectedTextColor="@color/tab_layout_selected_tab_color" app:tabMode="fixed" app:tabMaxWidth="0dp" app:tabGravity="fill" />
diff --git a/chrome/android/java/res/layout/infobar_translate_compact_content.xml b/chrome/android/java/res/layout/infobar_translate_compact_content.xml index 679386bd..dc12798 100644 --- a/chrome/android/java/res/layout/infobar_translate_compact_content.xml +++ b/chrome/android/java/res/layout/infobar_translate_compact_content.xml
@@ -10,7 +10,7 @@ android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> - + <!-- TODO(huayinz): Change app:tabIndicatorColor to some common color reference --> <org.chromium.chrome.browser.infobar.translate.TranslateTabLayout android:id="@+id/translate_infobar_tabs" android:layout_width="0dp" @@ -18,8 +18,8 @@ android:layout_weight="1" android:requiresFadingEdge="horizontal" android:fadingEdgeLength="@dimen/infobar_translate_fade_edge_length" - app:tabIndicatorColor="@color/infobar_accent_blue" - app:tabSelectedTextColor="@color/infobar_accent_blue" + app:tabIndicatorColor="@color/tab_layout_selected_tab_color" + app:tabSelectedTextColor="@color/tab_layout_selected_tab_color" app:tabGravity="fill" app:tabMode="scrollable" />
diff --git a/chrome/android/java/res/layout/keyboard_accessory_tabs.xml b/chrome/android/java/res/layout/keyboard_accessory_tabs.xml index 4aa193f2..2a39504c 100644 --- a/chrome/android/java/res/layout/keyboard_accessory_tabs.xml +++ b/chrome/android/java/res/layout/keyboard_accessory_tabs.xml
@@ -8,7 +8,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" app:tabIndicatorHeight="@dimen/divider_height" app:tabTextColor="@color/default_icon_color" - app:tabSelectedTextColor="@color/default_icon_color_blue" + app:tabSelectedTextColor="@color/tab_layout_selected_tab_color" android:layout_gravity="end" android:layout_width="wrap_content" android:layout_height="@dimen/keyboard_accessory_tab_size"/>
diff --git a/chrome/android/java/res/layout/payment_option_edit_icon.xml b/chrome/android/java/res/layout/payment_option_edit_icon.xml index d6b0750..2f8a398 100644 --- a/chrome/android/java/res/layout/payment_option_edit_icon.xml +++ b/chrome/android/java/res/layout/payment_option_edit_icon.xml
@@ -4,27 +4,26 @@ found in the LICENSE file. --> <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/payments_open_editor_pencil_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:contentDescription="@string/payments_edit_button"> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/payments_open_editor_pencil_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/payments_edit_button"> <View - android:layout_width="1dp" - android:layout_height="48dp" - android:layout_gravity="center_vertical" - android:layout_marginStart="@dimen/editor_dialog_section_large_spacing" - android:layout_marginEnd="@dimen/editor_dialog_section_large_spacing" - android:background="@color/payments_section_separator" - android:importantForAccessibility="no"/> + android:layout_width="1dp" + android:layout_height="48dp" + android:layout_gravity="center_vertical" + android:layout_marginStart="@dimen/editor_dialog_section_large_spacing" + android:layout_marginEnd="@dimen/editor_dialog_section_large_spacing" + style="@style/VerticalDivider" /> <ImageView - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_gravity="center_vertical" - android:src="@drawable/ic_edit_24dp" - tools:ignore="ContentDescription" - android:importantForAccessibility="no" /> + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center_vertical" + android:src="@drawable/ic_edit_24dp" + tools:ignore="ContentDescription" + android:importantForAccessibility="no" /> </LinearLayout>
diff --git a/chrome/android/java/res/layout/payment_request.xml b/chrome/android/java/res/layout/payment_request.xml index f993aaa..9979c2e 100644 --- a/chrome/android/java/res/layout/payment_request.xml +++ b/chrome/android/java/res/layout/payment_request.xml
@@ -14,7 +14,7 @@ android:gravity="center" app:maxWidthLandscape="@dimen/payments_ui_max_dialog_width" app:maxWidthPortrait="@dimen/payments_ui_max_dialog_width" - android:background="@color/modern_primary_color" > + android:background="@color/payment_request_bg" > <include layout="@layout/payment_request_header" /> <include layout="@layout/payment_request_spinny" />
diff --git a/chrome/android/java/res/layout/payment_request_bottom_bar.xml b/chrome/android/java/res/layout/payment_request_bottom_bar.xml index 603ef72..7e29649 100644 --- a/chrome/android/java/res/layout/payment_request_bottom_bar.xml +++ b/chrome/android/java/res/layout/payment_request_bottom_bar.xml
@@ -11,7 +11,7 @@ android:layout_height="wrap_content" android:layout_width="match_parent" android:padding="@dimen/editor_dialog_section_large_spacing" - android:background="@color/modern_primary_color" + android:background="@color/payment_request_bg" android:visibility="gone" > <ImageView
diff --git a/chrome/android/java/res/layout/payment_request_header.xml b/chrome/android/java/res/layout/payment_request_header.xml index 12e9602c..f133b058 100644 --- a/chrome/android/java/res/layout/payment_request_header.xml +++ b/chrome/android/java/res/layout/payment_request_header.xml
@@ -8,14 +8,14 @@ Request dialog: Displays an X in the top right corner, allowing the user to close it. Result dialog: Displays no X. Title goes all the way to the end. --> -<merge xmlns:android="http://schemas.android.com/apk/res/android" > +<merge xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> <org.chromium.chrome.browser.payments.ui.PaymentRequestHeader android:id="@+id/header" android:layout_height="wrap_content" android:layout_width="match_parent" - android:minHeight="64dp" - android:background="@color/modern_primary_color" > + android:minHeight="64dp"> <ImageView android:id="@+id/icon_view" @@ -68,7 +68,8 @@ android:src="@drawable/btn_close" android:contentDescription="@string/close" android:background="?attr/selectableItemBackground" - android:scaleType="center" /> + android:scaleType="center" + app:tint="@color/standard_mode_tint" /> </org.chromium.chrome.browser.payments.ui.PaymentRequestHeader> </merge> \ No newline at end of file
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index b1d76956..efb85db 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -57,6 +57,9 @@ <!-- Snackbar colors --> <color name="snackbar_background_color">#282C32</color> + <!-- Bottom sheet colors --> + <color name="sheet_bg_color">@color/default_bg_color_elev_2</color> + <!-- Tab Switcher Colors --> <color name="tab_switcher_background">#14181C</color> <color name="accessibility_tab_switcher_list_item">#252525</color> @@ -187,9 +190,9 @@ <color name="bookmark_widget_background">#DDFFFFFF</color> <!-- Payments UI colors --> + <color name="payment_request_bg">@color/sheet_bg_color</color> <color name="payments_section_edit_background">@color/modern_secondary_color</color> <color name="payments_section_chevron">#B2B2B2</color> - <color name="payments_section_separator">@color/modern_grey_300</color> <!-- Translate Infobar colors --> <color name="translate_overflow_menu_divider_color">@color/modern_grey_300</color> @@ -202,6 +205,6 @@ <color name="bottom_system_nav_divider_color">@color/black_alpha_12</color> <color name="search_box_hint">@color/default_text_color_secondary</color> <color name="thumbnail_placeholder_on_primary_bg">@color/modern_secondary_color</color> - <color name="clear_browsing_data_selected_tab_color">@color/modern_blue_600</color> + <color name="tab_layout_selected_tab_color">@color/default_text_color_blue</color> </resources>
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 0d699fe..60e7f4a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import android.app.Activity; import android.app.Notification; import android.app.Service; import android.content.Intent; @@ -104,6 +105,13 @@ public void initCommandLine(CommandLine instance) {} /** + * Inform platform of current display mode. + * @param displayMode the new display mode (see WebDisplayMode) + * @param activity the affected activity. + */ + public void setDisplayModeForActivity(int displayMode, Activity activity) {} + + /** * Creates a new {@link AccountManagerDelegate}. * @return the created {@link AccountManagerDelegate}. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java index 5d9fbff..2c30853 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -8,6 +8,7 @@ import android.app.Application; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.os.Bundle; import android.support.annotation.Nullable; @@ -40,6 +41,7 @@ import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides; import org.chromium.chrome.browser.init.InvalidStartupDialog; import org.chromium.chrome.browser.metrics.UmaUtils; +import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.vr.OnExitVrRequestListener; import org.chromium.chrome.browser.vr.VrModuleProvider; @@ -69,7 +71,7 @@ // Quirk: context.getApplicationContext() returns null during this method. @Override protected void attachBaseContext(Context context) { - boolean isBrowserProcess = !ContextUtils.getProcessName().contains(":"); + boolean isBrowserProcess = isBrowserProcess(); if (isBrowserProcess) UmaUtils.recordMainEntryPointTime(); super.attachBaseContext(context); ContextUtils.initApplicationContext(this); @@ -135,6 +137,10 @@ ChromePreferenceManager.COMMAND_LINE_ON_NON_ROOTED_ENABLED_KEY, false); } + private static boolean isBrowserProcess() { + return !ContextUtils.getProcessName().contains(":"); + } + private static void updateMemoryPressurePolling(@ApplicationState int newState) { if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { MemoryPressureMonitor.INSTANCE.enablePolling(); @@ -224,6 +230,15 @@ }); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + // TODO(huayinz): Add observer pattern for application configuration changes. + if (isBrowserProcess()) { + SystemNightModeMonitor.getInstance().onApplicationConfigurationChanged(); + } + } + /** Returns the application-scoped component. */ public static ChromeAppComponent getComponent() { if (sComponent == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java index eab14af..75881ac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
@@ -103,6 +103,6 @@ // NightModeStateProvider.Observer implementation. @Override public void onNightModeStateChanged() { - recreate(); + if (!isFinishing()) recreate(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 5e49b1d2..58788f8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -227,6 +227,7 @@ public static final String DOWNLOAD_OFFLINE_CONTENT_PROVIDER = "UseDownloadOfflineContentProvider"; public static final String DOWNLOADS_LOCATION_CHANGE = "DownloadsLocationChange"; + public static final String DRAW_VERTICALLY_EDGE_TO_EDGE = "DrawVerticallyEdgeToEdge"; public static final String EPHEMERAL_TAB = "EphemeralTab"; public static final String EXPERIMENTAL_APP_BANNERS = "ExperimentalAppBanners"; public static final String EXPERIMENTAL_UI = "ExperimentalUi";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java index 9eddd72..9fbee15 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExpirationDateFixFlowPrompt.java
@@ -77,14 +77,12 @@ mMonthInput.addTextChangedListener(this); mMonthInput.setOnFocusChangeListener((view, hasFocus) -> { mDidFocusOnMonth |= hasFocus; - validate(); }); mYearInput = (EditText) mDialogView.findViewById(R.id.cc_year_edit); mYearInput.addTextChangedListener(this); mYearInput.setOnFocusChangeListener((view, hasFocus) -> { mDidFocusOnYear |= hasFocus; - validate(); }); mDialogModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) @@ -142,7 +140,12 @@ @Override public void onDismiss(PropertyModel model, int dismissalCause) { - mDelegate.onPromptDismissed(); + // Do not call dismissed on the delegate if dialog was dismissed either because the user + // accepted to save the card or was dismissed by native code. + if (dismissalCause != DialogDismissalCause.POSITIVE_BUTTON_CLICKED + && dismissalCause != DialogDismissalCause.DISMISSED_BY_NATIVE) { + mDelegate.onPromptDismissed(); + } } /** @@ -169,17 +172,14 @@ * @param errorType The type of error detected. */ private void moveFocus(@ErrorType int errorType) { - if (errorType != ErrorType.NOT_ENOUGH_INFO) { - // There is an error or the month and year is filled and valid. - return; - } if (mMonthInput.isFocused() && mMonthInput.getText().length() == AutofillUiUtils.EXPIRATION_FIELDS_LENGTH) { - // The user just finished typing in the month field and there are no validation - // errors. - // Year was not filled, move focus there. - mYearInput.requestFocus(); - mDidFocusOnYear = true; + // The user just finished typing in the month field and if there are no errors in the + // month, then move focus to the year input. + if (errorType != ErrorType.EXPIRATION_MONTH) { + mYearInput.requestFocus(); + mDidFocusOnYear = true; + } } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java index a717f12c7..1c28bcc9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java
@@ -161,6 +161,7 @@ public void onClick(PropertyModel model, int buttonType) { if (buttonType == ModalDialogProperties.ButtonType.POSITIVE) { mDelegate.onUserAccept(mUserNameInput.getText().toString()); + mModalDialogManager.dismissDialog(model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED); } else if (buttonType == ModalDialogProperties.ButtonType.NEGATIVE) { mModalDialogManager.dismissDialog(model, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED); } @@ -168,6 +169,11 @@ @Override public void onDismiss(PropertyModel model, int dismissalCause) { - mDelegate.onPromptDismissed(); + // Do not call dismissed on the delegate if dialog was dismissed either because the user + // accepted to save the card or was dismissed by native code. + if (dismissalCause != DialogDismissalCause.POSITIVE_BUTTON_CLICKED + && dismissalCause != DialogDismissalCause.DISMISSED_BY_NATIVE) { + mDelegate.onPromptDismissed(); + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisher.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisher.java deleted file mode 100644 index d80dec7..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisher.java +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import android.app.Notification; -import android.app.NotificationManager; -import android.content.Context; -import android.content.res.Resources; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; -import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; - -/** - * The class responsible for showing the "Would you like to clear your data", the "You are clearing - * your data" and the "Your data has been cleared" notifications that occur when a user uninstalls - * (or clears data for) a Trusted Web Activity client app. - * - * Lifecycle: This class holds no state, create an instance or share as you like. - * Thread safety: Methods on this class can be called from any thread. - */ -public class ClearDataNotificationPublisher { - private static final String NOTIFICATION_TAG_CLEAR_DATA = "ClearDataNotification.ClearData"; - - /* package */ void showClearDataNotification(Context context, String appName, String domain, - boolean uninstall) { - // We base the notification id on the URL so we don't have duplicate Notifications - // offering to clear the same URL. - int notificationId = domain.hashCode(); - - Resources res = context.getResources(); - String title = res.getString(uninstall ? R.string.you_have_uninstalled_app - : R.string.you_have_cleared_app, appName); - - Notification notification = NotificationBuilderFactory - .createChromeNotificationBuilder(true /* preferCompat */, - ChannelDefinitions.ChannelId.BROWSER) - .setContentTitle(title) - .setContentText(res.getString(R.string.clear_related_data, domain)) - .addAction(R.drawable.btn_star, res.getString(R.string.clear_data_delete), - ClearDataService.getClearDataIntent(context, domain, notificationId)) - .addAction(R.drawable.btn_close, res.getString(R.string.close), - ClearDataService.getDismissIntent(context, notificationId)) - .setSmallIcon(R.drawable.ic_chrome) - .build(); - - NotificationManager manager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - manager.notify(NOTIFICATION_TAG_CLEAR_DATA, notificationId, notification); - } - - /* package */ void dismissClearDataNotification(Context context, int notificationId) { - NotificationManager manager = - (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - manager.cancel(NOTIFICATION_TAG_CLEAR_DATA, notificationId); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataService.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataService.java deleted file mode 100644 index 89282763..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataService.java +++ /dev/null
@@ -1,122 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import android.support.annotation.Nullable; - -import org.chromium.base.Log; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.preferences.website.SiteDataCleaner; -import org.chromium.chrome.browser.preferences.website.WebsitePermissionsFetcher; - -/** - * A background service that clears browsing data. - * - * Lifecycle: This is a Service, so it will be created by the Android Framework. - * Thread safety: handles intents on the main thread. - */ -public class ClearDataService extends Service { - private static final String TAG = "ClearDataService"; - - /* package */ static final String ACTION_CLEAR_DATA = - "org.chromium.chrome.browser.browserservices.ClearDataService.CLEAR_DATA"; - /* package */ static final String ACTION_DISMISS = - "org.chromium.chrome.browser.browserservices.ClearDataService.DISMISS"; - - /* package */ static final String EXTRA_NOTIFICATION_ID = - "org.chromium.chrome.browser.browserservices.ClearDataService.NOTIFICATION_ID"; - /* package */ static final String EXTRA_DOMAIN = - "org.chromium.chrome.browser.browserservices.ClearDataService.DOMAIN"; - - private final ClearDataNotificationPublisher mNotificationManager; - private final DomainDataCleaner mCleaner; - - /** Constructor required by Android with default dependencies. */ - public ClearDataService() { - this(new ClearDataNotificationPublisher(), - new DomainDataCleaner(ChromeBrowserInitializer.getInstance(), - new SiteDataCleaner(), new WebsitePermissionsFetcher())); - } - - /** Constructor with dependency injection for testing. */ - public ClearDataService(ClearDataNotificationPublisher notificationManager, - DomainDataCleaner cleaner) { - super(); - mNotificationManager = notificationManager; - mCleaner = cleaner; - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - if (intent == null) { - stopSelf(); - return START_NOT_STICKY; - } - // ClearDataService is not exported, so as long as we don't let PendingIntents pointing to - // this class leak to other Android applications, we can trust that this code can only be - // called from Chrome (or a Notification that Chrome created). - - if (!intent.hasExtra(EXTRA_NOTIFICATION_ID)) { - Log.w(TAG, "Got Intent without Notification Id"); - stopSelf(); - return START_NOT_STICKY; - } - int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, 0); - - if (ACTION_CLEAR_DATA.equals(intent.getAction())) { - String domain = intent.getStringExtra(EXTRA_DOMAIN); - if (domain == null) { - Log.w(TAG, "Got Clear Data Intent without EXTRA_DOMAIN."); - stopSelf(); - return START_NOT_STICKY; - } - mCleaner.clearData(domain, this::stopSelf); - - mNotificationManager.dismissClearDataNotification(this, notificationId); - } else if (ACTION_DISMISS.equals(intent.getAction())) { - mNotificationManager.dismissClearDataNotification(this, notificationId); - } - - return START_REDELIVER_INTENT; - } - - /** - * Creates a PendingIntent to clear data for the given |domain| and cancel the notification with - * the given |id|. - */ - public static PendingIntent getClearDataIntent(Context context, String domain, int id) { - Intent intent = new Intent(context, ClearDataService.class); - intent.setAction(ACTION_CLEAR_DATA); - intent.putExtra(EXTRA_NOTIFICATION_ID, id); - // TODO(peconn): Consider putting this in data instead. - intent.putExtra(EXTRA_DOMAIN, domain); - // See similar code in {@link getDismissIntent}. - return PendingIntent.getService(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - /** - * Creates a PendingIntent to dismiss the Notification with the given |id|. - */ - public static PendingIntent getDismissIntent(Context context, int id) { - Intent intent = new Intent(context, ClearDataService.class); - intent.setAction(ACTION_DISMISS); - // Store the notification ID in the intent itself so we can retrieve it later. - intent.putExtra(EXTRA_NOTIFICATION_ID, id); - // Also use the notification ID as the request code so we can have multiple pending intents - // existing at the same time for different applications/urls. - return PendingIntent.getService(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java index fd65cd0f..74f7cd5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -69,7 +69,7 @@ /** Constructor with default dependencies for Android. */ public ClientAppBroadcastReceiver() { - this(new DialogClearDataStrategy(), new ClientAppDataRegister(), + this(new ClearDataStrategy(), new ClientAppDataRegister(), ChromeApplication.getComponent().resolvePreferenceManager()); } @@ -117,32 +117,8 @@ } } - interface ClearDataStrategy { - void execute(Context context, ClientAppDataRegister register, int uid, boolean uninstalled); - } - - static class NotificationClearDataStrategy implements ClearDataStrategy { - private final ClearDataNotificationPublisher mNotificationPublisher; - - NotificationClearDataStrategy(ClearDataNotificationPublisher notificationPublisher) { - mNotificationPublisher = notificationPublisher; - } - - @Override - public void execute(Context context, ClientAppDataRegister register, - int uid, boolean uninstalled) { - String appName = register.getAppNameForRegisteredUid(uid); - Set<String> domains = register.getDomainsForRegisteredUid(uid); - - for (String domain : domains) { - mNotificationPublisher.showClearDataNotification(context, appName, domain, - uninstalled); - } - } - } - - static class DialogClearDataStrategy implements ClearDataStrategy { - @Override + /** Implemented as a class partially for historic reasons, partially to help testing. */ + static class ClearDataStrategy { public void execute(Context context, ClientAppDataRegister register, int uid, boolean uninstalled) { // Retrieving domains and origins ahead of time, because the register is about to be
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DomainDataCleaner.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DomainDataCleaner.java deleted file mode 100644 index 0b6345d..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/DomainDataCleaner.java +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import org.chromium.base.library_loader.ProcessInitException; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.preferences.website.SiteDataCleaner; -import org.chromium.chrome.browser.preferences.website.Website; -import org.chromium.chrome.browser.preferences.website.WebsitePermissionsFetcher; -import org.chromium.chrome.browser.util.UrlUtilities; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -/** - * Implements data clearing for entire domains. - */ -class DomainDataCleaner { - private final ChromeBrowserInitializer mChromeBrowserInitializer; - private final SiteDataCleaner mDataCleaner; - private final WebsitePermissionsFetcher mWebsitePermissionsFetcher; - - DomainDataCleaner(ChromeBrowserInitializer chromeBrowserInitializer, - SiteDataCleaner dataCleaner, WebsitePermissionsFetcher websitePermissionsFetcher) { - mChromeBrowserInitializer = chromeBrowserInitializer; - mDataCleaner = dataCleaner; - mWebsitePermissionsFetcher = websitePermissionsFetcher; - } - - /** - * Clears the data of all {@link Website}s associated with the given domain. - * Must be called on the main thread. - * Doesn't require native to be initialized prior to the call. - */ - void clearData(String domain, Runnable finishCallback) { - try { - mChromeBrowserInitializer.handleSynchronousStartup(); - } catch (ProcessInitException e) { - throw new RuntimeException("Failed to initialize native library", e); - } - - mWebsitePermissionsFetcher.fetchAllPreferences( - sites -> clearData(collectSitesOfTargetDomain(sites, domain), finishCallback::run)); - } - - private void clearData( - Collection<Website> sites, Website.StoredDataClearedCallback finishCallback) { - clearDataOfCurrentAndScheduleNext(sites.iterator(), finishCallback); - } - - /** - * Data cleaning for a collection of {@link Website}s is implemented sequentially to avoid - * relying on thread-safety of native methods being used. - * The asynchronous tasks are chained using recursion. - */ - private void clearDataOfCurrentAndScheduleNext( - Iterator<Website> siteIterator, Website.StoredDataClearedCallback finishCallback) { - if (!siteIterator.hasNext()) { - finishCallback.onStoredDataCleared(); - return; - } - mDataCleaner.clearData(siteIterator.next(), - () -> clearDataOfCurrentAndScheduleNext(siteIterator, finishCallback)); - } - - private Collection<Website> collectSitesOfTargetDomain( - Collection<Website> sites, String domain) { - List<Website> sitesToClear = new ArrayList<>(); - for (Website site : sites) { - String origin = site.getAddress().getOrigin(); - if (UrlUtilities.getDomainAndRegistry(origin, true).equals(domain)) { - sitesToClear.add(site); - } - } - return sitesToClear; - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java index 72b2a58e..e5716db 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -355,6 +355,12 @@ } } + @CalledByNative + private void notifyWillUseSurfaceControl() { + mAlwaysTranslucent = true; + mCompositorSurfaceManager.requestSurface(getSurfacePixelFormat()); + } + /** * Converts the layout into compositor layers. This is to be called on every frame the layout * is changing.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index b766af5d..17992ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -299,7 +299,7 @@ @Override protected NightModeStateProvider createNightModeStateProvider() { - mNightModeStateController = new CustomTabNightModeStateController(); + mNightModeStateController = new CustomTabNightModeStateController(getLifecycleDispatcher()); return mNightModeStateController; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java index ac7133ac..ea32135 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java
@@ -9,20 +9,36 @@ import android.support.customtabs.CustomTabsIntent; import android.support.v7.app.AppCompatDelegate; +import org.chromium.base.ObserverList; +import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.night_mode.NightModeStateProvider; +import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.IntentUtils; /** * Maintains and provides the night mode state for {@link CustomTabActivity}. */ -class CustomTabNightModeStateController implements NightModeStateProvider { +class CustomTabNightModeStateController + implements Destroyable, NightModeStateProvider, SystemNightModeMonitor.Observer { + private final ObserverList<Observer> mObservers = new ObserverList<>(); + /** * The color scheme requested for the CCT. Only {@link CustomTabsIntent#COLOR_SCHEME_LIGHT} * and {@link CustomTabsIntent#COLOR_SCHEME_DARK} should be considered - fall back to the * system status for {@link CustomTabsIntent#COLOR_SCHEME_SYSTEM} when enabled. */ private int mRequestedColorScheme; + private AppCompatDelegate mAppCompatDelegate; + + /** + * @param lifecycleDispatcher The {@link ActivityLifecycleDispatcher} that will notify this + * class about lifecycle changes. + */ + CustomTabNightModeStateController(ActivityLifecycleDispatcher lifecycleDispatcher) { + lifecycleDispatcher.register(this); + } /** * Initializes the initial night mode state. @@ -38,19 +54,22 @@ mRequestedColorScheme = IntentUtils.safeGetIntExtra( intent, CustomTabsIntent.EXTRA_COLOR_SCHEME, CustomTabsIntent.COLOR_SCHEME_SYSTEM); + mAppCompatDelegate = delegate; - switch (mRequestedColorScheme) { - case CustomTabsIntent.COLOR_SCHEME_LIGHT: - delegate.setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO); - break; - case CustomTabsIntent.COLOR_SCHEME_DARK: - delegate.setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES); - break; - default: - break; + updateNightMode(); + + // No need to observe system night mode if the intent specifies a light/dark color scheme. + if (mRequestedColorScheme == CustomTabsIntent.COLOR_SCHEME_SYSTEM) { + SystemNightModeMonitor.getInstance().addObserver(this); } } + // Destroyable implementation. + @Override + public void destroy() { + SystemNightModeMonitor.getInstance().removeObserver(this); + } + // NightModeStateProvider implementation. @Override public boolean isInNightMode() { @@ -60,16 +79,19 @@ case CustomTabsIntent.COLOR_SCHEME_DARK: return true; default: - // TODO(peter): Adhere to system status. - return false; + return SystemNightModeMonitor.getInstance().isSystemNightModeOn(); } } @Override - public void addObserver(@NonNull Observer observer) {} + public void addObserver(@NonNull Observer observer) { + mObservers.addObserver(observer); + } @Override - public void removeObserver(@NonNull Observer observer) {} + public void removeObserver(@NonNull Observer observer) { + mObservers.removeObserver(observer); + } @Override public boolean shouldOverrideConfiguration() { @@ -77,4 +99,20 @@ // during CustomTabActivity#onCreate(). return false; } + + // SystemNightModeMonitor.Observer implementation. + @Override + public void onSystemNightModeChanged() { + updateNightMode(); + // We need to notify observers on system night mode change so that activities can be + // restarted as needed (we do not handle color scheme changes during runtime). No need to + // check for color scheme because we don't observe system night mode for light/dark color + // scheme. + for (Observer observer : mObservers) observer.onNightModeStateChanged(); + } + + private void updateNightMode() { + mAppCompatDelegate.setLocalNightMode(isInNightMode() ? AppCompatDelegate.MODE_NIGHT_YES + : AppCompatDelegate.MODE_NIGHT_NO); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java index 208c146..4c5cdfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -235,14 +235,15 @@ /** * Initializes the adapter. + * @param context The {@link Context} used for inflating views. * @param provider The {@link BackendProvider} that provides classes needed by the adapter. * @param uiConfig The UiConfig used to observe display style changes. */ - public void initialize(BackendProvider provider, @Nullable UiConfig uiConfig) { + public void initialize(Context context, BackendProvider provider, @Nullable UiConfig uiConfig) { mBackendProvider = provider; mUiConfig = uiConfig; - generateHeaderItems(); + generateHeaderItems(context); DownloadItemSelectionDelegate selectionDelegate = (DownloadItemSelectionDelegate) mBackendProvider.getSelectionDelegate(); @@ -414,15 +415,15 @@ /** * Initialize space display view in storage info header and generate header item for it. + * @param context The {@link Context} used for inflating views. */ - private void generateHeaderItems() { - mSpaceDisplay = new SpaceDisplay(null, this); + private void generateHeaderItems(Context context) { + mSpaceDisplay = new SpaceDisplay(context, null, this); View view = mSpaceDisplay.getViewContainer(); registerAdapterDataObserver(mSpaceDisplay); mSpaceDisplayHeaderItem = new HeaderItem(0, view); if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOADS_LOCATION_CHANGE)) { - Context context = ContextUtils.getApplicationContext(); View storageSummaryView = LayoutInflater.from(context).inflate(R.layout.download_storage_summary, null); mStorageSummaryProvider =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index 27433f3..dfae14ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -245,7 +245,7 @@ } mSelectableListLayout.configureWideDisplayStyle(); - mHistoryAdapter.initialize(mBackendProvider, mSelectableListLayout.getUiConfig()); + mHistoryAdapter.initialize(activity, mBackendProvider, mSelectableListLayout.getUiConfig()); mUndoDeletionSnackbarController = new UndoDeletionSnackbarController(); enableStorageInfoHeader(mHistoryAdapter.shouldShowStorageInfoHeader());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java index 2e7122d..a1c4f6d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
@@ -15,7 +15,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; -import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; @@ -115,10 +114,10 @@ private long mFreeBytes; private long mFileSystemBytes; - SpaceDisplay(final ViewGroup parent, DownloadHistoryAdapter historyAdapter) { + SpaceDisplay(Context context, final ViewGroup parent, DownloadHistoryAdapter historyAdapter) { mHistoryAdapter = historyAdapter; - mViewContainer = LayoutInflater.from(ContextUtils.getApplicationContext()) - .inflate(R.layout.download_manager_ui_space_widget, parent, false); + mViewContainer = LayoutInflater.from(context).inflate( + R.layout.download_manager_ui_space_widget, parent, false); mView = mViewContainer.findViewById(R.id.space_widget_content); mSpaceUsedByDownloadsTextView = (TextView) mView.findViewById(R.id.size_downloaded); mSpaceFreeAndOtherAppsTextView =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogView.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogView.java index c32c12a..009c3e5e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogView.java
@@ -6,8 +6,10 @@ import android.content.Context; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.TextUtils; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; @@ -15,16 +17,21 @@ import android.widget.TextView; import org.chromium.base.Callback; +import org.chromium.base.Log; import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.BoundedLinearLayout; import org.chromium.chrome.browser.widget.FadingEdgeScrollView; import org.chromium.ui.UiUtils; import org.chromium.ui.modaldialog.ModalDialogProperties; +import java.lang.reflect.Field; + /** * Generic dialog view for app modal or tab modal alert dialogs. */ public class ModalDialogView extends BoundedLinearLayout implements View.OnClickListener { + private static final String TAG = "ModalDialogView"; + private ModalDialogProperties.Controller mController; private FadingEdgeScrollView mScrollView; @@ -38,6 +45,7 @@ private Button mNegativeButton; private Callback<Integer> mOnButtonClickedCallback; private boolean mTitleScrollable; + private boolean mFilterTouchForSecurity; /** * Constructor for inflating from XML. @@ -157,6 +165,45 @@ mCustomViewContainer.setLayoutParams(layoutParams); } + /** + * @param filterTouchForSecurity Whether button touch events should be filtered when buttons are + * obscured by another visible window. + */ + void setFilterTouchForSecurity(boolean filterTouchForSecurity) { + if (mFilterTouchForSecurity == filterTouchForSecurity) return; + + mFilterTouchForSecurity = filterTouchForSecurity; + if (filterTouchForSecurity) { + setupFilterTouchForSecurity(); + } else { + assert false : "Shouldn't remove touch filter after setting it up"; + } + } + + /** Setup touch filters to block events when buttons are obscured by another window. */ + private void setupFilterTouchForSecurity() { + Button positiveButton = getButton(ModalDialogProperties.ButtonType.POSITIVE); + Button negativeButton = getButton(ModalDialogProperties.ButtonType.NEGATIVE); + View.OnTouchListener onTouchListener = (View v, MotionEvent ev) -> { + // Filter touch events based MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED which is + // introduced on M+. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false; + + try { + Field field = MotionEvent.class.getField("FLAG_WINDOW_IS_PARTIALLY_OBSCURED"); + if ((ev.getFlags() & field.getInt(null)) != 0) return true; + } catch (NoSuchFieldException | IllegalAccessException e) { + Log.e(TAG, "Reflection failure: " + e); + } + return false; + }; + + positiveButton.setFilterTouchesWhenObscured(true); + positiveButton.setOnTouchListener(onTouchListener); + negativeButton.setFilterTouchesWhenObscured(true); + negativeButton.setOnTouchListener(onTouchListener); + } + /** @param message The message in the dialog content. */ void setMessage(String message) { mMessageView.setText(message);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewBinder.java index f2439a7..2a6a140e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewBinder.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.modaldialog; +import android.text.TextUtils; + import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -27,12 +29,14 @@ } else if (ModalDialogProperties.CUSTOM_VIEW == propertyKey) { view.setCustomView(model.get(ModalDialogProperties.CUSTOM_VIEW)); } else if (ModalDialogProperties.POSITIVE_BUTTON_TEXT == propertyKey) { + assert checkFilterTouchConsistency(model); view.setButtonText(ModalDialogProperties.ButtonType.POSITIVE, model.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT)); } else if (ModalDialogProperties.POSITIVE_BUTTON_DISABLED == propertyKey) { view.setButtonEnabled(ModalDialogProperties.ButtonType.POSITIVE, !model.get(ModalDialogProperties.POSITIVE_BUTTON_DISABLED)); } else if (ModalDialogProperties.NEGATIVE_BUTTON_TEXT == propertyKey) { + assert checkFilterTouchConsistency(model); view.setButtonText(ModalDialogProperties.ButtonType.NEGATIVE, model.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT)); } else if (ModalDialogProperties.NEGATIVE_BUTTON_DISABLED == propertyKey) { @@ -46,10 +50,26 @@ }); } else if (ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE == propertyKey) { // Intentionally left empty since this is a property for the dialog container. + } else if (ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY == propertyKey) { + assert checkFilterTouchConsistency(model); + view.setFilterTouchForSecurity( + model.get(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY)); } else if (ModalDialogProperties.CONTENT_DESCRIPTION == propertyKey) { // Intentionally left empty since this is a property used for the dialog container. } else { assert false : "Unhandled property detected in ModalDialogViewBinder!"; } } + + /** + * Checks if FILTER_TOUCH_FOR_SECURITY flag is consistent with the set of enabled buttons. + * Touch event filtering in ModalDialogView is only applied to standard buttons. When buttons + * are hidden, filtering touch events doesn't have effect. + * @return false if security sensitive dialog doesn't have standard buttons. + */ + static boolean checkFilterTouchConsistency(PropertyModel model) { + return !model.get(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY) + || !TextUtils.isEmpty(model.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT)) + || !TextUtils.isEmpty(model.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT)); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java index 77afe38..6380b2e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java
@@ -29,8 +29,9 @@ /** * Maintains and provides the night mode state for the entire application. */ -public class GlobalNightModeStateController - implements NightModeStateProvider, ApplicationStatus.ApplicationStateListener { +public class GlobalNightModeStateController implements NightModeStateProvider, + SystemNightModeMonitor.Observer, + ApplicationStatus.ApplicationStateListener { private static GlobalNightModeStateController sInstance; private final ObserverList<Observer> mObservers = new ObserverList<>(); @@ -103,6 +104,12 @@ mObservers.removeObserver(observer); } + // SystemNightModeMonitor.Observer implementation. + @Override + public void onSystemNightModeChanged() { + updateNightMode(); + } + // ApplicationStatus.ApplicationStateListener implementation. @Override public void onApplicationStateChange(int newState) { @@ -123,6 +130,7 @@ ContextUtils.getApplicationContext().registerReceiver(mPowerModeReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); } + SystemNightModeMonitor.getInstance().addObserver(this); ChromePreferenceManager.getInstance().addObserver(mPreferenceObserver); updateNightMode(); } @@ -135,12 +143,14 @@ if (mPowerModeReceiver != null) { ContextUtils.getApplicationContext().unregisterReceiver(mPowerModeReceiver); } + SystemNightModeMonitor.getInstance().removeObserver(this); ChromePreferenceManager.getInstance().removeObserver(mPreferenceObserver); } private void updateNightMode() { - // TODO(huayinz): Listen to system ui mode change. - boolean newMode = mPowerSaveModeOn + // TODO(https://crbug.com/942771): Update logic for real user settings. + final boolean newMode = mPowerSaveModeOn + || SystemNightModeMonitor.getInstance().isSystemNightModeOn() || ChromePreferenceManager.getInstance().readBoolean( NIGHT_MODE_SETTINGS_ENABLED_KEY, false); if (mNightModeOn != null && newMode == mNightModeOn) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java new file mode 100644 index 0000000..f89ec4d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java
@@ -0,0 +1,79 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.night_mode; + +import android.content.res.Configuration; + +import org.chromium.base.ContextUtils; +import org.chromium.base.ObserverList; +import org.chromium.chrome.browser.ChromeApplication; + +/** + * Observes and keeps a record of the system night mode state (i.e. the night mode from + * {@link ChromeApplication}). + */ +public class SystemNightModeMonitor { + private static SystemNightModeMonitor sInstance; + + /** Interface for callback when system night mode is changed. */ + public interface Observer { + /** Called when system night mode is changed. */ + void onSystemNightModeChanged(); + } + + private final ObserverList<Observer> mObservers = new ObserverList<>(); + private boolean mSystemNightModeOn; + + /** + * @return The {@link SystemNightModeMonitor} that observes the system night mode state + * (i.e. the night mode from {@link ChromeApplication}). + */ + public static SystemNightModeMonitor getInstance() { + if (sInstance == null) { + sInstance = new SystemNightModeMonitor(); + } + return sInstance; + } + + private SystemNightModeMonitor() { + calculateSystemNightMode(); + } + + /** @return True if system night mode is on, and false otherwise. */ + public boolean isSystemNightModeOn() { + return mSystemNightModeOn; + } + + /** @param observer The {@link Observer} to be added for observing system night mode changes. */ + public void addObserver(Observer observer) { + mObservers.addObserver(observer); + } + + /** + * @param observer The {@link Observer} to be removed from observing system night mode changes. + */ + public void removeObserver(Observer observer) { + mObservers.removeObserver(observer); + } + + /** + * Updates the system night mode state, and notifies observers if system night mode changes. + */ + public void onApplicationConfigurationChanged() { + final boolean oldNightMode = mSystemNightModeOn; + calculateSystemNightMode(); + + if (oldNightMode != mSystemNightModeOn) { + for (Observer observer : mObservers) observer.onSystemNightModeChanged(); + } + } + + private void calculateSystemNightMode() { + final int uiMode = + ContextUtils.getApplicationContext().getResources().getConfiguration().uiMode; + mSystemNightModeOn = + (uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java index f6e1adb..dd02628 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
@@ -23,50 +23,49 @@ view.setIconBitmap(model.get(AnswerSuggestionViewProperties.ANSWER_IMAGE)); } else if (AnswerSuggestionViewProperties.ANSWER_ICON_TYPE.equals(propertyKey)) { int type = model.get(AnswerSuggestionViewProperties.ANSWER_ICON_TYPE); - if (type == AnswerIcon.UNDEFINED) return; - int drawableId = R.drawable.ic_omnibox_page; - switch (type) { - case AnswerIcon.CALCULATOR: - drawableId = R.drawable.ic_equals_sign_round; - break; - case AnswerIcon.DICTIONARY: - drawableId = R.drawable.ic_book_round; - break; - case AnswerIcon.FINANCE: - drawableId = R.drawable.ic_swap_vert_round; - break; - case AnswerIcon.KNOWLEDGE: - drawableId = R.drawable.ic_google_round; - break; - case AnswerIcon.SUNRISE: - drawableId = R.drawable.ic_wb_sunny_round; - break; - case AnswerIcon.TRANSLATION: - drawableId = R.drawable.logo_translate_round; - break; - case AnswerIcon.WEATHER: - drawableId = R.drawable.logo_partly_cloudy_light; - break; - case AnswerIcon.EVENT: - drawableId = R.drawable.ic_event_round; - break; - case AnswerIcon.CURRENCY: - drawableId = R.drawable.ic_loop_round; - break; - case AnswerIcon.SPORTS: - drawableId = R.drawable.ic_google_round; - break; - default: - assert false : "Invalid answer type: " + type; - break; - } - - view.setFallbackIconRes(drawableId); + view.setFallbackIconRes(getAnswerIcon(type)); } else if (AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT.equals(propertyKey)) { view.setLine1TextContent(model.get(AnswerSuggestionViewProperties.TEXT_LINE_1_TEXT)); } else if (AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT.equals(propertyKey)) { view.setLine2TextContent(model.get(AnswerSuggestionViewProperties.TEXT_LINE_2_TEXT)); } } + + /** + * Convert AnswerIcon type to drawable resource type representing answer icon. + * + * Answers are not shown when user is in incognito mode, so we can rely on + * configuration UI to define colors for light and dark mode that will be used + * by the icons below. + * + * @param type AnswerIcon type to get drawable for. + */ + private static final int getAnswerIcon(@AnswerIcon int type) { + switch (type) { + case AnswerIcon.CALCULATOR: + return R.drawable.ic_equals_sign_round; + case AnswerIcon.DICTIONARY: + return R.drawable.ic_book_round; + case AnswerIcon.FINANCE: + return R.drawable.ic_swap_vert_round; + case AnswerIcon.KNOWLEDGE: + return R.drawable.ic_google_round; + case AnswerIcon.SUNRISE: + return R.drawable.ic_wb_sunny_round; + case AnswerIcon.TRANSLATION: + return R.drawable.logo_translate_round; + case AnswerIcon.WEATHER: + return R.drawable.logo_partly_cloudy; + case AnswerIcon.EVENT: + return R.drawable.ic_event_round; + case AnswerIcon.CURRENCY: + return R.drawable.ic_loop_round; + case AnswerIcon.SPORTS: + return R.drawable.ic_google_round; + default: + assert false : "Invalid answer type: " + type; + return 0; + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java index 8333ba8e0..394a02c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java
@@ -6,6 +6,7 @@ import android.content.Context; import android.graphics.Bitmap; +import android.support.annotation.ColorInt; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.util.AttributeSet; @@ -13,20 +14,31 @@ import android.widget.ImageView; import android.widget.TextView; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.widget.TintedDrawable; /** This class represents a bar to display at the top of the payment request UI. */ public class PaymentRequestHeader extends FrameLayout { + private final @ColorInt int mBackgroundColor; private Context mContext; /** Constructor for when the PaymentRequestHeader is inflated from XML. */ public PaymentRequestHeader(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; + mBackgroundColor = + ApiCompatibilityUtils.getColor(getResources(), R.color.payment_request_bg); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setBackgroundColor(mBackgroundColor); } /** @@ -50,16 +62,18 @@ TextView hostName = (TextView) findViewById(R.id.hostname); Spannable url = new SpannableStringBuilder(origin); + final boolean useDarkColors = + !ColorUtils.shouldUseLightForegroundOnBackground(mBackgroundColor); OmniboxUrlEmphasizer.emphasizeUrl(url, mContext.getResources(), Profile.getLastUsedProfile(), securityLevel, false /* isInternalPage */, - true /* useDarkColors */, true /* emphasizeHttpsScheme */); + useDarkColors, true /* emphasizeHttpsScheme */); hostName.setText(url); if (origin.startsWith(UrlConstants.HTTPS_URL_PREFIX)) { // Add a lock icon. hostName.setCompoundDrawablesRelativeWithIntrinsicBounds( TintedDrawable.constructTintedDrawable( - mContext, R.drawable.omnibox_https_valid, R.color.google_green_700), + mContext, R.drawable.omnibox_https_valid, R.color.default_green), null, null, null); // Remove left padding to align left compound drawable with the title. Note that the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java index d8fa461..b8dd9c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -6,9 +6,9 @@ import android.content.Context; import android.content.res.Resources; -import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Handler; +import android.support.annotation.ColorInt; import android.support.annotation.Nullable; import android.support.v4.view.MarginLayoutParamsCompat; import android.support.v4.view.animation.LinearOutSlowInInterpolator; @@ -39,6 +39,7 @@ import org.chromium.chrome.browser.widget.DualControlLayout; import org.chromium.chrome.browser.widget.TintedDrawable; import org.chromium.chrome.browser.widget.prefeditor.EditableOption; +import org.chromium.ui.HorizontalListDividerDrawable; import org.chromium.ui.UiUtils; import java.util.ArrayList; @@ -136,6 +137,7 @@ protected int mDisplayMode = DISPLAY_MODE_NORMAL; private final int mVerticalSpacing; + private final @ColorInt int mUnfocusedBackgroundColor; private final int mFocusedBackgroundColor; private final LinearLayout mMainSection; private final ImageView mLogoView; @@ -164,6 +166,8 @@ setGravity(Gravity.CENTER_VERTICAL); // Set the styling of the view. + mUnfocusedBackgroundColor = + ApiCompatibilityUtils.getColor(getResources(), R.color.payment_request_bg); mFocusedBackgroundColor = ApiCompatibilityUtils.getColor( getResources(), R.color.payments_section_edit_background); mLargeSpacing = @@ -454,7 +458,7 @@ boolean isExpanded = mDisplayMode == DISPLAY_MODE_FOCUSED || mDisplayMode == DISPLAY_MODE_CHECKING; - setBackgroundColor(isExpanded ? mFocusedBackgroundColor : Color.WHITE); + setBackgroundColor(isExpanded ? mFocusedBackgroundColor : mUnfocusedBackgroundColor); // Update whether the logo is displayed. if (mLogoView != null) { @@ -1502,8 +1506,7 @@ public SectionSeparator(ViewGroup parent, int index) { super(parent.getContext()); Resources resources = parent.getContext().getResources(); - setBackgroundColor(ApiCompatibilityUtils.getColor( - resources, R.color.payments_section_separator)); + setBackground(HorizontalListDividerDrawable.create(getContext())); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, resources.getDimensionPixelSize(R.dimen.separator_height));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionAppModalDialogView.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionAppModalDialogView.java index f312877..80e104d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionAppModalDialogView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionAppModalDialogView.java
@@ -44,6 +44,7 @@ .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, delegate.getSecondaryButtonText()) .with(ModalDialogProperties.CONTENT_DESCRIPTION, delegate.getMessageText()) + .with(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY, true) .build(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index dd3e9a575..61a1a38e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -273,8 +273,10 @@ } boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity); - mScrimParams.backgroundColor = - !isTablet && !mLocationBarModel.isIncognito() ? mLightScrimColor : null; + mScrimParams.backgroundColor = !isTablet && !mLocationBarModel.isIncognito() + && !mActivity.getNightModeStateProvider().isInNightMode() + ? mLightScrimColor + : null; if (hasFocus && !showScrimAfterAnimationCompletes()) { mActivity.getScrim().showScrim(mScrimParams);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index d6b81bcf..1dcc63e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -476,6 +476,7 @@ if (storage != null) { mDisclosureSnackbarController.maybeShowDisclosure(this, storage, false /* force */); } + AppHooks.get().setDisplayModeForActivity(mWebappInfo.displayMode(), this); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webauth/Fido2ApiHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/webauth/Fido2ApiHandler.java index 019afb8..2a6670f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webauth/Fido2ApiHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webauth/Fido2ApiHandler.java
@@ -15,7 +15,7 @@ /** * Android implementation of the Authenticator service defined in - * //third_party/blink/public/platform/modules/webauth/authenticator.mojom. + * //third_party/blink/public/mojom/webauth/authenticator.mojom. */ public class Fido2ApiHandler { private static Fido2ApiHandler sInstance;
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index f743dbf..71777725 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3686,15 +3686,6 @@ <message name="IDS_TWA_RUNNING_IN_CHROME" desc="Message on a snackbar indicating that the current Activity may use Chrome data (the rest of the app may not be)."> Running in Chrome </message> - <message name="IDS_YOU_HAVE_UNINSTALLED_APP" desc="Notification title saying the user has uninstalled the given app."> - You have uninstalled <ph name="APP_NAME">%1$s<ex>YouTube</ex></ph>. - </message> - <message name="IDS_YOU_HAVE_CLEARED_APP" desc="Notification title saying the user has cleared data for the given app."> - You have cleared data for <ph name="APP_NAME">%1$s<ex>YouTube</ex></ph>. - </message> - <message name="IDS_CLEAR_RELATED_DATA" desc="Notification text asking if the user wants to clear data for the given url as they have just uninstalled/cleared an app linked to that URL."> - Would you like to clear data for <ph name="URL">%1$s<ex>youtube.com</ex></ph>? - </message> <message name="IDS_TWA_CLEAR_DATA_DIALOG_TITLE" desc="Title of the clear data dialog showing after user uninstalls or clears data of an app hosting a Trusted Web Activity"> <ph name="APP_NAME">%1$s<ex>YouTube</ex></ph> also has data in Chrome </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 0c82c0b..a953c30a 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -192,11 +192,8 @@ "java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java", "java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java", "java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java", - "java/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisher.java", - "java/src/org/chromium/chrome/browser/browserservices/ClearDataService.java", "java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java", "java/src/org/chromium/chrome/browser/browserservices/ClientAppDataRegister.java", - "java/src/org/chromium/chrome/browser/browserservices/DomainDataCleaner.java", "java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java", "java/src/org/chromium/chrome/browser/browserservices/Origin.java", "java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java", @@ -938,6 +935,7 @@ "java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java", "java/src/org/chromium/chrome/browser/night_mode/NightModeStateProvider.java", "java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java", + "java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java", "java/src/org/chromium/chrome/browser/notifications/ActionInfo.java", "java/src/org/chromium/chrome/browser/notifications/ChromeNotification.java", "java/src/org/chromium/chrome/browser/notifications/ChromeNotificationBuilder.java", @@ -2405,11 +2403,8 @@ "junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java", "junit/src/org/chromium/chrome/browser/browseractions/BrowserActionsIntentTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java", - "junit/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisherTest.java", - "junit/src/org/chromium/chrome/browser/browserservices/ClearDataServiceTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java", "junit/src/org/chromium/chrome/browser/browserservices/ClientAppDataRegisterTest.java", - "junit/src/org/chromium/chrome/browser/browserservices/DomainDataCleanerTest.java", "junit/src/org/chromium/chrome/browser/browserservices/OriginTest.java", "junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java", "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/ClientAppDataRecorderTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackgroundServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackgroundServiceTest.java index c412172..2318de51 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackgroundServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeBackgroundServiceTest.java
@@ -16,12 +16,13 @@ import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ntp.snippets.SnippetsLauncher; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.UiThreadTaskTraits; /** * Tests {@link ChromeBackgroundService}. @@ -65,7 +66,7 @@ protected void checkExpectations(final boolean expectedLaunchBrowser, final boolean expectedDidCallOnPersistentSchedulerWakeUp, final boolean expectedDidCallOnBrowserUpgraded) { - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertEquals("StartedService", expectedLaunchBrowser, mDidLaunchBrowser); Assert.assertEquals("OnPersistentSchedulerWakeUp", expectedDidCallOnPersistentSchedulerWakeUp,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java index 8213a8b..2fcb67a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
@@ -14,7 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -29,6 +29,7 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.ViewEventSink; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; @@ -115,7 +116,7 @@ addFocusChangedListener(view); final EdgeSwipeHandler edgeSwipeHandler = mActivityTestRule.getActivity().getLayoutManager().getToolbarSwipeHandler(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { edgeSwipeHandler.swipeStarted(ScrollDirection.RIGHT, 0, 0); edgeSwipeHandler.swipeUpdated(100, 0, 100, 0, 100, 0); }); @@ -134,7 +135,7 @@ Assert.assertFalse("Content view didn't lose focus", blockForFocusChanged()); // End the drag - ThreadUtils.runOnUiThread(() -> edgeSwipeHandler.swipeFinished()); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> edgeSwipeHandler.swipeFinished()); CriteriaHelper.pollUiThread( new Criteria("Layout not requesting Tab Android view be attached") { @@ -217,11 +218,11 @@ onTitleUpdatedHelper.waitForCallback(callCount); Assert.assertEquals("initial", mTitle); callCount = onTitleUpdatedHelper.getCallCount(); - ThreadUtils.runOnUiThread(() -> eventSink.onPauseForTesting()); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> eventSink.onPauseForTesting()); onTitleUpdatedHelper.waitForCallback(callCount); Assert.assertEquals("blurred", mTitle); callCount = onTitleUpdatedHelper.getCallCount(); - ThreadUtils.runOnUiThread(() -> eventSink.onResumeForTesting()); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> eventSink.onResumeForTesting()); onTitleUpdatedHelper.waitForCallback(callCount); Assert.assertEquals("focused", mTitle); mActivityTestRule.getWebContents().removeObserver(observer);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java b/chrome/android/javatests/src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java index 91d09d05..2623185 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java
@@ -8,10 +8,11 @@ import org.json.JSONException; import org.json.JSONObject; -import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.UsedByReflection; +import org.chromium.base.task.PostTask; import org.chromium.components.safe_browsing.SafeBrowsingApiHandler; import org.chromium.components.safe_browsing.SafeBrowsingApiHandler.Observer; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.HashMap; import java.util.Map; @@ -55,7 +56,7 @@ public void startUriLookup(final long callbackId, String uri, int[] threatsOfInterest) { final String metadata = getMetadata(uri, threatsOfInterest); // clang-format off - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, (Runnable) () -> mObserver.onUrlCheckDone( callbackId, SafeBrowsingResult.SUCCESS, metadata, DEFAULT_CHECK_DELTA_US)); // clang-format on
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java index 8da82522..f21beceb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java
@@ -15,7 +15,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; @@ -27,6 +27,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.safe_browsing.SafeBrowsingApiBridge; +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.content_public.browser.test.util.DOMUtils; @@ -68,7 +69,8 @@ new MockSafeBrowsingApiHandler().getClass()); mActivityTestRule.startMainActivityOnBlankPage(); - ThreadUtils.runOnUiThread(() -> Assert.assertTrue(getNumInfobarsShowing() == 0)); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> Assert.assertTrue(getNumInfobarsShowing() == 0)); mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); mPopupHtmlUrl = mTestServer.getURL(POPUP_HTML_PATH);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index b4fb256..d8f66e45 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -31,6 +31,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; @@ -75,6 +76,7 @@ import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher; import org.chromium.content_public.browser.SelectionPopupController; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.browser.test.util.Criteria; @@ -1685,7 +1687,7 @@ mActivityTestRule.getKeyboardDelegate().isKeyboardShowing( mActivityTestRule.getActivity(), urlBar)); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { edgeSwipeHandler.swipeStarted(ScrollDirection.RIGHT, 0, 0); float swipeXChange = mTabsViewWidthDp / 2.f; edgeSwipeHandler.swipeUpdated( @@ -1701,7 +1703,7 @@ } }); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertFalse("Keyboard should be hidden while swiping", mActivityTestRule.getKeyboardDelegate().isKeyboardShowing( mActivityTestRule.getActivity(), urlBar));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java index 3b10124..de17c67 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java
@@ -19,12 +19,14 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.MetricsUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.browser.test.util.Criteria; @@ -74,7 +76,7 @@ final AtomicBoolean isRenderViewReady = new AtomicBoolean(); final AtomicReference<WebContents> webContentsReference = new AtomicReference<>(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mWarmupManager.createSpareWebContents(!WarmupManager.FOR_CCT); Assert.assertTrue(mWarmupManager.hasSpareWebContents()); WebContents webContents = @@ -99,7 +101,8 @@ return isRenderViewReady.get(); } }); - ThreadUtils.runOnUiThread(() -> webContentsReference.get().destroy()); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> webContentsReference.get().destroy()); } /** Tests that taking a spare WebContents makes it unavailable to subsequent callers. */ @@ -226,8 +229,10 @@ server.start(); final String url = server.getURL("/hello_world.html"); - ThreadUtils.runOnUiThread(() -> mWarmupManager.maybePreconnectUrlAndSubResources( - Profile.getLastUsedProfile(), url)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> mWarmupManager.maybePreconnectUrlAndSubResources( + Profile.getLastUsedProfile(), url)); if (!connectionsSemaphore.tryAcquire(5, TimeUnit.SECONDS)) { // Starts at -1. int actualConnections = connectionsSemaphore.availablePermits() + 1;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java index 8bb3b027..2ae29893 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -19,7 +19,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -31,6 +31,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeTabUtils; +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; @@ -86,7 +87,8 @@ showAppMenuAndAssertMenuShown(); mAppMenu = mActivityTestRule.getActivity().getAppMenuHandler().getAppMenu(); - ThreadUtils.runOnUiThread(() -> mAppMenu.getListView().setSelection(0)); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mAppMenu.getListView().setSelection(0)); CriteriaHelper.pollInstrumentationThread(Criteria.equals(0, () -> getCurrentFocusedRow())); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @@ -212,7 +214,8 @@ } private void showAppMenuAndAssertMenuShown() { - ThreadUtils.runOnUiThread((Runnable) () -> mAppMenuHandler.showAppMenu(null, false, false)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + (Runnable) () -> mAppMenuHandler.showAppMenu(null, false, false)); CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not show") { @Override public boolean isSatisfied() { @@ -256,7 +259,7 @@ private void pressKey(final int keycode) { final View view = mAppMenu.getListView(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode)); view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode)); });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java index 70e2a84..95ff027 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java
@@ -36,6 +36,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.R; @@ -52,6 +53,7 @@ import org.chromium.chrome.test.util.InfoBarTestAnimationListener; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.ui.DropdownPopupWindowInterface; import org.chromium.ui.test.util.UiRestriction; @@ -356,7 +358,7 @@ InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener(); mActivityTestRule.getInfoBarContainer().addAnimationListener(listener); final String kInfoBarText = "SomeInfoBar"; - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(), InfoBarIdentifier.DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE_ANDROID, kInfoBarText, false); @@ -396,7 +398,7 @@ InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener(); mActivityTestRule.getInfoBarContainer().addAnimationListener(listener); final String kInfoBarText = "SomeInfoBar"; - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(), InfoBarIdentifier.DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE_ANDROID, kInfoBarText, false); @@ -440,7 +442,7 @@ // Create a simple, persistent snackbar and verify it's displayed. SnackbarManager manager = mActivityTestRule.getActivity().getSnackbarManager(); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> manager.showSnackbar(Snackbar.make(kSnackbarText, new SnackbarManager.SnackbarController() {}, @@ -476,7 +478,7 @@ InfoBarTestAnimationListener listener = new InfoBarTestAnimationListener(); mActivityTestRule.getInfoBarContainer().addAnimationListener(listener); final String kInfoBarText = "SomeInfoBar"; - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(), InfoBarIdentifier.DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE_ANDROID, kInfoBarText, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingTestHelper.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingTestHelper.java index 342d30b2..5abe6ee 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingTestHelper.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingTestHelper.java
@@ -36,6 +36,7 @@ import org.junit.Assert; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ChromeWindow; @@ -46,6 +47,7 @@ import org.chromium.components.autofill.AutofillDelegate; import org.chromium.components.autofill.AutofillSuggestion; import org.chromium.content_public.browser.ImeAdapter; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -322,7 +324,8 @@ .withCause(new Throwable("No tab at index " + tabIndex)) .build(); } - ThreadUtils.runOnUiThread(() -> tabLayout.getTabAt(tabIndex).select()); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> tabLayout.getTabAt(tabIndex).select()); } }; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 14e9aa30..b70e179 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -35,6 +35,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; @@ -62,6 +63,7 @@ import org.chromium.chrome.test.util.browser.TabLoadObserver; import org.chromium.chrome.test.util.browser.TabTitleObserver; import org.chromium.chrome.test.util.browser.WebappTestPage; +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.content_public.browser.test.util.TouchCommon; @@ -136,7 +138,8 @@ mAppData = new AppData(url, packageName); mAppData.setPackageInfo(NATIVE_APP_TITLE, mTestServer.getURL(NATIVE_ICON_PATH), 4.5f, NATIVE_APP_INSTALL_TEXT, null, mInstallIntent); - ThreadUtils.runOnUiThread(() -> { mObserver.onAppDetailsRetrieved(mAppData); }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { mObserver.onAppDetailsRetrieved(mAppData); }); } @Override @@ -923,7 +926,7 @@ triggerWebAppBanner(mTabbedActivityTestRule, webBannerUrl, WEB_APP_TITLE, false); // Verify metrics calling in the successful case. - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { AppBannerManager manager = getAppBannerManager(mTabbedActivityTestRule.getActivity().getActivityTab()); manager.recordMenuItemAddToHomescreen(); @@ -1053,7 +1056,7 @@ mTabbedActivityTestRule.getActivity().getActivityTab(), "Got userChoice: accepted") .waitForTitleUpdate(3); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "Webapp.Install.InstallEvent", 4)); @@ -1077,7 +1080,7 @@ "Got userChoice: accepted") .waitForTitleUpdate(3); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( "Webapp.Install.InstallEvent", 5));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java index 4a5748b..7c6953e5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -27,11 +27,13 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.R; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.StandardNotificationBuilder; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.concurrent.TimeoutException; @@ -175,7 +177,7 @@ private void postNotification() throws TimeoutException, InterruptedException { - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mClient.notifyNotification(SCOPE, NOTIFICATION_TAG, NOTIFICATION_ID, mBuilder); }); @@ -189,8 +191,8 @@ @Test @SmallTest public void testCancelNotification() throws TimeoutException, InterruptedException { - ThreadUtils.runOnUiThread(() -> - mClient.cancelNotification(SCOPE, NOTIFICATION_TAG, NOTIFICATION_ID)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> mClient.cancelNotification(SCOPE, NOTIFICATION_TAG, NOTIFICATION_ID)); mResponseHandler.mCancelNotification.waitForCallback();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 09537a6..93407f8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -37,6 +37,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; @@ -82,6 +83,7 @@ import org.chromium.components.navigation_interception.NavigationParams; import org.chromium.content_public.browser.SelectionClient; import org.chromium.content_public.browser.SelectionPopupController; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -1541,11 +1543,10 @@ @Test @SmallTest @Feature({"ContextualSearch"}) - @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.M, - message = "Flaky except on M+ Phones. See https://crbug.com/837998") + @DisabledTest(message = "See https://crbug.com/837998") @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) - public void - testLongPressGestureFollowedByTapDoesntSelect() throws InterruptedException, TimeoutException { + public void testLongPressGestureFollowedByTapDoesntSelect() + throws InterruptedException, TimeoutException { longPressNode("intelligence"); waitForPanelToPeek(); clickWordNode("states-far"); @@ -1566,12 +1567,9 @@ Assert.assertEquals("States", getSelectedText()); waitForPanelToPeek(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - ChromeTabUtils.simulateRendererKilledForTesting( - mActivityTestRule.getActivity().getActivityTab(), true); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + ChromeTabUtils.simulateRendererKilledForTesting( + mActivityTestRule.getActivity().getActivityTab(), true); }); // Give the panelState time to change @@ -1601,11 +1599,8 @@ TabModelUtils.getCurrentTab(mActivityTestRule.getActivity().getCurrentTabModel()); // TODO(donnd): consider using runOnUiThreadBlocking, won't need to waitForIdleSync? - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabModelUtils.setIndex(mActivityTestRule.getActivity().getCurrentTabModel(), 0); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + TabModelUtils.setIndex(mActivityTestRule.getActivity().getCurrentTabModel(), 0); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); @@ -1613,12 +1608,8 @@ Assert.assertEquals("States", getSelectedText()); waitForPanelToPeek(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - ChromeTabUtils.simulateRendererKilledForTesting(tab2, false); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { ChromeTabUtils.simulateRendererKilledForTesting(tab2, false); }); waitForPanelToPeek(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 567680b..0f49805d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -724,7 +724,7 @@ getActivity().getIntentDataProvider().setPendingIntentOnFinishedForTesting(onFinished); openAppMenuAndAssertMenuShown(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { MenuItem item = getActivity().getAppMenuPropertiesDelegate().getMenuItemForTitle( TEST_MENU_TITLE); Assert.assertNotNull(item); @@ -774,7 +774,7 @@ InstrumentationRegistry.getInstrumentation().addMonitor(filter, null, false); openAppMenuAndAssertMenuShown(); final String menuItemTitle = getActivity().getString(R.string.menu_open_in_product_default); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { MenuItem item = getActivity().getAppMenuHandler().getAppMenu().getMenu().findItem( R.id.open_in_browser_id); Assert.assertNotNull(item); @@ -2275,7 +2275,7 @@ }; ApplicationStatus.registerStateListenerForAllActivities(listener); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { cctActivity.getActivityTab().getTabWebContentsDelegateAndroid().openNewTab( "about:blank", null, null, WindowOpenDisposition.OFF_THE_RECORD, false); });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java index d7f1615..d90d720 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
@@ -24,6 +24,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApplicationStatus; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; @@ -36,6 +37,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabDelegateFactory; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +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.net.test.EmbeddedTestServer; @@ -200,12 +202,8 @@ } private void showAppMenuAndAssertMenuShown(final AppMenuHandler appMenuHandler) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - appMenuHandler.showAppMenu(null, false, false); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { appMenuHandler.showAppMenu(null, false, false); }); CriteriaHelper.pollUiThread(new Criteria("AppMenu did not show") { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java index a1cb968..ec38be8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -21,9 +21,11 @@ import org.junit.Assert; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.R; import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.CriteriaHelper; import java.util.concurrent.TimeoutException; @@ -115,7 +117,7 @@ } public static void openAppMenuAndAssertMenuShown(CustomTabActivity activity) { - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { activity.onMenuOrKeyboardAction(R.id.show_menu, false); }); CriteriaHelper.pollUiThread(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java index 8dc1e28b..3efd2397 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
@@ -26,6 +26,7 @@ import org.chromium.base.PathUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.MetricsUtils.HistogramDelta; import org.chromium.chrome.browser.ChromeFeatureList; @@ -39,6 +40,7 @@ import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.safe_browsing.SafeBrowsingApiBridge; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.JavaScriptUtils; @@ -229,7 +231,7 @@ CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback); CustomTabsTestUtils.warmUpAndWait(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertEquals(status, mConnection.handleParallelRequest( session, prepareIntent(url, Uri.parse("http://not-the-right-origin")))); @@ -256,7 +258,7 @@ Math.abs(NetError.ERR_EMPTY_RESPONSE)); CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mConnection.onHandledIntent(session, prepareIntent(url, ORIGIN))); CustomTabsTestUtils.warmUpAndWait(); customTabsCallback.waitForRequest(); @@ -282,7 +284,7 @@ List<Uri> urls = Arrays.asList(Uri.parse(mServer.getURL("/echo-raw?a=1")), Uri.parse(mServer.getURL("/echo-raw?a=2")), Uri.parse(mServer.getURL("/echo-raw?a=3"))); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Assert.assertEquals(urls.size(), mConnection.maybePrefetchResources( session, prepareIntentForResourcePrefetch(urls, ORIGIN))); @@ -416,7 +418,7 @@ CustomTabsSessionToken session = prepareSession(ORIGIN, customTabsCallback); if (afterNative) CustomTabsTestUtils.warmUpAndWait(); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mConnection.onHandledIntent(session, prepareIntent(url, ORIGIN))); if (!afterNative) CustomTabsTestUtils.warmUpAndWait();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java index 500a19f..a7e74f93 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java
@@ -329,7 +329,7 @@ // Wait until the offline page model has been loaded. CallbackHelper callback = new CallbackHelper(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { if (offlinePageBridge.isOfflinePageModelLoaded()) { callback.notifyCalled(); return; @@ -345,7 +345,7 @@ callback.waitForCallback(0); CallbackHelper callback2 = new CallbackHelper(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { CustomTabActivity customTabActivity = mCustomTabActivityTestRule.getActivity(); Tab tab = customTabActivity.getActivityTab(); String pageUrl = tab.getUrl();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java index ea18c671..b8c5581 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java
@@ -40,6 +40,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.FlakyTest; @@ -66,6 +67,7 @@ import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.offline_items_collection.OfflineItem; +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.ui.test.util.UiRestriction; @@ -180,7 +182,8 @@ int callCount = mAdapterObserver.onChangedCallback.getCallCount(); int spaceDisplayCallCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final DownloadItem updateItem = StubbedProvider.createDownloadItem(7, "20151021 07:28"); - ThreadUtils.runOnUiThread(() -> mAdapter.onDownloadItemCreated(updateItem)); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mAdapter.onDownloadItemCreated(updateItem)); mAdapterObserver.onChangedCallback.waitForCallback(callCount, 2); mAdapterObserver.onSpaceDisplayUpdatedCallback.waitForCallback(spaceDisplayCallCount); // Use Criteria here because the text for SpaceDisplay is updated through an AsyncTask. @@ -191,7 +194,8 @@ spaceDisplayCallCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final DownloadItem deletedItem = StubbedProvider.createDownloadItem(6, "20151021 07:28"); deletedItem.setHasBeenExternallyRemoved(true); - ThreadUtils.runOnUiThread(() -> mAdapter.onDownloadItemUpdated(deletedItem)); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mAdapter.onDownloadItemUpdated(deletedItem)); mAdapterObserver.onChangedCallback.waitForCallback(callCount, 2); mAdapterObserver.onSpaceDisplayUpdatedCallback.waitForCallback(spaceDisplayCallCount); onView(withText("5.50 GB downloaded")).check(matches(isDisplayed())); @@ -200,7 +204,7 @@ callCount = mAdapterObserver.onChangedCallback.getCallCount(); spaceDisplayCallCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final OfflineItem deletedPage = StubbedProvider.createOfflineItem(3, "20151021 07:28"); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mStubbedProvider.getOfflineContentProvider().observer.onItemRemoved( deletedPage.id)); @@ -273,7 +277,7 @@ Assert.assertEquals( 0, mStubbedProvider.getOfflineContentProvider().deleteItemCallback.getCallCount()); int callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> Assert.assertTrue( mUi.getDownloadManagerToolbarForTests() @@ -344,7 +348,7 @@ int callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final DownloadItem item7 = StubbedProvider.createDownloadItem(7, "20161021 07:28"); final DownloadItem item8 = StubbedProvider.createDownloadItem(8, "20161021 17:28"); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mAdapter.onDownloadItemCreated(item7); mAdapter.onDownloadItemCreated(item8); }); @@ -367,7 +371,7 @@ // Click the delete button. callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> Assert.assertTrue( mUi.getDownloadManagerToolbarForTests() @@ -385,7 +389,7 @@ callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final View rootView = mUi.getView().getRootView(); Assert.assertNotNull(rootView.findViewById(R.id.snackbar)); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, (Runnable) () -> rootView.findViewById(R.id.snackbar_button).callOnClick()); mAdapterObserver.onSpaceDisplayUpdatedCallback.waitForCallback(callCount); @@ -420,7 +424,7 @@ int callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final DownloadItem item7 = StubbedProvider.createDownloadItem(7, "20161021 07:28"); final DownloadItem item8 = StubbedProvider.createDownloadItem(8, "20161021 17:28"); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mAdapter.onDownloadItemCreated(item7); mAdapter.onDownloadItemCreated(item8); }); @@ -451,7 +455,7 @@ callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final View rootView = mUi.getView().getRootView(); Assert.assertNotNull(rootView.findViewById(R.id.snackbar)); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, (Runnable) () -> rootView.findViewById(R.id.snackbar_button).callOnClick()); mAdapterObserver.onSpaceDisplayUpdatedCallback.waitForCallback(callCount); @@ -484,7 +488,7 @@ int callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final DownloadItem item7 = StubbedProvider.createDownloadItem(7, "20161021 07:28"); final DownloadItem item8 = StubbedProvider.createDownloadItem(8, "20161021 17:28"); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mAdapter.onDownloadItemCreated(item7); mAdapter.onDownloadItemCreated(item8); }); @@ -507,7 +511,7 @@ // Click the delete button. callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> Assert.assertTrue( mUi.getDownloadManagerToolbarForTests() @@ -524,7 +528,7 @@ callCount = mAdapterObserver.onSpaceDisplayUpdatedCallback.getCallCount(); final View rootView = mUi.getView().getRootView(); Assert.assertNotNull(rootView.findViewById(R.id.snackbar)); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, (Runnable) () -> rootView.findViewById(R.id.snackbar_button).callOnClick()); mAdapterObserver.onSpaceDisplayUpdatedCallback.waitForCallback(callCount); @@ -565,7 +569,7 @@ shareIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)); // Scroll to ensure the item at position 8 is visible. - ThreadUtils.runOnUiThread(() -> mRecyclerView.scrollToPosition(9)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mRecyclerView.scrollToPosition(9)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); // Select another image, download item #0. @@ -579,7 +583,7 @@ shareIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM).size()); // Scroll to ensure the item at position 5 is visible. - ThreadUtils.runOnUiThread(() -> mRecyclerView.scrollToPosition(6)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mRecyclerView.scrollToPosition(6)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); // Select non-image item, download item #4. @@ -593,7 +597,7 @@ shareIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM).size()); // Scroll to ensure the item at position 2 is visible. - ThreadUtils.runOnUiThread(() -> mRecyclerView.scrollToPosition(3)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mRecyclerView.scrollToPosition(3)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); // Select an offline page #3. @@ -618,7 +622,7 @@ @EnableFeatures("OfflinePagesSharing") public void testShareOfflinePageWithP2PSharingEnabled() throws Exception { // Scroll to ensure the item at position 2 is visible. - ThreadUtils.runOnUiThread(() -> mRecyclerView.scrollToPosition(3)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mRecyclerView.scrollToPosition(3)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); // Select the offline page located at position #3. @@ -805,7 +809,7 @@ private void clickOnFilter(final DownloadManagerUi ui, final int position) throws Exception { int previousCount = mAdapterObserver.onChangedCallback.getCallCount(); final Spinner spinner = mUi.getDownloadManagerToolbarForTests().getSpinnerForTests(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { spinner.performClick(); spinner.setSelection(position); }); @@ -815,13 +819,14 @@ private void toggleItemSelection(int position) throws Exception { int callCount = mAdapterObserver.onSelectionCallback.getCallCount(); final DownloadItemView itemView = getView(position); - ThreadUtils.runOnUiThread((Runnable) () -> itemView.performLongClick()); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, (Runnable) () -> itemView.performLongClick()); mAdapterObserver.onSelectionCallback.waitForCallback(callCount, 1); } private void simulateContextMenu(int position, @StringRes int text) throws Exception { final DownloadItemView view = getView(position); - ThreadUtils.runOnUiThread((Runnable) () -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, (Runnable) () -> { Item[] items = view.getItems(); for (Item item : items) { if (item.getTextId() == text) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java index c77beb9..fa21691 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
@@ -6,6 +6,7 @@ import android.content.SharedPreferences.Editor; import android.support.test.filters.SmallTest; +import android.support.test.rule.ActivityTestRule; import android.support.v7.widget.RecyclerView; import org.junit.Assert; @@ -19,10 +20,10 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.download.DownloadActivity; import org.chromium.chrome.browser.download.DownloadItem; import org.chromium.chrome.browser.download.ui.StubbedProvider.StubbedDownloadDelegate; import org.chromium.chrome.browser.download.ui.StubbedProvider.StubbedOfflineContentProvider; -import org.chromium.chrome.browser.test.ChromeBrowserTestRule; import org.chromium.chrome.browser.widget.DateDividedAdapter.ItemViewType; import org.chromium.components.download.DownloadState; import org.chromium.components.offline_items_collection.ContentId; @@ -38,7 +39,8 @@ @RunWith(BaseJUnit4ClassRunner.class) public class DownloadHistoryAdapterTest { @Rule - public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); + public ActivityTestRule<DownloadActivity> mActivityTestRule = + new ActivityTestRule<>(DownloadActivity.class); private static class Observer extends RecyclerView.AdapterDataObserver implements DownloadHistoryAdapter.TestObserver, SpaceDisplay.Observer { @@ -128,7 +130,7 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mAdapter.initialize(mBackendProvider, null); + mAdapter.initialize(mActivityTestRule.getActivity(), mBackendProvider, null); } }); mAdapter.getSpaceDisplayForTests().addObserverForTests(mObserver);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java index 04e82ff..045dae5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java
@@ -30,8 +30,10 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; @@ -48,6 +50,8 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.ui.test.util.UiDisableIf; import java.util.Map; import java.util.concurrent.TimeoutException; @@ -127,6 +131,7 @@ @Test @SmallTest @Feature({"InterestFeedContentSuggestions"}) + @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/944061. public void testNtpOpeningTriggersInitializeOnlyOnce() throws InterruptedException { // We open to about:blank initially so we shouldn't have called initialize() yet. verify(mAppLifecycleListener, times(0)).initialize(); @@ -257,6 +262,7 @@ @Test @SmallTest @Feature({"InterestFeedContentSuggestions"}) + @DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/944061. public void testMultiWindowDoesNotCauseMultipleInitialize() throws InterruptedException { mActivityTestRule.loadUrl(UrlConstants.NTP_URL); verify(mAppLifecycleListener, times(1)).initialize(); @@ -308,12 +314,9 @@ private void signalActivityState(final Activity activity, final @ActivityState int activityState) throws InterruptedException, TimeoutException { final CallbackHelper waitForStateChangeHelper = new CallbackHelper(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - ApplicationStatus.onStateChangeForTesting(activity, activityState); - waitForStateChangeHelper.notifyCalled(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + ApplicationStatus.onStateChangeForTesting(activity, activityState); + waitForStateChangeHelper.notifyCalled(); }); waitForStateChangeHelper.waitForCallback(0);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java index 0c2a458..6b3c532 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -34,6 +34,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; @@ -58,6 +59,7 @@ import org.chromium.chrome.test.util.browser.suggestions.FakeMostVisitedSites; import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule; import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.ui.test.util.UiDisableIf; import java.util.List; @@ -68,6 +70,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS) +@DisableIf.Device(type = {UiDisableIf.TABLET}) // https://crbug.com/944061. public class FeedNewTabPageTest { private static final String TEST_FEED = UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/feed_large.gcl.bin");
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 7298e4b..7eb8a123 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
@@ -23,7 +23,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.customtabs.CustomTabActivity; @@ -35,6 +35,7 @@ import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; +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; @@ -250,7 +251,7 @@ } }); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { Button button = (Button) activity.findViewById(id); Assert.assertNotNull(message, button); button.performClick();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java index 6b57e808..f800826 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -25,6 +25,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; @@ -48,6 +49,7 @@ import org.chromium.content_public.browser.GestureListenerManager; import org.chromium.content_public.browser.GestureStateListener; import org.chromium.content_public.browser.SelectionPopupController; +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.content_public.browser.test.util.JavaScriptUtils; @@ -185,13 +187,10 @@ // the test (See https://b/10387660) UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - View view = tab.getContentView(); - view.setSystemUiVisibility( - view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_FULLSCREEN); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + View view = tab.getContentView(); + view.setSystemUiVisibility( + view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_FULLSCREEN); }); FullscreenTestUtils.waitForFullscreenFlag(tab, true, mActivityTestRule.getActivity()); FullscreenTestUtils.waitForPersistentFullscreen(delegate, true); @@ -451,20 +450,12 @@ Tab tab = mActivityTestRule.getActivity().getActivityTab(); final TabWebContentsDelegateAndroid delegate = tab.getTabWebContentsDelegateAndroid(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - delegate.rendererUnresponsive(); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { delegate.rendererUnresponsive(); }); FullscreenManagerTestUtils.waitForBrowserControlsPosition(mActivityTestRule, 0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - delegate.rendererResponsive(); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { delegate.rendererResponsive(); }); // TODO(tedchoc): This is running into timing issues with the renderer offset logic. //waitForBrowserControlsToBeMoveable(getActivity().getActivityTab());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java index 39bb59c..7f1c8f45 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -36,6 +36,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; @@ -59,6 +60,7 @@ import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.chrome.test.util.browser.sync.SyncTestUtil; import org.chromium.components.signin.ChromeSigninController; +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.ui.base.PageTransition; @@ -214,13 +216,10 @@ int callCount = mTestObserver.onChangedCallback.getCallCount(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - Assert.assertTrue( - mHistoryManager.getToolbarForTests().getMenu().performIdentifierAction( - R.id.selection_mode_delete_menu_id, 0)); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + Assert.assertTrue( + mHistoryManager.getToolbarForTests().getMenu().performIdentifierAction( + R.id.selection_mode_delete_menu_id, 0)); }); // Check that all items were removed. The onChangedCallback should be called three times - @@ -300,13 +299,10 @@ toggleItemSelection(2); toggleItemSelection(3); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - Assert.assertTrue( - mHistoryManager.getToolbarForTests().getMenu().performIdentifierAction( - R.id.selection_mode_open_in_incognito, 0)); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + Assert.assertTrue( + mHistoryManager.getToolbarForTests().getMenu().performIdentifierAction( + R.id.selection_mode_open_in_incognito, 0)); }); intended( @@ -633,12 +629,7 @@ private void toggleItemSelection(int position) throws Exception { int callCount = mTestObserver.onSelectionCallback.getCallCount(); final SelectableItemView<HistoryItem> itemView = getItemView(position); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - itemView.performLongClick(); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { itemView.performLongClick(); }); mTestObserver.onSelectionCallback.waitForCallback(callCount, 1); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java index 0ebe7f25..48592de 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
@@ -20,6 +20,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -32,6 +33,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.InfoBarTestAnimationListener; import org.chromium.chrome.test.util.InfoBarUtil; +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.net.test.EmbeddedTestServer; @@ -107,13 +109,10 @@ int previousCount = infoBars.size(); final TestListener testListener = new TestListener(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(), - testListener, InfoBarIdentifier.TEST_INFOBAR, 0, MESSAGE_TEXT, null, null, - null, expires); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(), + testListener, InfoBarIdentifier.TEST_INFOBAR, 0, MESSAGE_TEXT, null, null, null, + expires); }); mListener.addInfoBarAnimationFinished("InfoBar not added.");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java index e4f91bf..544fb20 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
@@ -20,6 +20,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; @@ -41,6 +42,7 @@ import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -515,15 +517,12 @@ mActivityTestRule.loadUrl(HELLO_WORLD_URL); // Fake an unresponsive renderer signal. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - CommandLine.getInstance().appendSwitch(ChromeSwitches.ENABLE_HUNG_RENDERER_INFOBAR); - mActivityTestRule.getActivity() - .getActivityTab() - .getTabWebContentsDelegateAndroid() - .rendererUnresponsive(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + CommandLine.getInstance().appendSwitch(ChromeSwitches.ENABLE_HUNG_RENDERER_INFOBAR); + mActivityTestRule.getActivity() + .getActivityTab() + .getTabWebContentsDelegateAndroid() + .rendererUnresponsive(); }); mListener.addInfoBarAnimationFinished("InfoBar not added"); @@ -534,14 +533,11 @@ Assert.assertTrue(InfoBarUtil.hasSecondaryButton(infoBars.get(0))); // Fake a responsive renderer signal. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity() - .getActivityTab() - .getTabWebContentsDelegateAndroid() - .rendererResponsive(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mActivityTestRule.getActivity() + .getActivityTab() + .getTabWebContentsDelegateAndroid() + .rendererResponsive(); }); mListener.removeInfoBarAnimationFinished("InfoBar not removed."); Assert.assertTrue("Wrong infobar count", mActivityTestRule.getInfoBars().isEmpty()); @@ -559,15 +555,12 @@ mActivityTestRule.loadUrl(HELLO_WORLD_URL); // Fake an unresponsive renderer signal. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - CommandLine.getInstance().appendSwitch(ChromeSwitches.ENABLE_HUNG_RENDERER_INFOBAR); - mActivityTestRule.getActivity() - .getActivityTab() - .getTabWebContentsDelegateAndroid() - .rendererUnresponsive(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + CommandLine.getInstance().appendSwitch(ChromeSwitches.ENABLE_HUNG_RENDERER_INFOBAR); + mActivityTestRule.getActivity() + .getActivityTab() + .getTabWebContentsDelegateAndroid() + .rendererUnresponsive(); }); mListener.addInfoBarAnimationFinished("InfoBar not added"); @@ -578,12 +571,8 @@ Assert.assertTrue(InfoBarUtil.hasSecondaryButton(infoBars.get(0))); // Activate the Kill button. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - InfoBarUtil.clickPrimaryButton(infoBars.get(0)); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { InfoBarUtil.clickPrimaryButton(infoBars.get(0)); }); // The renderer should have been killed and the InfoBar removed. mListener.removeInfoBarAnimationFinished("InfoBar not removed."); @@ -617,13 +606,10 @@ // Swap out the WebContents and send the user somewhere so that the InfoBar gets removed. InfoBarTestAnimationListener removeListener = new InfoBarTestAnimationListener(); mActivityTestRule.getInfoBarContainer().addAnimationListener(removeListener); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - WebContents newContents = WebContentsFactory.createWebContents(false, false); - mActivityTestRule.getActivity().getActivityTab().swapWebContents( - newContents, false, false); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + WebContents newContents = WebContentsFactory.createWebContents(false, false); + mActivityTestRule.getActivity().getActivityTab().swapWebContents( + newContents, false, false); }); mActivityTestRule.loadUrl(HELLO_WORLD_URL); removeListener.removeInfoBarAnimationFinished("InfoBar not removed.");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java index 9a8f038..09a0499d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java
@@ -14,8 +14,8 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ChromeActivity; @@ -27,6 +27,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.InfoBarTestAnimationListener; import org.chromium.chrome.test.util.InfoBarUtil; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.test.EmbeddedTestServer; import java.util.concurrent.TimeoutException; @@ -50,7 +51,7 @@ // Simulate the DSE being granted location (the test server isn't set to be the DSE). PermissionInfo locationSettings = new PermissionInfo( PermissionInfo.Type.GEOLOCATION, mTestServer.getURL(SEARCH_PAGE), null, false); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> locationSettings.setContentSetting(ContentSettingValues.ALLOW)); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java index 411f4e8..20bbb58 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java
@@ -34,7 +34,7 @@ @CommandLineParameter( {"", "enable-features=" + ChromeFeatureList.LOOKALIKE_NAVIGATION_URL_SUGGESTIONS_UI}) public class LookalikeInterstitialTest { - private static final String INTERSTITIAL_TITLE_PREFIX = "Did you mean?"; + private static final String INTERSTITIAL_TITLE_PREFIX = "Continue to "; private static final int INTERSTITIAL_TITLE_UPDATE_TIMEOUT_SECONDS = 5; @@ -62,8 +62,12 @@ "/chrome/test/data/android/navigate/simple.html")); // Wait for the interstitial page to commit and check the page title. - new TabTitleObserver(tab, INTERSTITIAL_TITLE_PREFIX) - .waitForTitleUpdate(INTERSTITIAL_TITLE_UPDATE_TIMEOUT_SECONDS); + new TabTitleObserver(tab, INTERSTITIAL_TITLE_PREFIX) { + @Override + protected boolean doesTitleMatch(String expectedTitle, String actualTitle) { + return actualTitle.indexOf(expectedTitle) == 0; + } + }.waitForTitleUpdate(INTERSTITIAL_TITLE_UPDATE_TIMEOUT_SECONDS); Assert.assertEquals(0, tab.getTitle().indexOf(INTERSTITIAL_TITLE_PREFIX)); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperUtils.java index 41b84ff..2a64d237 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperUtils.java
@@ -10,8 +10,10 @@ import org.junit.Assert; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.search_engines.TemplateUrlService; +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; @@ -55,12 +57,9 @@ }); // Click on the OK button. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - View view = rootView.findViewById(OK_BUTTON_ID); - view.performClick(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + View view = rootView.findViewById(OK_BUTTON_ID); + view.performClick(); }); // Confirm the engine was set appropriately.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewTest.java index 1595324..92a0e84c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewTest.java
@@ -23,10 +23,14 @@ import android.text.TextUtils; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; +import android.view.View; import android.widget.FrameLayout; import android.widget.ScrollView; import android.widget.TextView; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -335,6 +339,46 @@ onView(withId(R.id.negative_button)).check(matches(not(isDisplayed()))); } + @Test + @MediumTest + @Feature({"ModalDialog"}) + public void testTouchFilter() { + PropertyModel model = createModel( + mModelBuilder + .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, mResources, R.string.ok) + .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, mResources, + R.string.cancel) + .with(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY, true)); + onView(withId(R.id.positive_button)).check(matches(touchFilterEnabled())); + onView(withId(R.id.negative_button)).check(matches(touchFilterEnabled())); + } + + @Test + @MediumTest + @Feature({"ModalDialog"}) + public void testTouchFilterDisabled() { + PropertyModel model = createModel( + mModelBuilder + .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, mResources, R.string.ok) + .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, mResources, + R.string.cancel)); + onView(withId(R.id.positive_button)).check(matches(not(touchFilterEnabled()))); + onView(withId(R.id.negative_button)).check(matches(not(touchFilterEnabled()))); + } + + private static Matcher<View> touchFilterEnabled() { + return new TypeSafeMatcher<View>() { + @Override + public void describeTo(Description description) { + description.appendText("Touch filtering enabled"); + } + @Override + public boolean matchesSafely(View view) { + return view.getFilterTouchesWhenObscured(); + } + }; + } + private PropertyModel createModel(PropertyModel.Builder modelBuilder) { return ThreadUtils.runOnUiThreadBlockingNoException(() -> { PropertyModel model = modelBuilder.build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 7e2fe0a4..70aa1f80 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -332,6 +332,9 @@ @DisableIf.Build(sdk_is_greater_than = 22, message = "crbug.com/593007") @ParameterAnnotations.UseMethodParameter(InterestFeedParams.class) public void testSearchFromFakebox(boolean interestFeedEnabled) throws InterruptedException { + // TODO(https://crbug.com/944061): Re-enable tablet test on interest feed enabled. + if (interestFeedEnabled && mActivityTestRule.getActivity().isTablet()) return; + TouchCommon.singleClickView(mFakebox); waitForFakeboxFocusAnimationComplete(mNtp); final UrlBar urlBar = (UrlBar) mActivityTestRule.getActivity().findViewById(R.id.url_bar); @@ -393,6 +396,9 @@ @ParameterAnnotations.UseMethodParameter(InterestFeedParams.class) public void testOpenMostVisitedItemInIncognitoTab(boolean interestFeedEnabled) throws InterruptedException, ExecutionException { + // TODO(https://crbug.com/944061): Re-enable tablet test on interest feed enabled. + if (interestFeedEnabled && mActivityTestRule.getActivity().isTablet()) return; + ChromeTabUtils.invokeContextMenuAndOpenInANewTab(mActivityTestRule, mTileGridLayout.getChildAt(0), ContextMenuManager.ContextMenuItemId.OPEN_IN_INCOGNITO_TAB, true, @@ -407,6 +413,9 @@ @Feature({"NewTabPage", "FeedNewTabPage"}) @ParameterAnnotations.UseMethodParameter(InterestFeedParams.class) public void testRemoveMostVisitedItem(boolean interestFeedEnabled) throws ExecutionException { + // TODO(https://crbug.com/944061): Re-enable tablet test on interest feed enabled. + if (interestFeedEnabled && mActivityTestRule.getActivity().isTablet()) return; + SiteSuggestion testSite = mSiteSuggestions.get(0); View mostVisitedItem = mTileGridLayout.getChildAt(0); ArrayList<View> views = new ArrayList<>(); @@ -454,6 +463,9 @@ @ParameterAnnotations.UseMethodParameter(InterestFeedParams.class) public void testUrlFocusAnimationsEnabledOnFailedLoad(boolean interestFeedEnabled) throws Exception { + // TODO(https://crbug.com/944061): Re-enable tablet test on interest feed enabled. + if (interestFeedEnabled && mActivityTestRule.getActivity().isTablet()) return; + // TODO(jbudorick): switch this to EmbeddedTestServer. TestWebServer webServer = TestWebServer.start(); try {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java index 947b6a4b..e7d64b061 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -20,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; @@ -36,6 +37,7 @@ import org.chromium.components.offlinepages.SavePageResult; import org.chromium.components.offlinepages.background.UpdateRequestResult; import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.NetworkChangeNotifier; import org.chromium.net.test.EmbeddedTestServer; @@ -76,27 +78,24 @@ private void initializeBridgeForProfile(final boolean incognitoProfile) throws InterruptedException { final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - Profile profile = Profile.getLastUsedProfile(); - if (incognitoProfile) { - profile = profile.getOffTheRecordProfile(); - } - // Ensure we start in an offline state. - mOfflinePageBridge = OfflinePageBridge.getForProfile(profile); - if (mOfflinePageBridge == null || mOfflinePageBridge.isOfflinePageModelLoaded()) { - semaphore.release(); - return; - } - mOfflinePageBridge.addObserver(new OfflinePageModelObserver() { - @Override - public void offlinePageModelLoaded() { - semaphore.release(); - mOfflinePageBridge.removeObserver(this); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + Profile profile = Profile.getLastUsedProfile(); + if (incognitoProfile) { + profile = profile.getOffTheRecordProfile(); } + // Ensure we start in an offline state. + mOfflinePageBridge = OfflinePageBridge.getForProfile(profile); + if (mOfflinePageBridge == null || mOfflinePageBridge.isOfflinePageModelLoaded()) { + semaphore.release(); + return; + } + mOfflinePageBridge.addObserver(new OfflinePageModelObserver() { + @Override + public void offlinePageModelLoaded() { + semaphore.release(); + mOfflinePageBridge.removeObserver(this); + } + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } @@ -509,16 +508,13 @@ private void deletePages(final List<Long> offlineIds) throws InterruptedException { final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mOfflinePageBridge.deletePagesByOfflineId(offlineIds, new Callback<Integer>() { - @Override - public void onResult(Integer deletePageResult) { - semaphore.release(); - } - }); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mOfflinePageBridge.deletePagesByOfflineId(offlineIds, new Callback<Integer>() { + @Override + public void onResult(Integer deletePageResult) { + semaphore.release(); + } + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } @@ -547,18 +543,15 @@ throws InterruptedException { final List<OfflinePageItem> result = new ArrayList<OfflinePageItem>(); final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mOfflinePageBridge.getPagesByNamespace( - namespace, new Callback<List<OfflinePageItem>>() { - @Override - public void onResult(List<OfflinePageItem> pages) { - result.addAll(pages); - semaphore.release(); - } - }); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mOfflinePageBridge.getPagesByNamespace( + namespace, new Callback<List<OfflinePageItem>>() { + @Override + public void onResult(List<OfflinePageItem> pages) { + result.addAll(pages); + semaphore.release(); + } + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); return result; @@ -590,20 +583,16 @@ private void savePageLater(final String url, final String namespace) throws InterruptedException { final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mOfflinePageBridge.savePageLater(url, namespace, true /* userRequested */, - new OfflinePageOrigin(), new Callback<Integer>() { - @Override - public void onResult(Integer i) { - Assert.assertEquals("SavePageLater did not succeed", - Integer.valueOf(0), - i); // 0 is SUCCESS - semaphore.release(); - } - }); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mOfflinePageBridge.savePageLater(url, namespace, true /* userRequested */, + new OfflinePageOrigin(), new Callback<Integer>() { + @Override + public void onResult(Integer i) { + Assert.assertEquals("SavePageLater did not succeed", Integer.valueOf(0), + i); // 0 is SUCCESS + semaphore.release(); + } + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); } @@ -613,19 +602,16 @@ final AtomicReference<List<OfflinePageBridge.RequestRemovedResult>> ref = new AtomicReference<>(); final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mOfflinePageBridge.removeRequestsFromQueue(requestsToRemove, - new Callback<List<OfflinePageBridge.RequestRemovedResult>>() { - @Override - public void onResult( - List<OfflinePageBridge.RequestRemovedResult> removedRequests) { - ref.set(removedRequests); - semaphore.release(); - } - }); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mOfflinePageBridge.removeRequestsFromQueue( + requestsToRemove, new Callback<List<OfflinePageBridge.RequestRemovedResult>>() { + @Override + public void onResult( + List<OfflinePageBridge.RequestRemovedResult> removedRequests) { + ref.set(removedRequests); + semaphore.release(); + } + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); return ref.get(); @@ -635,15 +621,12 @@ throws InterruptedException { final AtomicReference<LoadUrlParams> ref = new AtomicReference<>(); final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mOfflinePageBridge.getLoadUrlParamsForOpeningMhtmlFileOrContent( - url, (loadUrlParams) -> { - ref.set(loadUrlParams); - semaphore.release(); - }); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mOfflinePageBridge.getLoadUrlParamsForOpeningMhtmlFileOrContent( + url, (loadUrlParams) -> { + ref.set(loadUrlParams); + semaphore.release(); + }); }); Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); return ref.get();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java index 1aa75406..492d949 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
@@ -21,7 +21,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.StreamUtil; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Manual; import org.chromium.base.test.util.TimeoutScale; @@ -33,6 +33,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.offlinepages.BackgroundSavePageResult; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.io.BufferedReader; import java.io.File; @@ -132,26 +133,23 @@ Context.NOTIFICATION_SERVICE); notificationManager.cancelAll(); final Semaphore mClearingSemaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - assert mBridge != null; - mBridge.getRequestsInQueue(new Callback<SavePageRequest[]>() { - @Override - public void onResult(SavePageRequest[] results) { - ArrayList<Long> ids = new ArrayList<Long>(results.length); - for (int i = 0; i < results.length; i++) { - ids.add(results[i].getRequestId()); - } - mBridge.removeRequestsFromQueue(ids, new Callback<Integer>() { - @Override - public void onResult(Integer removedCount) { - mClearingSemaphore.release(); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + assert mBridge != null; + mBridge.getRequestsInQueue(new Callback<SavePageRequest[]>() { + @Override + public void onResult(SavePageRequest[] results) { + ArrayList<Long> ids = new ArrayList<Long>(results.length); + for (int i = 0; i < results.length; i++) { + ids.add(results[i].getRequestId()); } - }); - } + mBridge.removeRequestsFromQueue(ids, new Callback<Integer>() { + @Override + public void onResult(Integer removedCount) { + mClearingSemaphore.release(); + } + }); + } + }); }); checkTrue(mClearingSemaphore.tryAcquire(REMOVE_REQUESTS_TIMEOUT_MS, TimeUnit.MILLISECONDS), "Timed out when clearing remaining requests!"); @@ -229,27 +227,24 @@ private void initializeBridgeForProfile(final boolean useTestingScheduler) throws InterruptedException { final Semaphore semaphore = new Semaphore(0); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - Profile profile = Profile.getLastUsedProfile(); - mBridge = new OfflinePageEvaluationBridge(profile, useTestingScheduler); - if (mBridge == null) { - Assert.fail("OfflinePageEvaluationBridge initialization failed!"); - return; - } - if (mBridge.isOfflinePageModelLoaded()) { - semaphore.release(); - return; - } - mBridge.addObserver(new OfflinePageEvaluationObserver() { - @Override - public void offlinePageModelLoaded() { - semaphore.release(); - mBridge.removeObserver(this); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + Profile profile = Profile.getLastUsedProfile(); + mBridge = new OfflinePageEvaluationBridge(profile, useTestingScheduler); + if (mBridge == null) { + Assert.fail("OfflinePageEvaluationBridge initialization failed!"); + return; } + if (mBridge.isOfflinePageModelLoaded()) { + semaphore.release(); + return; + } + mBridge.addObserver(new OfflinePageEvaluationObserver() { + @Override + public void offlinePageModelLoaded() { + semaphore.release(); + mBridge.removeObserver(this); + } + }); }); checkTrue(semaphore.tryAcquire(PAGE_MODEL_LOAD_TIMEOUT_MS, TimeUnit.MILLISECONDS), "Timed out when loading OfflinePageModel!"); @@ -323,12 +318,8 @@ */ private void savePageLater(final String url, final String namespace) throws InterruptedException { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mBridge.savePageLater(url, namespace, mIsUserRequested); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { mBridge.savePageLater(url, namespace, mIsUserRequested); }); } private void processUrls(List<String> urls) throws InterruptedException, IOException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java index 603f0270..4c425d41 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; @@ -39,6 +40,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.offlinepages.SavePageResult; +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.net.ConnectionType; @@ -243,24 +245,20 @@ int tabId = mActivityTestRule.getActivity().getActivityTab().getId(); // Act. This needs to be called from the UI thread. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - OfflinePageTabObserver offlineObserver = new OfflinePageTabObserver( - mActivityTestRule.getActivity().getTabModelSelector(), - mActivityTestRule.getActivity().getSnackbarManager(), - mockSnackbarController); - OfflinePageTabObserver.setObserverForTesting( - mActivityTestRule.getActivity(), offlineObserver); - OfflinePageUtils.showOfflineSnackbarIfNecessary( - mActivityTestRule.getActivity().getActivityTab()); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + OfflinePageTabObserver offlineObserver = new OfflinePageTabObserver( + mActivityTestRule.getActivity().getTabModelSelector(), + mActivityTestRule.getActivity().getSnackbarManager(), mockSnackbarController); + OfflinePageTabObserver.setObserverForTesting( + mActivityTestRule.getActivity(), offlineObserver); + OfflinePageUtils.showOfflineSnackbarIfNecessary( + mActivityTestRule.getActivity().getActivityTab()); - // Pretend that we went online, this should cause the snackbar to show. - // This call will set the isConnected call to return true. - NetworkChangeNotifier.forceConnectivityState(true); - // This call will make an event get sent with connection type CONNECTION_WIFI. - NetworkChangeNotifier.fakeNetworkConnected(0, ConnectionType.CONNECTION_WIFI); - } + // Pretend that we went online, this should cause the snackbar to show. + // This call will set the isConnected call to return true. + NetworkChangeNotifier.forceConnectivityState(true); + // This call will make an event get sent with connection type CONNECTION_WIFI. + NetworkChangeNotifier.fakeNetworkConnected(0, ConnectionType.CONNECTION_WIFI); }); // Wait for the snackbar to be dismissed before we check its values. The snackbar is on a
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java index 9da95525..dffcb95 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflineTestUtil.java
@@ -11,11 +11,13 @@ import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageModelObserver; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.offline_items_collection.OfflineItem; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.CriteriaHelper; import java.util.ArrayList; @@ -114,7 +116,7 @@ throws TimeoutException, InterruptedException { final CallbackHelper ready = new CallbackHelper(); final AtomicReference<OfflinePageBridge> result = new AtomicReference<OfflinePageBridge>(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { OfflinePageBridge bridge = OfflinePageBridge.getForProfile(Profile.getLastUsedProfile()); if (bridge == null || bridge.isOfflinePageModelLoaded()) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java index 0785c91f..636432dc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.browser.ChromeSwitches; @@ -30,6 +31,7 @@ import org.chromium.components.background_task_scheduler.TaskInfo; import org.chromium.components.background_task_scheduler.TaskParameters; import org.chromium.components.offlinepages.PrefetchBackgroundTaskRescheduleType; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.HashMap; import java.util.concurrent.Semaphore; @@ -95,12 +97,8 @@ } public void setTaskRescheduling(int rescheduleType) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - setTaskReschedulingForTesting(rescheduleType); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { setTaskReschedulingForTesting(rescheduleType); }); } public void waitForTaskFinished() throws Exception { @@ -121,19 +119,16 @@ @Override public boolean schedule(final Context context, final TaskInfo taskInfo) { mAddCount++; - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TestPrefetchBackgroundTask task = new TestPrefetchBackgroundTask(taskInfo); - mTasks.put(taskInfo.getTaskId(), task); - task.startTask(context, new TaskFinishedCallback() { - @Override - public void taskFinished(boolean needsReschedule) { - removeTask(taskInfo.getTaskId()); - } - }); - mStartSemaphore.release(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + TestPrefetchBackgroundTask task = new TestPrefetchBackgroundTask(taskInfo); + mTasks.put(taskInfo.getTaskId(), task); + task.startTask(context, new TaskFinishedCallback() { + @Override + public void taskFinished(boolean needsReschedule) { + removeTask(taskInfo.getTaskId()); + } + }); + mStartSemaphore.release(); }); return true; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java index 6a32ef9..ab31caf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
@@ -14,6 +14,7 @@ import org.junit.runner.RunWith; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; @@ -24,6 +25,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher; +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.ui.test.util.UiRestriction; @@ -229,11 +231,8 @@ } private void showAppMenuAndAssertMenuShown() { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity().getAppMenuHandler().showAppMenu(null, false, false); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mActivityTestRule.getActivity().getAppMenuHandler().showAppMenu(null, false, false); }); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override @@ -244,12 +243,8 @@ } private void hideAppMenuAndAssertMenuShown() { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity().getAppMenuHandler().hideAppMenu(); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { mActivityTestRule.getActivity().getAppMenuHandler().hideAppMenu(); }); CriteriaHelper.pollInstrumentationThread(new Criteria() { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java index ea0ef0ef..1e81e38 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -19,6 +19,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; @@ -34,6 +35,7 @@ import org.chromium.chrome.browser.widget.prefeditor.EditorObserverForTest; import org.chromium.chrome.browser.widget.prefeditor.EditorTextField; import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -361,7 +363,7 @@ protected void clickAndroidBackButtonInEditorAndWait(CallbackHelper helper) throws InterruptedException, TimeoutException { int callCount = helper.getCallCount(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mUI.getEditorDialog().dispatchKeyEvent( new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)); mUI.getEditorDialog().dispatchKeyEvent(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java index e3bab92..7e0e3c84 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java
@@ -27,6 +27,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.library_loader.ProcessInitException; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; @@ -44,6 +45,7 @@ import org.chromium.chrome.browser.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ActivityUtils; +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.content_public.browser.test.util.UiUtils; @@ -414,22 +416,14 @@ private static void userSetTextScale(final AccessibilityPreferences accessibilityPref, final SeekBarPreference textScalePref, final float textScale) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - accessibilityPref.onPreferenceChange(textScalePref, textScale); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { accessibilityPref.onPreferenceChange(textScalePref, textScale); }); } private static void userSetForceEnableZoom(final AccessibilityPreferences accessibilityPref, final SeekBarLinkedCheckBoxPreference forceEnableZoomPref, final boolean enabled) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - accessibilityPref.onPreferenceChange(forceEnableZoomPref, enabled); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> { accessibilityPref.onPreferenceChange(forceEnableZoomPref, enabled); }); } private static Preference waitForPreference(final PreferenceFragment prefFragment,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java index d749e16..1c7e331 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java
@@ -13,10 +13,11 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.chrome.browser.test.ChromeBrowserTestRule; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; +import org.chromium.content_public.browser.UiThreadTaskTraits; /** * Tests sharing URLs in reader mode (DOM distiller) @@ -31,16 +32,13 @@ private void assertCorrectUrl(final String originalUrl, final String sharedUrl) throws Throwable { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - ShareParams params = - new ShareParams.Builder(new Activity(), "", sharedUrl).setText("").build(); - Intent intent = ShareHelper.getShareLinkIntent(params); - Assert.assertTrue(intent.hasExtra(Intent.EXTRA_TEXT)); - String url = intent.getStringExtra(Intent.EXTRA_TEXT); - Assert.assertEquals(originalUrl, url); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + ShareParams params = + new ShareParams.Builder(new Activity(), "", sharedUrl).setText("").build(); + Intent intent = ShareHelper.getShareLinkIntent(params); + Assert.assertTrue(intent.hasExtra(Intent.EXTRA_TEXT)); + String url = intent.getStringExtra(Intent.EXTRA_TEXT); + Assert.assertEquals(originalUrl, url); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java index f2b520b..4d3b059 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java
@@ -13,13 +13,14 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +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; @@ -74,37 +75,26 @@ Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_TEST_SNACKBAR); final Snackbar persistent = Snackbar.make("persistent", mDefaultController, Snackbar.TYPE_PERSISTENT, Snackbar.UMA_TEST_SNACKBAR); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(stackbar); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mManager.showSnackbar(stackbar); }); CriteriaHelper.pollUiThread(new Criteria("First snackbar not shown") { @Override public boolean isSatisfied() { return mManager.isShowing() && mManager.getCurrentSnackbarForTesting() == stackbar; } }); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(queuebar); - Assert.assertTrue("Snackbar not showing", mManager.isShowing()); - Assert.assertEquals( - "Snackbars on stack should not be cancelled by snackbars on queue", - stackbar, mManager.getCurrentSnackbarForTesting()); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mManager.showSnackbar(queuebar); + Assert.assertTrue("Snackbar not showing", mManager.isShowing()); + Assert.assertEquals("Snackbars on stack should not be cancelled by snackbars on queue", + stackbar, mManager.getCurrentSnackbarForTesting()); }); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(persistent); - Assert.assertTrue("Snackbar not showing", mManager.isShowing()); - Assert.assertEquals( - "Snackbars on stack should not be cancelled by persistent snackbars", - stackbar, mManager.getCurrentSnackbarForTesting()); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + mManager.showSnackbar(persistent); + Assert.assertTrue("Snackbar not showing", mManager.isShowing()); + Assert.assertEquals( + "Snackbars on stack should not be cancelled by persistent snackbars", stackbar, + mManager.getCurrentSnackbarForTesting()); }); CriteriaHelper.pollUiThread(new Criteria("Snackbar on queue not shown") { @Override @@ -119,7 +109,7 @@ && mManager.getCurrentSnackbarForTesting() == persistent; } }); - ThreadUtils.runOnUiThread(() -> mManager.onClick(null)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.onClick(null)); CriteriaHelper.pollUiThread(new Criteria("Persistent snackbar did not get cleared") { @Override public boolean isSatisfied() { @@ -138,12 +128,7 @@ Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_TEST_SNACKBAR); final Snackbar persistent = Snackbar.make("persistent", mDefaultController, Snackbar.TYPE_PERSISTENT, Snackbar.UMA_TEST_SNACKBAR); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(persistent); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.showSnackbar(persistent)); CriteriaHelper.pollUiThread(new Criteria("First snackbar not shown") { @Override public boolean isSatisfied() { @@ -151,12 +136,7 @@ && mManager.getCurrentSnackbarForTesting() == persistent; } }); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(queuebar); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.showSnackbar(queuebar)); CriteriaHelper.pollUiThread(new Criteria( "Persistent snackbar was not cleared by queue snackbar") { @Override @@ -164,12 +144,7 @@ return mManager.isShowing() && mManager.getCurrentSnackbarForTesting() == queuebar; } }); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(stackbar); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.showSnackbar(stackbar)); CriteriaHelper.pollUiThread( new Criteria("Snackbar on queue was not cleared by snackbar stack.") { @Override @@ -185,7 +160,7 @@ && mManager.getCurrentSnackbarForTesting() == persistent; } }); - ThreadUtils.runOnUiThread(() -> mManager.onClick(null)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.onClick(null)); CriteriaHelper.pollUiThread(new Criteria("Persistent snackbar did not get cleared") { @Override public boolean isSatisfied() { @@ -200,12 +175,7 @@ final Snackbar snackbar = Snackbar.make("stack", mDismissController, Snackbar.TYPE_ACTION, Snackbar.UMA_TEST_SNACKBAR); mDismissed = false; - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.showSnackbar(snackbar); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.showSnackbar(snackbar)); CriteriaHelper.pollUiThread( new Criteria("Snackbar on queue was not cleared by snackbar stack.") { @Override @@ -214,12 +184,8 @@ && mManager.getCurrentSnackbarForTesting() == snackbar; } }); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mManager.dismissSnackbars(mDismissController); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mManager.dismissSnackbars(mDismissController)); CriteriaHelper.pollUiThread(new Criteria("Snackbar did not time out") { @Override public boolean isSatisfied() { @@ -236,7 +202,7 @@ final Snackbar snackbar = Snackbar.make("persistent", mDismissController, Snackbar.TYPE_PERSISTENT, Snackbar.UMA_TEST_SNACKBAR); mDismissed = false; - ThreadUtils.runOnUiThread(() -> mManager.showSnackbar(snackbar)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.showSnackbar(snackbar)); CriteriaHelper.pollUiThread(new Criteria("Persistent Snackbar not shown.") { @Override public boolean isSatisfied() { @@ -250,7 +216,7 @@ return mManager.isShowing() && !mDismissed; } }); - ThreadUtils.runOnUiThread(() -> mManager.onClick(null)); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> mManager.onClick(null)); CriteriaHelper.pollUiThread(new Criteria("Persistent snackbar not removed on action.") { @Override public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java index a14631c7..99fbb6d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassinTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.CallbackHelper; @@ -41,6 +42,7 @@ import org.chromium.chrome.browser.tabmodel.document.MockDocumentTabModel; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.chrome.test.util.browser.tabmodel.document.MockActivityDelegate; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import java.io.File; @@ -182,13 +184,10 @@ final DocumentModeAssassin assassin = createAssassinForTesting(DocumentModeAssassin.STAGE_UNINITIALIZED, true, false); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - assassin.addObserver(observer); - Assert.assertEquals(0, doneCallback.getCallCount()); - assassin.migrateFromDocumentToTabbedMode(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + assassin.addObserver(observer); + Assert.assertEquals(0, doneCallback.getCallCount()); + assassin.migrateFromDocumentToTabbedMode(); }); doneCallback.waitForCallback(0); @@ -242,20 +241,17 @@ setUpDirectories(); final DocumentModeAssassin assassin = createAssassinForTesting( DocumentModeAssassin.STAGE_UNINITIALIZED, true, true); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - assassin.addObserver(observer); - Assert.assertEquals(0, copyStartedCallback.getCallCount()); - Assert.assertEquals(0, copyDoneCallback.getCallCount()); - Assert.assertEquals(0, writeStartedCallback.getCallCount()); - Assert.assertEquals(0, writeDoneCallback.getCallCount()); - Assert.assertEquals(0, changeStartedCallback.getCallCount()); - Assert.assertEquals(0, changeDoneCallback.getCallCount()); - Assert.assertEquals(0, deletionStartedCallback.getCallCount()); - Assert.assertEquals(0, deletionDoneCallback.getCallCount()); - assassin.migrateFromDocumentToTabbedMode(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + assassin.addObserver(observer); + Assert.assertEquals(0, copyStartedCallback.getCallCount()); + Assert.assertEquals(0, copyDoneCallback.getCallCount()); + Assert.assertEquals(0, writeStartedCallback.getCallCount()); + Assert.assertEquals(0, writeDoneCallback.getCallCount()); + Assert.assertEquals(0, changeStartedCallback.getCallCount()); + Assert.assertEquals(0, changeDoneCallback.getCallCount()); + Assert.assertEquals(0, deletionStartedCallback.getCallCount()); + Assert.assertEquals(0, deletionDoneCallback.getCallCount()); + assassin.migrateFromDocumentToTabbedMode(); }); // Confirm that files got copied over. @@ -327,17 +323,14 @@ setUpDirectories(); final DocumentModeAssassin assassin = createAssassinForTesting(DocumentModeAssassin.STAGE_UNINITIALIZED, true, true); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - assassin.addObserver(observer); - Assert.assertEquals(0, writeDoneCallback.getCallCount()); - Assert.assertEquals(0, changeStartedCallback.getCallCount()); - Assert.assertEquals(0, changeDoneCallback.getCallCount()); - Assert.assertEquals(0, deletionStartedCallback.getCallCount()); - Assert.assertEquals(0, deletionDoneCallback.getCallCount()); - assassin.migrateFromDocumentToTabbedMode(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + assassin.addObserver(observer); + Assert.assertEquals(0, writeDoneCallback.getCallCount()); + Assert.assertEquals(0, changeStartedCallback.getCallCount()); + Assert.assertEquals(0, changeDoneCallback.getCallCount()); + Assert.assertEquals(0, deletionStartedCallback.getCallCount()); + Assert.assertEquals(0, deletionDoneCallback.getCallCount()); + assassin.migrateFromDocumentToTabbedMode(); }); // Confirm that the user got moved into tabbed mode. @@ -375,14 +368,11 @@ DocumentModeAssassin.STAGE_WRITE_TABMODEL_METADATA_DONE, false, true); // Write out the preference and wait for it. - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - assassin.addObserver(observer); - Assert.assertEquals(0, changeStartedCallback.getCallCount()); - Assert.assertEquals(0, changeDoneCallback.getCallCount()); - assassin.switchToTabbedMode(); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + assassin.addObserver(observer); + Assert.assertEquals(0, changeStartedCallback.getCallCount()); + Assert.assertEquals(0, changeDoneCallback.getCallCount()); + assassin.switchToTabbedMode(); }); changeStartedCallback.waitForCallback(0); mFinishAllDocumentActivitiesCallback.waitForCallback(0);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java index ed5a7f4..b737d2e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java
@@ -215,19 +215,11 @@ checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); mActivityTestRule.loadUrl("about:blank"); checkForBrandColor(mDefaultColor); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity().onBackPressed(); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mActivityTestRule.getActivity().onBackPressed()); checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getActivity().onBackPressed(); - } - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> mActivityTestRule.getActivity().onBackPressed()); checkForBrandColor(mDefaultColor); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java index 53d835b6d..2c351b1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java
@@ -21,7 +21,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; @@ -34,6 +34,7 @@ import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.RenderTestRule; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.io.IOException; import java.util.concurrent.TimeoutException; @@ -84,7 +85,7 @@ PermissionInfo notificationSettings = new PermissionInfo(PermissionInfo.Type.NOTIFICATION, "http://127.0.0.1:" + String.valueOf(SERVER_PORT), null, false); - ThreadUtils.runOnUiThread( + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> notificationSettings.setContentSetting(ContentSettingValues.DEFAULT)); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java index 0223775..56d9134 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
@@ -16,6 +16,7 @@ import org.junit.Assert; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.vr.KeyboardTestAction; @@ -28,6 +29,7 @@ import org.chromium.chrome.browser.vr.VrDialog; import org.chromium.chrome.browser.vr.VrShell; import org.chromium.chrome.browser.vr.VrViewContainer; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.DOMUtils; @@ -522,7 +524,7 @@ */ public static void waitNumFrames(int numFrames) { final CountDownLatch frameLatch = new CountDownLatch(numFrames); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { final Choreographer.FrameCallback callback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java index f380903..29f4d82 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
@@ -12,7 +12,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -22,6 +22,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.browser.WebappTestPage; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.test.EmbeddedTestServerRule; import java.util.HashMap; @@ -100,15 +101,13 @@ private void startWebApkUpdateDataFetcher(final String scopeUrl, final String manifestUrl, final WebApkUpdateDataFetcher.Observer observer) { final WebApkUpdateDataFetcher fetcher = new WebApkUpdateDataFetcher(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - WebApkInfo oldInfo = WebApkInfo.create("", "", scopeUrl, null, null, null, null, - null, -1, -1, -1, -1, -1, "random.package", -1, manifestUrl, "", - WebApkInfo.WebApkDistributor.BROWSER, new HashMap<String, String>(), null, - false /* forceNavigation */, false /* useTransparentSplash */, null /* shareData */); - fetcher.start(mTab, oldInfo, observer); - } + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + WebApkInfo oldInfo = WebApkInfo.create("", "", scopeUrl, null, null, null, null, null, + -1, -1, -1, -1, -1, "random.package", -1, manifestUrl, "", + WebApkInfo.WebApkDistributor.BROWSER, new HashMap<String, String>(), null, + false /* forceNavigation */, false /* useTransparentSplash */, + null /* shareData */); + fetcher.start(mTab, oldInfo, observer); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java index acba719..e0d6dcd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -24,8 +24,8 @@ import org.junit.runner.RunWith; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -36,6 +36,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.UiThreadTaskTraits; /** * Tests for splash screens. @@ -98,13 +99,10 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); Assert.assertTrue(mActivityTestRule.isSplashScreenVisible()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulateFirstVisuallyNonEmptyPaint( - mActivityTestRule.getActivity().getActivityTab()); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulateFirstVisuallyNonEmptyPaint( + mActivityTestRule.getActivity().getActivityTab())); mActivityTestRule.waitUntilSplashscreenHides(); } @@ -116,12 +114,10 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); Assert.assertTrue(mActivityTestRule.isSplashScreenVisible()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulateCrash(mActivityTestRule.getActivity().getActivityTab(), true); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulateCrash( + mActivityTestRule.getActivity().getActivityTab(), true)); mActivityTestRule.waitUntilSplashscreenHides(); } @@ -133,13 +129,10 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); Assert.assertTrue(mActivityTestRule.isSplashScreenVisible()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulatePageLoadFinished( - mActivityTestRule.getActivity().getActivityTab()); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulatePageLoadFinished( + mActivityTestRule.getActivity().getActivityTab())); mActivityTestRule.waitUntilSplashscreenHides(); } @@ -151,13 +144,10 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); Assert.assertTrue(mActivityTestRule.isSplashScreenVisible()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulatePageLoadFailed( - mActivityTestRule.getActivity().getActivityTab(), 0); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulatePageLoadFailed( + mActivityTestRule.getActivity().getActivityTab(), 0)); mActivityTestRule.waitUntilSplashscreenHides(); } @@ -169,15 +159,12 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); Assert.assertTrue(mActivityTestRule.isSplashScreenVisible()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - Tab tab = mActivityTestRule.getActivity().getActivityTab(); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { + Tab tab = mActivityTestRule.getActivity().getActivityTab(); - TabTestUtils.simulatePageLoadFinished(tab); - TabTestUtils.simulatePageLoadFailed(tab, 0); - TabTestUtils.simulateFirstVisuallyNonEmptyPaint(tab); - } + TabTestUtils.simulatePageLoadFinished(tab); + TabTestUtils.simulatePageLoadFailed(tab, 0); + TabTestUtils.simulateFirstVisuallyNonEmptyPaint(tab); }); mActivityTestRule.waitUntilSplashscreenHides(); @@ -235,13 +222,10 @@ @Feature({"Webapps"}) public void testUmaWhenSplashHides() throws Exception { mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulateFirstVisuallyNonEmptyPaint( - mActivityTestRule.getActivity().getActivityTab()); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulateFirstVisuallyNonEmptyPaint( + mActivityTestRule.getActivity().getActivityTab())); mActivityTestRule.waitUntilSplashscreenHides();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java index 8b80fa0..755046b6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
@@ -15,8 +15,8 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -26,6 +26,7 @@ import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +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; @@ -78,13 +79,10 @@ finalColor = ColorUtils.getDarkenedColorForStatusBar(Color.GREEN); } - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - TabTestUtils.simulateChangeThemeColor( - mActivityTestRule.getActivity().getActivityTab(), baseColor); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () + -> TabTestUtils.simulateChangeThemeColor( + mActivityTestRule.getActivity().getActivityTab(), baseColor)); // Waits for theme-color to change so the test doesn't rely on system timing. CriteriaHelper.pollInstrumentationThread(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java index 0918c43..c72fdc6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
@@ -17,7 +17,7 @@ import org.junit.runner.RunWith; import org.chromium.base.DiscardableReferencePool; -import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -26,6 +26,7 @@ import org.chromium.chrome.browser.widget.ThumbnailProvider.ThumbnailRequest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.content_public.browser.UiThreadTaskTraits; /** * Instrumentation test for {@link ThumbnailProviderImpl}. @@ -43,7 +44,7 @@ @Before public void setUp() throws Exception { mActivityTestRule.startMainActivityOnBlankPage(); - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { mReferencePool = new DiscardableReferencePool(); mThumbnailProvider = new ThumbnailProviderImpl( mReferencePool, ThumbnailProviderImpl.ClientType.NTP_SUGGESTIONS); @@ -52,7 +53,7 @@ @After public void tearDown() { - ThreadUtils.runOnUiThread(mThumbnailProvider::destroy); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, mThumbnailProvider::destroy); } @Test @@ -67,9 +68,8 @@ final TestThumbnailRequest request = new TestThumbnailRequest( testFilePath, requiredSize, thumbnailRetrievedCallbackHelper); - ThreadUtils.runOnUiThread(() -> { - mThumbnailProvider.getThumbnail(request); - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mThumbnailProvider.getThumbnail(request); }); thumbnailRetrievedCallbackHelper.waitForCallback( "Reached timeout when fetching a thumbnail for a downloaded image.", 0); @@ -89,9 +89,8 @@ final TestThumbnailRequest request = new TestThumbnailRequest( testFilePath, requiredSize, thumbnailRetrievedCallbackHelper); - ThreadUtils.runOnUiThread(() -> { - mThumbnailProvider.getThumbnail(request); - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mThumbnailProvider.getThumbnail(request); }); thumbnailRetrievedCallbackHelper.waitForCallback( "Reached timeout when fetching a thumbnail for a downloaded image.", 0); @@ -111,9 +110,8 @@ final TestThumbnailRequest request = new TestThumbnailRequest( testFilePath, requiredSize, thumbnailRetrievedCallbackHelper); - ThreadUtils.runOnUiThread(() -> { - mThumbnailProvider.getThumbnail(request); - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mThumbnailProvider.getThumbnail(request); }); thumbnailRetrievedCallbackHelper.waitForCallback( "Reached timeout when fetching a thumbnail for a downloaded image.", 0); @@ -133,9 +131,8 @@ final TestThumbnailRequest request = new TestThumbnailRequest( testFilePath, requiredSize, thumbnailRetrievedCallbackHelper); - ThreadUtils.runOnUiThread(() -> { - mThumbnailProvider.getThumbnail(request); - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mThumbnailProvider.getThumbnail(request); }); thumbnailRetrievedCallbackHelper.waitForCallback( "Reached timeout when fetching a thumbnail for a downloaded image.", 0); @@ -155,9 +152,8 @@ final TestThumbnailRequest request = new TestThumbnailRequest( testFilePath, requiredSize, thumbnailRetrievedCallbackHelper); - ThreadUtils.runOnUiThread(() -> { - mThumbnailProvider.getThumbnail(request); - }); + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { mThumbnailProvider.getThumbnail(request); }); thumbnailRetrievedCallbackHelper.waitForCallback( "Reached timeout when fetching a thumbnail for a downloaded image.", 0);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisherTest.java deleted file mode 100644 index c1b5a78a..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataNotificationPublisherTest.java +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import android.app.NotificationManager; -import android.content.Context; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowNotificationManager; - - -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Feature; - -/** - * Tests for {@link ClearDataNotificationPublisher}. - */ -@RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, - shadows={ ShadowNotificationManager.class }) -public class ClearDataNotificationPublisherTest { - private ClearDataNotificationPublisher mClearDataNotificationPublisher; - private Context mContext; - private ShadowNotificationManager mShadowNotificationManager; - - @Before - public void setUp() { - mClearDataNotificationPublisher = new ClearDataNotificationPublisher(); - mContext = RuntimeEnvironment.application; - mShadowNotificationManager = Shadows.shadowOf((NotificationManager.from(mContext))); - } - - @Test - @Feature("TrustedWebActivities") - public void showNotification() { - mClearDataNotificationPublisher.showClearDataNotification( - mContext, "App", "https://www.example.com/", true); - Assert.assertEquals(1, mShadowNotificationManager.getAllNotifications().size()); - } - - @Test - @Feature("TrustedWebActivities") - public void singleNotificationPerOrigin() { - mClearDataNotificationPublisher.showClearDataNotification( - mContext, "App", "https://www.website.com/", true); - mClearDataNotificationPublisher.showClearDataNotification( - mContext, "App 2", "https://www.website.com/", true); - Assert.assertEquals(1, mShadowNotificationManager.getAllNotifications().size()); - - mClearDataNotificationPublisher.showClearDataNotification( - mContext, "App", "https://www.otherwebsite.com/", true); - Assert.assertEquals(2, mShadowNotificationManager.getAllNotifications().size()); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataServiceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataServiceTest.java deleted file mode 100644 index 5e66f3f..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataServiceTest.java +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.Shadows; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowPendingIntent; - -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Feature; - -/** - * Tests for {@link ClearDataService}. - */ -@RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, - shadows={ ShadowPendingIntent.class }) -public class ClearDataServiceTest { - @Mock public ClearDataNotificationPublisher mNotificationManager; - @Mock public DomainDataCleaner mCleaner; - - private ClearDataService mService; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mService = new ClearDataService(mNotificationManager, mCleaner); - } - - @Test - @Feature("TrustedWebActivities") - public void dismissNotification() { - int notificationId = 12345; - - ShadowPendingIntent intent = Shadows.shadowOf( - ClearDataService.getDismissIntent(RuntimeEnvironment.application, notificationId)); - - mService.onStartCommand(intent.getSavedIntent(), 0, 0); - - verify(mNotificationManager).dismissClearDataNotification(any(), eq(notificationId)); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java index 406211a3..67a85ca 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiverTest.java
@@ -43,7 +43,6 @@ public class ClientAppBroadcastReceiverTest { @Mock public Context mContext; @Mock public ClientAppDataRegister mDataRegister; - @Mock public ClearDataNotificationPublisher mNotificationManager; @Mock public ClientAppBroadcastReceiver.ClearDataStrategy mMockStrategy; private ClientAppBroadcastReceiver mReceiver; @@ -97,36 +96,12 @@ verify(mMockStrategy).execute(any(), any(), eq(id), eq(true)); } - /** Tests we deal with multiple domains well. */ - @Test - @Feature("TrustedWebActivities") - public void notificationStrategyShowsNotification_ForEachDomain() { - mReceiver = new ClientAppBroadcastReceiver( - new ClientAppBroadcastReceiver.NotificationClearDataStrategy(mNotificationManager), - mDataRegister, mock(ChromePreferenceManager.class)); - - int id = 45; - String appName = "App Name 2"; - String domain1 = "example.com"; - String domain2 = "example2.com"; - Set<String> domains = new HashSet<>(Arrays.asList(domain1, domain2)); - - addToRegister(id, appName, domains); - - mReceiver.onReceive(mContext, createMockIntent(id, Intent.ACTION_PACKAGE_FULLY_REMOVED)); - - verify(mNotificationManager).showClearDataNotification( - any(), eq(appName), eq(domain1), eq(true)); - verify(mNotificationManager).showClearDataNotification( - any(), eq(appName), eq(domain2), eq(true)); - } - /** Tests we plumb the correct information to the {@link ClearDataDialogActivity}. */ @Test @Feature("TrustedWebActivities") public void dialogStrategy_ValidIntent() { mReceiver = new ClientAppBroadcastReceiver( - new ClientAppBroadcastReceiver.DialogClearDataStrategy(), mDataRegister, + new ClientAppBroadcastReceiver.ClearDataStrategy(), mDataRegister, mock(ChromePreferenceManager.class)); int id = 67;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/DomainDataCleanerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/DomainDataCleanerTest.java deleted file mode 100644 index 66d61971..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/DomainDataCleanerTest.java +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.browserservices; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.MockitoAnnotations.initMocks; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.stubbing.Answer; -import org.robolectric.annotation.Config; - -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.preferences.website.SiteDataCleaner; -import org.chromium.chrome.browser.preferences.website.Website; -import org.chromium.chrome.browser.preferences.website.WebsiteAddress; -import org.chromium.chrome.browser.preferences.website.WebsitePermissionsFetcher; -import org.chromium.chrome.browser.preferences.website.WebsitePermissionsFetcher.WebsitePermissionsCallback; -import org.chromium.chrome.browser.util.test.ShadowUrlUtilities; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** Tests for {@link DomainDataCleaner}. */ -@RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, shadows = {ShadowUrlUtilities.class}) -public class DomainDataCleanerTest { - private final Map<String, String> mUrlToDomain = new HashMap<>(); - @Mock - private ChromeBrowserInitializer mChromeBrowserInitializer; - @Mock - private SiteDataCleaner mSiteDataCleaner; - @Mock - private WebsitePermissionsFetcher mWebsitePermissionsFetcher; - @Mock - private Runnable mFinishCallback; - - private DomainDataCleaner mCleaner; - - private Collection<Website> mSites; - - @Before - public void setUp() { - initMocks(this); - - doAnswer((Answer<Void>) invocation -> { - Runnable callback = invocation.getArgument(1); - callback.run(); - return null; - }).when(mSiteDataCleaner).clearData(any(), any()); - - doAnswer((Answer<Void>) invocation -> { - WebsitePermissionsCallback callback = invocation.getArgument(0); - callback.onWebsitePermissionsAvailable(mSites); - return null; - }).when(mWebsitePermissionsFetcher).fetchAllPreferences(any()); - - ShadowUrlUtilities.setTestImpl(new ShadowUrlUtilities.TestImpl() { - @Override - public String getDomainAndRegistry(String url, boolean includePrivateRegistries) { - return mUrlToDomain.get(url); - } - }); - - mCleaner = new DomainDataCleaner( - mChromeBrowserInitializer, mSiteDataCleaner, mWebsitePermissionsFetcher); - } - - @After - public void tearDown() { - ShadowUrlUtilities.reset(); - } - - @Test - public void cleansDataOfSingleWebsite() { - mSites = Arrays.asList(makeMockWebsite("http://www.facebook.com", "facebook.com")); - mCleaner.clearData("facebook.com", mFinishCallback); - verifyCleared("http://www.facebook.com"); - verify(mFinishCallback).run(); - } - - @Test - public void cleansDataOfMultipleWebsites() { - mSites = Arrays.asList( - makeMockWebsite("http://www.facebook.com", "facebook.com"), - makeMockWebsite("http://m.facebook.com", "facebook.com"), - makeMockWebsite("http://p.facebook.com", "facebook.com")); - mCleaner.clearData("facebook.com", mFinishCallback); - verifyCleared("http://www.facebook.com"); - verifyCleared("http://m.facebook.com"); - verifyCleared("http://p.facebook.com"); - verify(mFinishCallback).run(); - } - - @Test - public void doesntCleanDataOfIrrelevantWebsites() { - mSites = Arrays.asList( - makeMockWebsite("http://www.google.com", "google.com"), - makeMockWebsite("http://www.twitter.com", "twitter.com")); - mCleaner.clearData("facebook.com", mFinishCallback); - verify(mSiteDataCleaner, never()).clearData(any(), any()); - verify(mFinishCallback).run(); - } - - private Website makeMockWebsite(String origin, String domain) { - Website website = new Website(WebsiteAddress.create(origin), null); - mUrlToDomain.put(origin, domain); - return website; - } - - private void verifyCleared(String origin) { - verify(mSiteDataCleaner) - .clearData(argThat(argument -> argument.getAddress().getOrigin().equals(origin)), - any()); - } -}
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index ad7eb14..00882c1 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-74.0.3725.0_rc-r1-merged.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-75.0.3740.0_rc-r1-merged.afdo.bz2 \ No newline at end of file
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni index 52466dd..5d51e08 100644 --- a/chrome/android/trichrome.gni +++ b/chrome/android/trichrome.gni
@@ -59,11 +59,15 @@ version_name = chrome_version_name version_code = trichrome_version_code - # TODO(torne): using these resources just to get a temporary icon + # TODO(torne): using system_webview_resources just to get a temporary icon deps = [ "//android_webview:system_webview_resources", ] + if (trichrome_shared_assets) { + deps += [ "//third_party/icu:icu_assets" ] + } + # Only try to generate the native library version in configurations that # include a native library. if (!android_64bit_target_cpu || build_apk_secondary_abi) { @@ -89,11 +93,17 @@ secondary_abi_loadable_modules = [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ] } + if (trichrome_shared_assets) { + deps += [ "//android_webview:v8_snapshot_secondary_abi_assets" ] + } } else { shared_libraries = [ "//chrome/android:monochrome" ] deps += [ "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline", ] + if (trichrome_shared_assets) { + deps += [ "//chrome/android:chrome_public_v8_assets" ] + } loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ] }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index a5da442..1b21958 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -91,7 +91,7 @@ #define IDC_WINDOW_MUTE_SITE 35012 #define IDC_WINDOW_PIN_TAB 35013 #define IDC_MIGRATE_LOCAL_CREDIT_CARD_FOR_PAGE 35014 -#define IDC_SEND_TO_MY_DEVICES 35015 +#define IDC_SEND_TAB_TO_SELF 35015 #define IDC_FOCUS_THIS_TAB 35016 // Clipboard commands
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 92acdc8..d747fc4 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -531,6 +531,7 @@ std::string actual_locale = LoadLocalState(chrome_feature_list_creator_.get(), is_running_tests); chrome_feature_list_creator_->SetApplicationLocale(actual_locale); + chrome_feature_list_creator_->OverrideCachedUIStrings(); } bool ChromeMainDelegate::ShouldCreateFeatureList() {
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index 59098e7..5b5844d9 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -691,9 +691,12 @@ <!-- about:browser-switch strings --> <if expr="is_win or is_macosx or (is_linux and not is_chromeos)"> - <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION" desc="Description shown while waiting for an alternative browser to open"> + <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER" desc="Description shown while waiting for an alternative browser to open, when the browser name is not auto-detected"> Your system administrator has configured Chromium to open an alternative browser to access <ph name="TARGET_URL_HOSTNAME">$1<ex>example.com</ex></ph>. </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER" desc="Description shown while waiting for an alternative browser to open, when the browser name is auto-detected"> + Your system administrator has configured Chromium to open <ph name="ALTERNATIVE_BROWSER_NAME">$2<ex>Internet Explorer</ex></ph> to access <ph name="TARGET_URL_HOSTNAME">$1<ex>example.com</ex></ph>. + </message> </if> <!-- Signin Email Confirmation tab modal dialog -->
diff --git a/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 deleted file mode 100644 index 9f7594dc..0000000 --- a/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -aba98673b2ef20b76e483bdc91aebf060c947ad7 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..ad5c028 --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1b0177328e34826d71f6d5d6bf826b982348488d \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1 b/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..cfaeb37 --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1e00800b1f530fd399ef25e381d294eb6a0f1e7a \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 4287585..0ea08a1 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -375,9 +375,6 @@ <message name="IDS_CONTENT_CONTEXT_SAVEPAGEAS" desc="The name of the Save Page As command in the content area context menu"> Save &as... </message> - <message name="IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES" desc="The name of the Send to my devices command in the content area context menu"> - Send to my devices - </message> <message name="IDS_CONTENT_CONTEXT_PRINT" desc="The name of the Print... command in the content area context menu. Brings a dialog to select the print options"> &Print... </message> @@ -599,9 +596,6 @@ <message name="IDS_CONTENT_CONTEXT_SAVEPAGEAS" desc="In Title Case: The name of the Save Page As command in the content area context menu"> Save &As... </message> - <message name="IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES" desc="In Title Case: The name of the Send To My Devices command in the content area context menu"> - Send To My Devices - </message> <message name="IDS_CONTENT_CONTEXT_PRINT" desc="In Title Case: The name of the Print... command in the content area context menu. Brings a dialog to select the print options"> &Print... </message> @@ -4220,6 +4214,11 @@ Extensions running in developer mode can harm your computer. If you're not a developer, you should disable these extensions running in developer mode to stay safe. </message> + <!-- Extensions Menu bubble --> + <message name="IDS_EXTENSIONS_MENU_TITLE" desc="Title of the Extensions Menu"> + Extensions + </message> + <!-- Settings API bubble --> <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their home page setting"> Is this the home page you were expecting? @@ -4734,18 +4733,30 @@ <message name="IDS_ABOUT_BROWSER_SWITCH_TITLE" desc="about:browser-switch page title"> Legacy Browser Support </message> - <message name="IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE" desc="Shown while waiting for an alternative browser to open"> + <message name="IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_UNKNOWN_BROWSER" desc="Shown while waiting for an alternative browser to open, when the browser name is not auto-detected"> Opening in alternative browser now </message> - <message name="IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE" desc="Error message shown when we fail to open the alternative browser"> + <message name="IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_KNOWN_BROWSER" desc="Shown while waiting for an alternative browser to open, when the browser name is auto-detected"> + Opening in <ph name="ALTERNATIVE_BROWSER_NAME">$1<ex>Internet Explorer</ex></ph> now + </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_UNKNOWN_BROWSER" desc="Error message shown when we fail to open the alternative browser, when the browser name is not auto-detected"> The alternative browser could not be opened </message> - <message name="IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE" desc="Shown while waiting for an alternative browser to open, with a countdown timer"> + <message name="IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_KNOWN_BROWSER" desc="Error message shown when we fail to open the alternative browser, when the browser name is auto-detected"> + <ph name="ALTERNATIVE_BROWSER_NAME">$1<ex>Internet Explorer</ex></ph> could not be opened + </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_UNKNOWN_BROWSER" desc="Shown while waiting for an alternative browser to open, with a countdown timer, when the browser name is not auto-detected"> Opening in alternative browser in <ph name="COUNTDOWN_SECONDS">$1<ex>5</ex></ph> seconds </message> - <message name="IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR" desc="Generic error message when we don't know why we failed to open the alternative browser"> + <message name="IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_KNOWN_BROWSER" desc="Shown while waiting for an alternative browser to open, with a countdown timer, when the browser name is auto-detected"> + Opening in <ph name="ALTERNATIVE_BROWSER_NAME">$2<ex>Internet Explorer</ex></ph> in <ph name="COUNTDOWN_SECONDS">$1<ex>5</ex></ph> seconds + </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_UNKNOWN_BROWSER" desc="Generic error message when we don't know why we failed to open the alternative browser, when the browser name is not auto-detected"> <ph name="URL">$1<ex>ftp://example.com/</ex></ph> could not be open in an alternative browser. Please contact your system administrator. </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_KNOWN_BROWSER" desc="Generic error message when we don't know why we failed to open the alternative browser, when the browser name is auto-detected"> + <ph name="URL">$1<ex>ftp://example.com/</ex></ph> could not be open in <ph name="ALTERNATIVE_BROWSER_NAME">$2<ex>Internet Explorer</ex></ph>. Please contact your system administrator. + </message> <message name="IDS_ABOUT_BROWSER_SWITCH_PROTOCOL_ERROR" desc="Specific error message when we failed to open the alternative browser, because the URL is not one of http://, https:// or file://"> Only http, https and file protocols are supported for browser redirects. </message> @@ -4990,6 +5001,9 @@ <message name="IDS_TOOLTIP_STOP" desc="The tooltip for the stop button"> Stop loading this page </message> + <message name="IDS_TOOLTIP_EXTENSIONS_BUTTON" desc="The tooltip for the extensions button"> + Extensions + </message> <if expr="is_macosx"> <message name="IDS_TOOLTIP_CLOSE_TAB" desc="The tooltip for the close tab button"> Close @@ -5449,12 +5463,17 @@ <message name="IDS_FEEDBACK_OFFLINE_DIALOG_TEXT" desc="The content of the message box displayed when the user attempts to send a report while offline"> Thank you for your feedback. You are offline now, and your report will be sent later. </message> - <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX" desc="Checkbox for including system information on the bug report dialog box"> - Send <ph name="BEGIN_LINK1"><a href="#" id="sys-info-url"></ph>system information<ph name="END_LINK1"></a></ph> - </message> + <if expr="not chromeos"> + <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX" desc="Checkbox for including system information on the bug report dialog box"> + Send <ph name="BEGIN_LINK1"><a href="#" id="sys-info-url"></ph>system information<ph name="END_LINK1"></a></ph> + </message> + </if> <if expr="chromeos"> - <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX_ARC" desc="Checkbox for including system, and app information on the bug report dialog box on an ARC enabled device"> - Send <ph name="BEGIN_LINK1"><a href="#" id="sys-info-url"></ph>system and app information<ph name="END_LINK1"></a></ph> + <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX" desc="Checkbox for including system information and metrics on the bug report dialog box"> + Send <ph name="BEGIN_LINK1"><a href="#" id="sys-info-url"></ph>system information<ph name="END_LINK1"></a></ph> and <ph name="BEGIN_LINK2"><a href="#" id="histograms-url"></ph>metrics<ph name="END_LINK2"></a></ph> + </message> + <message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX_ARC" desc="Checkbox for including system, metrics and app information on the bug report dialog box on an ARC enabled device"> + Send <ph name="BEGIN_LINK1"><a href="#" id="sys-info-url"></ph>system and app information<ph name="END_LINK1"></a></ph>, and <ph name="BEGIN_LINK2"><a href="#" id="histograms-url"></ph>metrics<ph name="END_LINK2"></a></ph> </message> </if> <message name="IDS_FEEDBACK_INCLUDE_ASSISTANT_INFORMATION_CHKBOX" desc="Checkbox for including Assistant debug information in the feedback report"> @@ -5808,9 +5827,6 @@ <message name="IDS_TAB_CXMENU_BOOKMARK_ALL_TABS" desc="The label of the tab context menu item for creating a bookmark folder containing an entry for each open tab."> Bookmark all tabs... </message> - <message name="IDS_TAB_CXMENU_SEND_TO_MY_DEVICES" desc="The label of the tab context menu item for share this tab to other devices."> - Send to my devices - </message> <message name="IDS_TAB_CXMENU_ADD_TAB_TO_NEW_GROUP" desc="The label of the tab context menu item for creating a new tab group and adding one or more tabs to it."> Add to new group </message> @@ -5873,9 +5889,6 @@ <message name="IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP" desc="In Title Case: The label of the tab context menu item for removing one or more tabs from the groups that contain them."> Remove From Group </message> - <message name="IDS_TAB_CXMENU_SEND_TO_MY_DEVICES" desc="In Title Case: The label of the tab context menu item for share this tab to other devices."> - Send To My Devices - </message> </if> <!-- Application window menu --> @@ -6222,6 +6235,19 @@ </message> </if> + <!-- Self share item in different context menus. --> + <if expr="not use_titlecase"> + <message name="IDS_CONTEXT_MENU_SEND_TAB_TO_SELF" desc="The label of item for share this tab to other devices in different context menus."> + Send to your devices + </message> + </if> + <if expr="use_titlecase"> + <message name="IDS_CONTEXT_MENU_SEND_TAB_TO_SELF" desc="In Title Case: The label of item for share this tab to other devices in different context menus."> + Send to Your Devices + </message> + </if> + + <!-- Collected cookies window --> <message name="IDS_COLLECTED_COOKIES_DIALOG_TITLE" desc="The title of the collect cookies dialog"> Cookies in use
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_KNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..ad5c028 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1b0177328e34826d71f6d5d6bf826b982348488d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_UNKNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..cfaeb37 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1e00800b1f530fd399ef25e381d294eb6a0f1e7a \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_KNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..5b87934 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +0da48bba241693ac99ad4735cf3297bcc0a09fc8 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_UNKNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..3cc5801 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +dbcebbf7b85bbd02415624761c519bec134ebfb5 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_KNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..5b87934 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +0da48bba241693ac99ad4735cf3297bcc0a09fc8 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_UNKNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..3cc5801 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +dbcebbf7b85bbd02415624761c519bec134ebfb5 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING.png.sha1 deleted file mode 100644 index 9f7594dc..0000000 --- a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -aba98673b2ef20b76e483bdc91aebf060c947ad7 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_KNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..09a74312 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +5fbc50153f3ca1fe5d1ce934f562e78315d4b1ff \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_UNKNOWN_BROWSER.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..cde5ba4 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +9850fc3bb5708ff3c761ef1641a6401fb95752d2 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_TITLE.png.sha1 deleted file mode 100644 index 7f7d3d9..0000000 --- a/chrome/app/generated_resources_grd/IDS_ABOUT_BROWSER_SWITCH_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d6fb2b732de828f3ee1cfb1dd195e9f0c715cea4 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES.png.sha1 b/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES.png.sha1 deleted file mode 100644 index d5619175..0000000 --- a/chrome/app/generated_resources_grd/IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9a3e7b99c1ad9fc1180f07b09f1c3f64f3f7ab02 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CONTEXT_MENU_SEND_TAB_TO_SELF.png.sha1 b/chrome/app/generated_resources_grd/IDS_CONTEXT_MENU_SEND_TAB_TO_SELF.png.sha1 new file mode 100644 index 0000000..969bbc4 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_CONTEXT_MENU_SEND_TAB_TO_SELF.png.sha1
@@ -0,0 +1 @@ +486d7fc8373a3f2b699dd21d753ec5372bb0066a \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX.png.sha1 b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX.png.sha1 new file mode 100644 index 0000000..59d2d7e --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX.png.sha1
@@ -0,0 +1 @@ +bf18f00274d97bbe09707e55fac83c0b80b03ae4 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX_ARC.png.sha1 b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX_ARC.png.sha1 new file mode 100644 index 0000000..7ea69c6 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX_ARC.png.sha1
@@ -0,0 +1 @@ +e895e0c7b1649adc70084e1c97c210f58cc55e3b \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX.png.sha1 b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX.png.sha1 deleted file mode 100644 index 92a82d1..0000000 --- a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -f866d8699472c459f82cd462b8b918ea339ec1ca \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX_ARC.png.sha1 b/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX_ARC.png.sha1 deleted file mode 100644 index 0c15903..0000000 --- a/chrome/app/generated_resources_grd/IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX_ARC.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -771507fb5f1f255fcaea4612bc9c23a8af5ba3ac \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_SEND_TO_MY_DEVICES.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_SEND_TO_MY_DEVICES.png.sha1 deleted file mode 100644 index 194951fc..0000000 --- a/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_SEND_TO_MY_DEVICES.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -881e284a6f73a0b8acd1a1a4049848ba75355f62 \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 99bf2122..cf0de83 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -702,9 +702,12 @@ <!-- about:browser-switch strings --> <if expr="is_win or is_macosx or (is_linux and not is_chromeos)"> - <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION" desc="Description shown while waiting for an alternative browser to open"> + <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER" desc="Description shown while waiting for an alternative browser to open, when the browser name is not auto-detected"> Your system administrator has configured Google Chrome to open an alternative browser to access <ph name="TARGET_URL_HOSTNAME">$1<ex>example.com</ex></ph>. </message> + <message name="IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER" desc="Description shown while waiting for an alternative browser to open, when the browser name is auto-detected"> + Your system administrator has configured Google Chrome to open <ph name="ALTERNATIVE_BROWSER_NAME">$2<ex>Internet Explorer</ex></ph> to access <ph name="TARGET_URL_HOSTNAME">$1<ex>example.com</ex></ph>. + </message> </if> <!-- Signin Email Confirmation tab modal dialog -->
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 deleted file mode 100644 index 9f7594dc..0000000 --- a/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -aba98673b2ef20b76e483bdc91aebf060c947ad7 \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..ad5c028 --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1b0177328e34826d71f6d5d6bf826b982348488d \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1 new file mode 100644 index 0000000..cfaeb37 --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER.png.sha1
@@ -0,0 +1 @@ +1e00800b1f530fd399ef25e381d294eb6a0f1e7a \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 2596575..b488fc2 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1436,6 +1436,9 @@ <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_DONE_MESSAGE" desc="The message shown when a new printer is set up successfully."> Added <ph name="PRINTER_NAME">$1<ex>printer</ex></ph> </message> + <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_EDITED_PRINTER_DONE_MESSAGE" desc="The message shown when a printer is updated successfully."> + Updated <ph name="PRINTER_NAME">$1<ex>printer</ex></ph> + </message> <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_PRINTER_NEARBY" desc="The no-printer-found message shown in the auto discovery dialog."> No printers nearby </message> @@ -1932,6 +1935,9 @@ <message name="IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT" desc="Settings > Internet > Network details: Label for the checkbox determining whether to automatically connect to the network."> Automatically connect to this network </message> + <message name="IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT_CELLULAR" desc="Settings > Internet > Mobile Data details: Label for the checkbox determining whether to automatically connect to the cellular network."> + Automatically connect to cellular network + </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_ALWAYS_ON_VPN" desc="Settings > Internet > Network details: Label for the checkbox determining that all internet traffic has to go through this VPN (virtual private network), and all other network connections are blocked."> Always connect through this VPN </message>
diff --git a/chrome/app_shim/app_shim_controller.h b/chrome/app_shim/app_shim_controller.h index 8f8195c..c5b915e 100644 --- a/chrome/app_shim/app_shim_controller.h +++ b/chrome/app_shim/app_shim_controller.h
@@ -5,12 +5,15 @@ #ifndef CHROME_APP_SHIM_APP_SHIM_CONTROLLER_H_ #define CHROME_APP_SHIM_APP_SHIM_CONTROLLER_H_ +#import <AppKit/AppKit.h> + #include "base/files/file_path.h" #include "base/mac/scoped_nsobject.h" #include "chrome/common/mac/app_mode_common.h" #include "chrome/common/mac/app_shim.mojom.h" #include "chrome/common/mac/app_shim_param_traits.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" #include "mojo/public/cpp/system/isolated_connection.h" @class AppShimDelegate; @@ -19,20 +22,11 @@ // process, and generally controls the lifetime of the app shim process. class AppShimController : public chrome::mojom::AppShim { public: - explicit AppShimController(const app_mode::ChromeAppModeInfo* app_mode_info); + explicit AppShimController( + const app_mode::ChromeAppModeInfo* app_mode_info, + base::scoped_nsobject<NSRunningApplication> chrome_running_app); ~AppShimController() override; - // Called when the main Chrome process responds to the Apple Event ping that - // was sent, or when the ping fails (if |success| is false). - void OnPingChromeReply(bool success); - - // Called |kPingChromeTimeoutSeconds| after startup, to allow a timeout on the - // ping event to be detected. - void OnPingChromeTimeout(); - - // Connects to Chrome and sends a LaunchApp message. - void InitBootstrapPipe(); - chrome::mojom::AppShimHost* host() const { return host_.get(); } // Called when the app is activated, e.g. by clicking on it in the dock, by @@ -42,8 +36,8 @@ const std::vector<base::FilePath>& files); private: - // Create a channel from |socket_path| and send a LaunchApp message. - void CreateChannelAndSendLaunchApp(const base::FilePath& socket_path); + // Create a channel from the Mojo |endpoint| and send a LaunchApp message. + void CreateChannelAndSendLaunchApp(mojo::PlatformChannelEndpoint endpoint); // Builds main menu bar items. void SetUpMenu(); void ChannelError(uint32_t custom_reason, const std::string& description); @@ -66,7 +60,15 @@ // Terminates the app shim process. void Close(); + // Connects to Chrome and sends a LaunchApp message. + void InitBootstrapPipe(); + + // Check to see if Chrome's AppShimHostManager has been initialized. If it + // has, then connect. + void PollForChromeReady(const base::TimeDelta& time_until_timeout); + const app_mode::ChromeAppModeInfo* const app_mode_info_; + base::scoped_nsobject<NSRunningApplication> chrome_running_app_; mojo::IsolatedConnection bootstrap_mojo_connection_; chrome::mojom::AppShimHostBootstrapPtr host_bootstrap_; @@ -77,7 +79,6 @@ base::scoped_nsobject<AppShimDelegate> delegate_; bool launch_app_done_; - bool ping_chrome_reply_received_; NSInteger attention_request_id_; DISALLOW_COPY_AND_ASSIGN(AppShimController);
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm index c5a655b..4a17f7b 100644 --- a/chrome/app_shim/app_shim_controller.mm +++ b/chrome/app_shim/app_shim_controller.mm
@@ -5,11 +5,16 @@ #include "chrome/app_shim/app_shim_controller.h" #import <Cocoa/Cocoa.h> +#include <mach/message.h> + #include <utility> #include "base/bind.h" #include "base/command_line.h" #include "base/files/file_util.h" +#include "base/mac/foundation_util.h" +#include "base/mac/mach_logging.h" +#include "base/md5.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app_shim/app_shim_delegate.h" @@ -19,26 +24,44 @@ #include "content/public/browser/ns_view_bridge_factory_impl.h" #include "content/public/common/ns_view_bridge_factory.mojom.h" #include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/platform/features.h" #include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views_bridge_mac/bridge_factory_impl.h" #include "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h" +namespace { +// The maximum amount of time to wait for Chrome's AppShimHostManager to be +// ready. +constexpr base::TimeDelta kPollTimeoutSeconds = + base::TimeDelta::FromSeconds(60); + +// The period in between attempts to check of Chrome's AppShimHostManager is +// ready. +constexpr base::TimeDelta kPollPeriodMsec = + base::TimeDelta::FromMilliseconds(100); +} // namespace + AppShimController::AppShimController( - const app_mode::ChromeAppModeInfo* app_mode_info) + const app_mode::ChromeAppModeInfo* app_mode_info, + base::scoped_nsobject<NSRunningApplication> chrome_running_app) : app_mode_info_(app_mode_info), + chrome_running_app_(chrome_running_app), shim_binding_(this), host_request_(mojo::MakeRequest(&host_)), delegate_([[AppShimDelegate alloc] init]), launch_app_done_(false), - ping_chrome_reply_received_(false), attention_request_id_(0) { // Since AppShimController is created before the main message loop starts, // NSApp will not be set, so use sharedApplication. NSApplication* sharedApplication = [NSApplication sharedApplication]; [sharedApplication setDelegate:delegate_]; + + // Start polling to see if Chrome is ready to connect. + PollForChromeReady(kPollTimeoutSeconds); } AppShimController::~AppShimController() { @@ -47,19 +70,36 @@ [sharedApplication setDelegate:nil]; } -void AppShimController::OnPingChromeReply(bool success) { - ping_chrome_reply_received_ = true; - if (!success) { - [NSApp terminate:nil]; +void AppShimController::PollForChromeReady( + const base::TimeDelta& time_until_timeout) { + // If the Chrome application we planned to connect to is not running, quit. + if ([chrome_running_app_ isTerminated]) + LOG(FATAL) << "Running chrome instance terminated before connecting."; + + // Check to see if the app shim socket symlink path exists. If it does, then + // we know that the AppShimHostManager is listening in the browser process, + // and we can connect. + base::FilePath user_data_dir = base::FilePath(app_mode_info_->user_data_dir) + .DirName() + .DirName() + .DirName(); + CHECK(!user_data_dir.empty()); + base::FilePath symlink_path = + user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); + if (base::PathExists(symlink_path)) { + InitBootstrapPipe(); return; } - InitBootstrapPipe(); -} - -void AppShimController::OnPingChromeTimeout() { - if (!ping_chrome_reply_received_) - [NSApp terminate:nil]; + // Otherwise, try again after a brief delay. + if (time_until_timeout < kPollPeriodMsec) + LOG(FATAL) << "Timed out waiting for running chrome instance to be ready."; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AppShimController::PollForChromeReady, + base::Unretained(this), + time_until_timeout - kPollPeriodMsec), + kPollPeriodMsec); } void AppShimController::InitBootstrapPipe() { @@ -76,23 +116,68 @@ .DirName(); CHECK(!user_data_dir.empty()); - base::FilePath symlink_path = - user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); - base::FilePath socket_path; - if (base::ReadSymbolicLink(symlink_path, &socket_path)) { - app_mode::VerifySocketPermissions(socket_path); - CreateChannelAndSendLaunchApp(socket_path); + mojo::PlatformChannelEndpoint endpoint; + + // Check for the signal file. If this file is present, then Chrome is running + // with features::kMojoChannelMac and the app shim needs to connect over + // Mach IPC. The FeatureList also needs to be initialized with that on, so + // Mojo internals use the right transport mechanism. + base::FilePath mojo_channel_mac_signal_file = + user_data_dir.Append(app_mode::kMojoChannelMacSignalFile); + if (base::PathExists(mojo_channel_mac_signal_file)) { + base::FeatureList::InitializeInstance(mojo::features::kMojoChannelMac.name, + std::string()); + std::string name_fragment = + base::StringPrintf("%s.%s.%s", base::mac::BaseBundleID(), + app_mode::kAppShimBootstrapNameFragment, + base::MD5String(user_data_dir.value()).c_str()); + + // Normally NamedPlatformChannel is used for point-to-point peer + // communication. For apps shims, the same server is used to establish + // connections between multiple shim clients and the server. To do this, + // the shim creates a local PlatformChannel and sends the local (send) + // endpoint to the server in a raw Mach message. The server uses that to + // establish an IsolatedConnection, which the client does as well with the + // remote (receive) end. + mojo::PlatformChannelEndpoint server_endpoint = + mojo::NamedPlatformChannel::ConnectToServer(name_fragment); + mojo::PlatformChannel channel; + mach_msg_base_t message{}; + message.header.msgh_id = app_mode::kBootstrapMsgId; + message.header.msgh_bits = + MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND); + message.header.msgh_size = sizeof(message); + message.header.msgh_local_port = + channel.TakeLocalEndpoint().TakePlatformHandle().ReleaseMachSendRight(); + message.header.msgh_remote_port = + server_endpoint.TakePlatformHandle().ReleaseMachSendRight(); + kern_return_t kr = mach_msg_send(&message.header); + if (kr != KERN_SUCCESS) { + MACH_LOG(ERROR, kr) << "mach_msg_send"; + return; + } + endpoint = channel.TakeRemoteEndpoint(); } else { - // The path in the user data dir is not a symlink, try connecting directly. - CreateChannelAndSendLaunchApp(symlink_path); + base::FilePath symlink_path = + user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); + base::FilePath socket_path; + if (base::ReadSymbolicLink(symlink_path, &socket_path)) { + app_mode::VerifySocketPermissions(socket_path); + } else { + // The path in the user data dir is not a symlink, try connecting + // directly. + socket_path = symlink_path; + } + endpoint = mojo::NamedPlatformChannel::ConnectToServer(socket_path.value()); } + + CreateChannelAndSendLaunchApp(std::move(endpoint)); } void AppShimController::CreateChannelAndSendLaunchApp( - const base::FilePath& socket_path) { + mojo::PlatformChannelEndpoint endpoint) { mojo::ScopedMessagePipeHandle message_pipe = - bootstrap_mojo_connection_.Connect( - mojo::NamedPlatformChannel::ConnectToServer(socket_path.value())); + bootstrap_mojo_connection_.Connect(std::move(endpoint)); CHECK(message_pipe.is_valid()); host_bootstrap_ = chrome::mojom::AppShimHostBootstrapPtr( chrome::mojom::AppShimHostBootstrapPtrInfo(std::move(message_pipe), 0));
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm index a770ab4..16d7497 100644 --- a/chrome/app_shim/chrome_main_app_mode_mac.mm +++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -1,7 +1,6 @@ // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - // On Mac, one can't make shortcuts with command-line arguments. Instead, we // produce small app bundles which locate the Chromium framework and load it, // passing the appropriate data. This is the entry point into the framework for @@ -40,15 +39,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -namespace { - -// Timeout in seconds to wait for a reply for the initial Apple Event. Note that -// kAEDefaultTimeout on Mac is "about one minute" according to Apple's -// documentation, but is no longer supported for asynchronous Apple Events. -const int kPingChromeTimeoutSeconds = 60; - -} // namespace - // The NSApplication for app shims is a vanilla NSApplication, but sub-class it // so that we can DCHECK that we know precisely when it is initialized. @interface AppShimApplication : NSApplication @@ -57,107 +47,6 @@ @implementation AppShimApplication @end -// A ReplyEventHandler is a helper class to send an Apple Event to a process -// and call a callback when the reply returns. -// -// This is used to 'ping' the main Chrome process -- once Chrome has sent back -// an Apple Event reply, it's guaranteed that it has opened the IPC channel -// that the app shim will connect to. -@interface ReplyEventHandler : NSObject { - base::Callback<void(bool)> onReply_; - AEDesc replyEvent_; -} -// Sends an Apple Event to the process identified by the bundle identifier, -// and calls |replyFn| when the reply is received. Internally this -// creates a ReplyEventHandler, which will delete itself once the reply event -// has been received. -+ (void)pingProcessAndCall:(base::Callback<void(bool)>)replyFn; -@end - -@interface ReplyEventHandler (PrivateMethods) -// Initialise the reply event handler. Doesn't register any handlers until -// |-pingProcess:| is called. |replyFn| is the function to be called when the -// Apple Event reply arrives. -- (id)initWithCallback:(base::Callback<void(bool)>)replyFn; - -// Sends an Apple Event ping to the process identified by the bundle -// identifier and registers to listen for a reply. -- (void)pingProcess; - -// Called when a response is received from the target process for the ping sent -// by |-pingProcess:|. -- (void)message:(NSAppleEventDescriptor*)event - withReply:(NSAppleEventDescriptor*)reply; - -// Calls |onReply_|, passing it |success| to specify whether the ping was -// successful. -- (void)closeWithSuccess:(bool)success; -@end - -@implementation ReplyEventHandler -+ (void)pingProcessAndCall:(base::Callback<void(bool)>)replyFn { - // The object will release itself when the reply arrives, or possibly earlier - // if an unrecoverable error occurs. - ReplyEventHandler* handler = - [[ReplyEventHandler alloc] initWithCallback:replyFn]; - [handler pingProcess]; -} -@end - -@implementation ReplyEventHandler (PrivateMethods) -- (id)initWithCallback:(base::Callback<void(bool)>)replyFn { - if ((self = [super init])) { - onReply_ = replyFn; - } - return self; -} - -- (void)pingProcess { - // Register the reply listener. - NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; - [em setEventHandler:self - andSelector:@selector(message:withReply:) - forEventClass:kCoreEventClass - andEventID:kAEAnswer]; - - // Craft the Apple Event to send. - NSString* chromeBundleId = [base::mac::OuterBundle() bundleIdentifier]; - NSAppleEventDescriptor* target = [NSAppleEventDescriptor - descriptorWithDescriptorType:typeApplicationBundleID - data:[chromeBundleId - dataUsingEncoding:NSUTF8StringEncoding]]; - - NSAppleEventDescriptor* initialEvent = [NSAppleEventDescriptor - appleEventWithEventClass:app_mode::kAEChromeAppClass - eventID:app_mode::kAEChromeAppPing - targetDescriptor:target - returnID:kAutoGenerateReturnID - transactionID:kAnyTransactionID]; - - // Note that AESendMessage effectively ignores kAEDefaultTimeout, because this - // call does not pass kAEWantReceipt (which is deprecated and unsupported on - // Mac). Instead, rely on OnPingChromeTimeout(). - OSStatus status = AESendMessage([initialEvent aeDesc], &replyEvent_, - kAEQueueReply, kAEDefaultTimeout); - if (status != noErr) { - OSSTATUS_LOG(ERROR, status) << "AESendMessage"; - [self closeWithSuccess:false]; - } -} - -- (void)message:(NSAppleEventDescriptor*)event - withReply:(NSAppleEventDescriptor*)reply { - [self closeWithSuccess:true]; -} - -- (void)closeWithSuccess:(bool)success { - onReply_.Run(success); - NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; - [em removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEAnswer]; - [self release]; -} -@end - extern "C" { // |ChromeAppModeStart()| is the point of entry into the framework from the app @@ -252,20 +141,33 @@ io_thread->task_runner(), mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST); - // Find already running instances of Chrome. - pid_t pid = -1; - std::string chrome_process_id = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - app_mode::kLaunchedByChromeProcessId); - if (!chrome_process_id.empty()) { - if (!base::StringToInt(chrome_process_id, &pid)) - LOG(FATAL) << "Invalid PID: " << chrome_process_id; - } else { + base::scoped_nsobject<NSRunningApplication> chrome_running_app; + + // If this shim was launched by Chrome, open that specified process. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + app_mode::kLaunchedByChromeProcessId)) { + std::string chrome_pid_string = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + app_mode::kLaunchedByChromeProcessId); + int chrome_pid; + if (!base::StringToInt(chrome_pid_string, &chrome_pid)) + LOG(FATAL) << "Invalid PID: " << chrome_pid_string; + + chrome_running_app.reset([NSRunningApplication + runningApplicationWithProcessIdentifier:chrome_pid]); + if (!chrome_running_app) + LOG(FATAL) << "Failed open process with PID: " << chrome_pid; + } + + // Find an already running instance of Chrome to open, if one exists. + if (!chrome_running_app) { NSString* chrome_bundle_id = [base::mac::OuterBundle() bundleIdentifier]; NSArray* existing_chrome = [NSRunningApplication runningApplicationsWithBundleIdentifier:chrome_bundle_id]; - if ([existing_chrome count] > 0) - pid = [[existing_chrome objectAtIndex:0] processIdentifier]; + if ([existing_chrome count] > 0) { + chrome_running_app.reset([existing_chrome objectAtIndex:0], + base::scoped_policy::RETAIN); + } } // Initialize the NSApplication (and ensure that it was not previously @@ -276,7 +178,6 @@ base::MessageLoopForUI main_message_loop; ui::WindowResizeHelperMac::Get()->Init(main_message_loop.task_runner()); base::PlatformThread::SetName("CrAppShimMain"); - AppShimController controller(info); // TODO(https://crbug.com/925998): This workaround ensures that there is // always delayed work enqueued. If there is ever not enqueued delayed work, @@ -286,11 +187,10 @@ // the relevant message pump code. PostRepeatingDelayedTask(); - // In tests, launching Chrome does nothing, and we won't get a ping response, - // so just assume the socket exists. - if (pid == -1 && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - app_mode::kLaunchedForTest)) { + // If Chrome is not running, launch it. In tests, launching Chrome does + // nothing, so just assume the socket exists. + if (!chrome_running_app && !base::CommandLine::ForCurrentProcess()->HasSwitch( + app_mode::kLaunchedForTest)) { // Launch Chrome if it isn't already running. base::CommandLine command_line(base::CommandLine::NO_PROGRAM); command_line.AppendSwitch(switches::kSilentLaunch); @@ -304,34 +204,13 @@ base::FilePath(info->profile_dir)); } - NSRunningApplication* running_app = base::mac::OpenApplicationWithPath( - base::mac::OuterBundlePath(), command_line, NSWorkspaceLaunchDefault); - if (!running_app) - return 1; - - base::Callback<void(bool)> on_ping_chrome_reply = base::Bind( - &AppShimController::OnPingChromeReply, base::Unretained(&controller)); - - // This code abuses the fact that Apple Events sent before the process is - // fully initialized don't receive a reply until its run loop starts. Once - // the reply is received, Chrome will have opened its IPC port, guaranteed. - [ReplyEventHandler pingProcessAndCall:on_ping_chrome_reply]; - - main_message_loop.task_runner()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&AppShimController::OnPingChromeTimeout, - base::Unretained(&controller)), - base::TimeDelta::FromSeconds(kPingChromeTimeoutSeconds)); - } else { - // Chrome already running. Proceed to init. This could still fail if Chrome - // is still starting up or shutting down, but the process will exit quickly, - // which is preferable to waiting for the Apple Event to timeout after one - // minute. - main_message_loop.task_runner()->PostTask( - FROM_HERE, base::BindOnce(&AppShimController::InitBootstrapPipe, - base::Unretained(&controller))); + chrome_running_app.reset(base::mac::OpenApplicationWithPath( + base::mac::OuterBundlePath(), command_line, NSWorkspaceLaunchDefault)); + if (!chrome_running_app) + LOG(FATAL) << "Failed launch Chrome."; } + AppShimController controller(info, chrome_running_app); base::RunLoop().Run(); return 0; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 395095cb..4aef7c16 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -784,6 +784,8 @@ "metrics/google_update_metrics_provider_win.h", "metrics/https_engagement_metrics_provider.cc", "metrics/https_engagement_metrics_provider.h", + "metrics/incognito_observer.cc", + "metrics/incognito_observer.h", "metrics/jumplist_metrics_win.cc", "metrics/jumplist_metrics_win.h", "metrics/live_tab_count_metrics.cc", @@ -1373,7 +1375,6 @@ "profiles/profile_manager.h", "profiles/profile_metrics.cc", "profiles/profile_metrics.h", - "profiles/profile_metrics_mac.mm", "profiles/profile_shortcut_manager_win.cc", "profiles/profile_shortcut_manager_win.h", "profiles/profiles_state.cc", @@ -1969,6 +1970,7 @@ "//components/update_client", "//components/upload_list", "//components/url_formatter", + "//components/url_formatter/top_domains:top500_domains", "//components/url_formatter/top_domains:top500_domains_header", "//components/url_matcher", "//components/user_prefs", @@ -3424,7 +3426,6 @@ deps += [ "//ash/public/cpp", "//chrome/browser/chromeos", - "//chrome/browser/chromeos/kiosk_next_home", "//chrome/browser/chromeos/kiosk_next_home/mojom", "//chromeos/services/assistant/public:feature_flags", "//chromeos/services/device_sync",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index dffba63f..1d05c199 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -198,8 +198,6 @@ "+third_party/blink/public/platform/modules/installation/installation.mojom.h", "+third_party/blink/public/platform/modules/installedapp/installed_app_provider.mojom.h", "+third_party/blink/public/platform/modules/presentation/presentation.mojom.h", - "+third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h", - "+third_party/blink/public/web/window_features.mojom.h", # The following restrictions are for ChromeOS and in particular mus/mash where # Ozone does not run in process. If the linux build transitions to Ozone then
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index a9d49f1d..4a267466 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1182,6 +1182,9 @@ {"extension-apis", flag_descriptions::kExperimentalExtensionApisName, flag_descriptions::kExperimentalExtensionApisDescription, kOsDesktop, SINGLE_VALUE_TYPE(extensions::switches::kEnableExperimentalExtensionApis)}, + {"extensions-toolbar-menu", flag_descriptions::kExtensionsToolbarMenuName, + flag_descriptions::kExtensionsToolbarMenuDescription, kOsDesktop, + FEATURE_VALUE_TYPE(features::kExtensionsToolbarMenu)}, {"extensions-on-chrome-urls", flag_descriptions::kExtensionsOnChromeUrlsName, flag_descriptions::kExtensionsOnChromeUrlsDescription, kOsAll, @@ -3780,6 +3783,10 @@ flag_descriptions::kDelegateOverscrollSwipesName, flag_descriptions::kDelegateOverscrollSwipesDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kDelegateOverscrollSwipes)}, + {"draw-vertically-edge-to-edge", + flag_descriptions::kDrawVerticallyEdgeToEdgeName, + flag_descriptions::kDrawVerticallyEdgeToEdgeDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kDrawVerticallyEdgeToEdge)}, {"translate-android-manual-trigger", flag_descriptions::kTranslateAndroidManualTriggerName, flag_descriptions::kTranslateAndroidManualTriggerDescription, kOsAndroid,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 5ce1999b..13631ba9 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -163,21 +163,21 @@ case AutofillAssistantState::STARTING: SetOverlayState(OverlayState::FULL); AllowShowingSoftKeyboard(false); - SetProgressPulsingEnabled(false); + SetSpinPoodle(true); SetAllowSwipingSheet(true); return; case AutofillAssistantState::RUNNING: SetOverlayState(OverlayState::FULL); AllowShowingSoftKeyboard(false); - SetProgressPulsingEnabled(false); + SetSpinPoodle(true); SetAllowSwipingSheet(true); return; case AutofillAssistantState::AUTOSTART_FALLBACK_PROMPT: SetOverlayState(OverlayState::HIDDEN); AllowShowingSoftKeyboard(true); - SetProgressPulsingEnabled(true); + SetSpinPoodle(false); // user interaction is needed. ExpandBottomSheet(); @@ -186,7 +186,7 @@ case AutofillAssistantState::PROMPT: SetOverlayState(OverlayState::PARTIAL); AllowShowingSoftKeyboard(true); - SetProgressPulsingEnabled(true); + SetSpinPoodle(false); SetAllowSwipingSheet(ui_delegate_->GetPaymentRequestOptions() == nullptr); // user interaction is needed. @@ -196,14 +196,14 @@ case AutofillAssistantState::MODAL_DIALOG: SetOverlayState(OverlayState::FULL); AllowShowingSoftKeyboard(true); - SetProgressPulsingEnabled(false); + SetSpinPoodle(true); SetAllowSwipingSheet(true); return; case AutofillAssistantState::STOPPED: SetOverlayState(OverlayState::HIDDEN); AllowShowingSoftKeyboard(true); - SetProgressPulsingEnabled(false); + SetSpinPoodle(false); SetAllowSwipingSheet(true); // make sure user sees the error message. @@ -249,9 +249,9 @@ java_object_); } -void UiControllerAndroid::SetProgressPulsingEnabled(bool enabled) { - Java_AssistantHeaderModel_setProgressPulsingEnabled( - AttachCurrentThread(), GetHeaderModel(), enabled); +void UiControllerAndroid::SetSpinPoodle(bool enabled) { + Java_AssistantHeaderModel_setSpinPoodle(AttachCurrentThread(), + GetHeaderModel(), enabled); } void UiControllerAndroid::SetAllowSwipingSheet(bool allow) {
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index a1b11e5..73aba90c 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -139,7 +139,7 @@ void SetOverlayState(OverlayState state); void AllowShowingSoftKeyboard(bool enabled); void ExpandBottomSheet(); - void SetProgressPulsingEnabled(bool enabled); + void SetSpinPoodle(bool enabled); void SetAllowSwipingSheet(bool allow); std::string GetDebugContext(); void DestroySelf();
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index 8e9f6f8..e81b9ed 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -130,6 +130,7 @@ &kDownloadHomeV2, &kDownloadHomeShowStorageInfo, &kDownloadRename, + &kDrawVerticallyEdgeToEdge, &kEphemeralTab, &kExploreSites, &kHandleMediaIntents, @@ -350,6 +351,9 @@ const base::Feature kDelegateOverscrollSwipes{ "DelegateOverscrollSwipes", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDrawVerticallyEdgeToEdge{ + "DrawVerticallyEdgeToEdge", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kDownloadAutoResumptionThrottling{ "DownloadAutoResumptionThrottling", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 51f7467..f1e02d7 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -59,6 +59,7 @@ extern const base::Feature kDownloadHomeV2; extern const base::Feature kDownloadHomeShowStorageInfo; extern const base::Feature kDownloadRename; +extern const base::Feature kDrawVerticallyEdgeToEdge; extern const base::Feature kEphemeralTab; extern const base::Feature kExploreSites; extern const base::Feature kForegroundNotificationManager;
diff --git a/chrome/browser/android/compositor/compositor_view.cc b/chrome/browser/android/compositor/compositor_view.cc index 3426fa40..e66b857 100644 --- a/chrome/browser/android/compositor/compositor_view.cc +++ b/chrome/browser/android/compositor/compositor_view.cc
@@ -91,6 +91,12 @@ root_layer_->SetIsDrawable(true); root_layer_->SetBackgroundColor(SK_ColorWHITE); + + surface_control_feature_checker_ = content::GpuFeatureChecker::Create( + gpu::GpuFeatureType::GPU_FEATURE_TYPE_ANDROID_SURFACE_CONTROL, + base::Bind(&CompositorView::OnSurfaceControlFeatureStatusUpdate, + weak_factory_.GetWeakPtr())); + surface_control_feature_checker_->CheckGpuFeatureAvailability(); } CompositorView::~CompositorView() { @@ -144,6 +150,15 @@ return compositor_ ? &compositor_->GetUIResourceProvider() : nullptr; } +void CompositorView::OnSurfaceControlFeatureStatusUpdate(bool available) { + if (available) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_CompositorView_notifyWillUseSurfaceControl(env, obj_); + } + + surface_control_feature_checker_.reset(); +} + void CompositorView::SurfaceCreated(JNIEnv* env, const JavaParamRef<jobject>& object) { compositor_->SetRootLayer(root_layer_);
diff --git a/chrome/browser/android/compositor/compositor_view.h b/chrome/browser/android/compositor/compositor_view.h index 6a68ac7..c248cc1 100644 --- a/chrome/browser/android/compositor/compositor_view.h +++ b/chrome/browser/android/compositor/compositor_view.h
@@ -15,6 +15,7 @@ #include "cc/resources/ui_resource_client.h" #include "content/public/browser/android/compositor_client.h" #include "content/public/browser/browser_child_process_observer.h" +#include "content/public/browser/gpu_feature_checker.h" #include "third_party/skia/include/core/SkColor.h" namespace cc { @@ -102,6 +103,7 @@ const content::ChildProcessTerminationInfo& info) override; void SetBackground(bool visible, SkColor color); + void OnSurfaceControlFeatureStatusUpdate(bool available); base::android::ScopedJavaGlobalRef<jobject> obj_; std::unique_ptr<content::Compositor> compositor_; @@ -116,6 +118,8 @@ int content_height_; bool overlay_video_mode_; + scoped_refptr<content::GpuFeatureChecker> surface_control_feature_checker_; + base::WeakPtrFactory<CompositorView> weak_factory_; DISALLOW_COPY_AND_ASSIGN(CompositorView);
diff --git a/chrome/browser/android/feed/feed_debugging_bridge.cc b/chrome/browser/android/feed/feed_debugging_bridge.cc index bb259795..89a455fcf 100644 --- a/chrome/browser/android/feed/feed_debugging_bridge.cc +++ b/chrome/browser/android/feed/feed_debugging_bridge.cc
@@ -24,4 +24,9 @@ return ConvertJavaStringToUTF8(env, j_string); } +void TriggerRefreshForDebugging() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_FeedDebuggingBridge_triggerRefresh(env); +} + } // namespace feed
diff --git a/chrome/browser/android/feed/feed_debugging_bridge.h b/chrome/browser/android/feed/feed_debugging_bridge.h index bace944..daf587e6 100644 --- a/chrome/browser/android/feed/feed_debugging_bridge.h +++ b/chrome/browser/android/feed/feed_debugging_bridge.h
@@ -17,6 +17,8 @@ std::string GetFeedProcessScopeDumpForDebugging(); +void TriggerRefreshForDebugging(); + } // namespace feed #endif // CHROME_BROWSER_ANDROID_FEED_FEED_DEBUGGING_BRIDGE_H_
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc index 51a2ddb..76be59e3 100644 --- a/chrome/browser/android/webapk/webapk_installer.cc +++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -41,7 +41,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/storage_partition.h" -#include "content/public/common/manifest_util.h" #include "jni/WebApkInstaller_jni.h" #include "net/base/load_flags.h" #include "net/http/http_status_code.h" @@ -49,6 +48,7 @@ #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/resource_response_info.h" #include "services/network/public/cpp/simple_url_loader.h" +#include "third_party/blink/public/common/manifest/manifest_util.h" #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/codec/png_codec.h" #include "url/gurl.h" @@ -203,9 +203,9 @@ web_app_manifest->set_short_name(base::UTF16ToUTF8(shortcut_info.short_name)); web_app_manifest->set_start_url(shortcut_info.url.spec()); web_app_manifest->set_orientation( - content::WebScreenOrientationLockTypeToString(shortcut_info.orientation)); + blink::WebScreenOrientationLockTypeToString(shortcut_info.orientation)); web_app_manifest->set_display_mode( - content::WebDisplayModeToString(shortcut_info.display)); + blink::WebDisplayModeToString(shortcut_info.display)); web_app_manifest->set_background_color( OptionalSkColorToString(shortcut_info.background_color)); web_app_manifest->set_theme_color(
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc index 3e0f489..d512411 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.cc +++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -16,12 +16,68 @@ namespace apps { +AppServiceProxy::InnerIconLoader::InnerIconLoader(AppServiceProxy* host) + : host_(host), overriding_icon_loader_for_testing_(nullptr) {} + +apps::mojom::IconKeyPtr AppServiceProxy::InnerIconLoader::GetIconKey( + const std::string& app_id) { + if (overriding_icon_loader_for_testing_) { + return overriding_icon_loader_for_testing_->GetIconKey(app_id); + } + + apps::mojom::IconKeyPtr icon_key; + if (host_->app_service_.is_bound()) { + host_->cache_.ForOneApp(app_id, [&icon_key](const apps::AppUpdate& update) { + icon_key = update.IconKey(); + }); + } + return icon_key; +} + +std::unique_ptr<IconLoader::Releaser> +AppServiceProxy::InnerIconLoader::LoadIconFromIconKey( + apps::mojom::IconKeyPtr icon_key, + apps::mojom::IconCompression icon_compression, + int32_t size_hint_in_dip, + bool allow_placeholder_icon, + apps::mojom::Publisher::LoadIconCallback callback) { + if (overriding_icon_loader_for_testing_) { + return overriding_icon_loader_for_testing_->LoadIconFromIconKey( + std::move(icon_key), icon_compression, size_hint_in_dip, + allow_placeholder_icon, std::move(callback)); + } + + if (host_->app_service_.is_bound() && icon_key) { + // TODO(crbug.com/826982): wrap another IconLoader that coalesces multiple + // in-flight calls with the same IconLoader::Key, and use it here. + // + // Possibly related to that, Mojo doesn't guarantee the order of messages, + // so multiple calls to this method might not resolve their callbacks in + // order. As per khmel@, "you may have race here, assume you publish change + // for the app and app requested new icon. But new icon is not delivered + // yet and you resolve old one instead. Now new icon arrives asynchronously + // but you no longer notify the app or do?" + host_->app_service_->LoadIcon(std::move(icon_key), icon_compression, + size_hint_in_dip, allow_placeholder_icon, + std::move(callback)); + } else { + std::move(callback).Run(apps::mojom::IconValue::New()); + } + return nullptr; +} + // static AppServiceProxy* AppServiceProxy::Get(Profile* profile) { return AppServiceProxyFactory::GetForProfile(profile); } -AppServiceProxy::AppServiceProxy(Profile* profile) { +AppServiceProxy::AppServiceProxy(Profile* profile) + : inner_icon_loader_(this), + outer_icon_loader_(&inner_icon_loader_, + apps::IconCache::GarbageCollectionPolicy::kEager) { + if (!profile) { + return; + } service_manager::Connector* connector = content::BrowserContext::GetConnectorFor(profile); if (!connector) { @@ -60,13 +116,7 @@ } apps::mojom::IconKeyPtr AppServiceProxy::GetIconKey(const std::string& app_id) { - apps::mojom::IconKeyPtr icon_key; - if (app_service_.is_bound()) { - cache_.ForOneApp(app_id, [&icon_key](const apps::AppUpdate& update) { - icon_key = update.IconKey(); - }); - } - return icon_key; + return outer_icon_loader_.GetIconKey(app_id); } std::unique_ptr<apps::IconLoader::Releaser> @@ -76,23 +126,9 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon, apps::mojom::Publisher::LoadIconCallback callback) { - if (app_service_.is_bound() && !icon_key.is_null()) { - // TODO(crbug.com/826982): implement another IconLoader that coalesces - // multiple in-flight calls with the same IconLoader::Key, and use it here. - // - // Possibly related to that, Mojo doesn't guarantee the order of messages, - // so multiple calls to this method might not resolve their callbacks in - // order. As per khmel@, "you may have race here, assume you publish change - // for the app and app requested new icon. But new icon is not delivered - // yet and you resolve old one instead. Now new icon arrives asynchronously - // but you no longer notify the app or do?" - app_service_->LoadIcon(std::move(icon_key), icon_compression, - size_hint_in_dip, allow_placeholder_icon, - std::move(callback)); - } else { - std::move(callback).Run(apps::mojom::IconValue::New()); - } - return nullptr; + return outer_icon_loader_.LoadIconFromIconKey( + std::move(icon_key), icon_compression, size_hint_in_dip, + allow_placeholder_icon, std::move(callback)); } void AppServiceProxy::Launch(const std::string& app_id, @@ -135,6 +171,11 @@ } } +void AppServiceProxy::OverrideInnerIconLoaderForTesting( + apps::IconLoader* icon_loader) { + inner_icon_loader_.overriding_icon_loader_for_testing_ = icon_loader; +} + void AppServiceProxy::Shutdown() { #if defined(OS_CHROMEOS) if (app_service_.is_bound()) {
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h index 5d0a82c..0cb5c4a1 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.h +++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -21,6 +21,7 @@ #include "chrome/browser/apps/app_service/extension_apps.h" #endif // OS_CHROMEOS +class AppServiceProxyTest; class Profile; namespace apps { @@ -66,6 +67,68 @@ void OpenNativeSettings(const std::string& app_id); private: + // An adapter, presenting an IconLoader interface based on the underlying + // Mojo service (or on a fake implementation for testing). + // + // Conceptually, the ASP (the AppServiceProxy) is itself such an adapter: UI + // clients call the IconLoader::LoadIconFromIconKey method (which the ASP + // implements) and the ASP translates (i.e. adapts) these to Mojo calls (or + // C++ calls to the Fake). This diagram shows control flow going left to + // right (with "=c=>" and "=m=>" denoting C++ and Mojo calls), and the + // responses (callbacks) then run right to left in LIFO order: + // + // UI =c=> ASP =+=m=> MojoService + // | or + // +=c=> Fake + // + // It is more complicated in practice, as we want to insert IconLoader + // decorators (as in the classic "decorator" or "wrapper" design pattern) to + // provide optimizations like proxy-wide icon caching and IPC coalescing + // (de-duplication). Nonetheless, from a UI client's point of view, we would + // still like to present a simple API: that the ASP implements the IconLoader + // interface. We therefore split the "ASP" component into multiple + // sub-components. Once again, control flow runs from left to right, and + // inside the ASP, outer layers (wrappers) call into inner layers (wrappees): + // + // +------------------ ASP ------------------+ + // | | + // UI =c=> | Outer =c=> MoreDecorators... =c=> Inner | =+=m=> MojoService + // | | | or + // +-----------------------------------------+ +=c=> Fake + // + // The inner_icon_loader_ field (of type InnerIconLoader) is the "Inner" + // component: the one that ultimately talks to the Mojo service. + // + // The outer_icon_loader_ field (of type IconCache) is the "Outer" component: + // the entry point for calls into the AppServiceProxy. + // + // Note that even if the ASP provides some icon caching, upstream UI clients + // may want to introduce further icon caching. See the commentary where + // IconCache::GarbageCollectionPolicy is defined. + // + // IPC coalescing would be one of the "MoreDecorators". + class InnerIconLoader : public apps::IconLoader { + public: + explicit InnerIconLoader(AppServiceProxy* host); + + // apps::IconLoader overrides. + apps::mojom::IconKeyPtr GetIconKey(const std::string& app_id) override; + std::unique_ptr<IconLoader::Releaser> LoadIconFromIconKey( + apps::mojom::IconKeyPtr icon_key, + apps::mojom::IconCompression icon_compression, + int32_t size_hint_in_dip, + bool allow_placeholder_icon, + apps::mojom::Publisher::LoadIconCallback callback) override; + + // |host_| owns |this|, as the InnerIconLoader is an AppServiceProxy field. + AppServiceProxy* host_; + + apps::IconLoader* overriding_icon_loader_for_testing_; + }; + + friend class ::AppServiceProxyTest; + void OverrideInnerIconLoaderForTesting(apps::IconLoader* icon_loader); + // KeyedService overrides. void Shutdown() override; @@ -77,6 +140,14 @@ mojo::BindingSet<apps::mojom::Subscriber> bindings_; apps::AppRegistryCache cache_; + // The LoadIconFromIconKey implementation sends a chained series of requests + // through each icon loader, starting from the outer and working back to the + // inner. Fields are listed from inner to outer, the opposite of call order, + // as each one depends on the previous one, and in the constructor, + // initialization happens in field order. + InnerIconLoader inner_icon_loader_; + IconCache outer_icon_loader_; + #if defined(OS_CHROMEOS) BuiltInChromeOsApps built_in_chrome_os_apps_; CrostiniApps crostini_apps_;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc new file mode 100644 index 0000000..e7f2d7f --- /dev/null +++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -0,0 +1,126 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_skia_rep.h" + +class AppServiceProxyTest : public testing::Test { + protected: + using UniqueReleaser = std::unique_ptr<apps::IconLoader::Releaser>; + + class FakeIconLoader : public apps::IconLoader { + public: + void FlushPendingCallbacks() { + for (auto& callback : pending_callbacks_) { + auto iv = apps::mojom::IconValue::New(); + iv->icon_compression = apps::mojom::IconCompression::kUncompressed; + iv->uncompressed = + gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(1, 1), 1.0f)); + iv->is_placeholder_icon = false; + + std::move(callback).Run(std::move(iv)); + num_inner_finished_callbacks_++; + } + pending_callbacks_.clear(); + } + + int NumInnerFinishedCallbacks() { return num_inner_finished_callbacks_; } + int NumPendingCallbacks() { return pending_callbacks_.size(); } + + private: + apps::mojom::IconKeyPtr GetIconKey(const std::string& app_id) override { + return apps::mojom::IconKey::New(apps::mojom::AppType::kWeb, app_id, 0, 0, + 0); + } + + std::unique_ptr<Releaser> LoadIconFromIconKey( + apps::mojom::IconKeyPtr icon_key, + apps::mojom::IconCompression icon_compression, + int32_t size_hint_in_dip, + bool allow_placeholder_icon, + apps::mojom::Publisher::LoadIconCallback callback) override { + if (icon_compression == apps::mojom::IconCompression::kUncompressed) { + pending_callbacks_.push_back(std::move(callback)); + } + return nullptr; + } + + int num_inner_finished_callbacks_ = 0; + std::vector<apps::mojom::Publisher::LoadIconCallback> pending_callbacks_; + }; + + UniqueReleaser LoadIcon(apps::IconLoader* loader, const std::string& app_id) { + static constexpr auto icon_compression = + apps::mojom::IconCompression::kUncompressed; + static constexpr int32_t size_hint_in_dip = 1; + static bool allow_placeholder_icon = false; + + return loader->LoadIcon(app_id, icon_compression, size_hint_in_dip, + allow_placeholder_icon, + base::BindOnce(&AppServiceProxyTest::OnLoadIcon, + base::Unretained(this))); + } + + void OverrideAppServiceProxyInnerIconLoader(apps::AppServiceProxy* proxy, + apps::IconLoader* icon_loader) { + proxy->OverrideInnerIconLoaderForTesting(icon_loader); + } + + void OnLoadIcon(apps::mojom::IconValuePtr icon_value) { + num_outer_finished_callbacks_++; + } + + int NumOuterFinishedCallbacks() { return num_outer_finished_callbacks_; } + + int num_outer_finished_callbacks_ = 0; +}; + +TEST_F(AppServiceProxyTest, IconCache) { + apps::AppServiceProxy proxy(nullptr); + FakeIconLoader fake; + OverrideAppServiceProxyInnerIconLoader(&proxy, &fake); + + // The next LoadIcon call should be a cache miss. + UniqueReleaser c0 = LoadIcon(&proxy, "cromulent"); + EXPECT_EQ(1, fake.NumPendingCallbacks()); + EXPECT_EQ(0, fake.NumInnerFinishedCallbacks()); + EXPECT_EQ(0, NumOuterFinishedCallbacks()); + + // After a cache miss, manually trigger the inner callback. + fake.FlushPendingCallbacks(); + EXPECT_EQ(0, fake.NumPendingCallbacks()); + EXPECT_EQ(1, fake.NumInnerFinishedCallbacks()); + EXPECT_EQ(1, NumOuterFinishedCallbacks()); + + // The next LoadIcon call should be a cache hit. + UniqueReleaser c1 = LoadIcon(&proxy, "cromulent"); + EXPECT_EQ(0, fake.NumPendingCallbacks()); + EXPECT_EQ(1, fake.NumInnerFinishedCallbacks()); + EXPECT_EQ(2, NumOuterFinishedCallbacks()); + + // Destroy the IconLoader::Releaser's, clearing the cache. + c0.reset(); + c1.reset(); + + // The next LoadIcon call should be a cache miss. + UniqueReleaser c2 = LoadIcon(&proxy, "cromulent"); + EXPECT_EQ(1, fake.NumPendingCallbacks()); + EXPECT_EQ(1, fake.NumInnerFinishedCallbacks()); + EXPECT_EQ(2, NumOuterFinishedCallbacks()); + + // After a cache miss, manually trigger the inner callback. + fake.FlushPendingCallbacks(); + EXPECT_EQ(0, fake.NumPendingCallbacks()); + EXPECT_EQ(2, fake.NumInnerFinishedCallbacks()); + EXPECT_EQ(3, NumOuterFinishedCallbacks()); +} + +// TODO(crbug.com/826982): test coalescing multiple in-flight calls with the +// same IconLoader::Key.
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index cf969497..2628edc 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -200,14 +200,14 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon, LoadIconCallback callback) { - if (!icon_key.is_null() && !icon_key->s_key.empty()) { + if (icon_key) { // Treat the Play Store as a special case, loading an icon defined by a // resource instead of asking the Android VM (or the cache of previous // responses from the Android VM). Presumably this is for bootstrapping: // the Play Store icon (the UI for enabling and installing Android apps) // should be showable even before the user has installed their first // Android app and before bringing up an Android VM for the first time. - if (icon_key->s_key == arc::kPlayStoreAppId) { + if (icon_key->app_id == arc::kPlayStoreAppId) { LoadPlayStoreIcon(icon_compression, size_hint_in_dip, static_cast<IconEffects>(icon_key->icon_effects), std::move(callback)); @@ -218,10 +218,10 @@ // LoadIconFromVM. LoadIconFromFileWithFallback( icon_compression, size_hint_in_dip, - GetCachedIconFilePath(icon_key->s_key, size_hint_in_dip), + GetCachedIconFilePath(icon_key->app_id, size_hint_in_dip), static_cast<IconEffects>(icon_key->icon_effects), std::move(callback), base::BindOnce(&ArcApps::LoadIconFromVM, weak_ptr_factory_.GetWeakPtr(), - icon_key->s_key, icon_compression, size_hint_in_dip, + icon_key->app_id, icon_compression, size_hint_in_dip, allow_placeholder_icon, static_cast<IconEffects>(icon_key->icon_effects))); return; @@ -414,7 +414,7 @@ apps_util::GetPrimaryDisplayUIScaleFactor())); } -void ArcApps::LoadIconFromVM(const std::string icon_key_s_key, +void ArcApps::LoadIconFromVM(const std::string app_id, apps::mojom::IconCompression icon_compression, int32_t size_hint_in_dip, bool allow_placeholder_icon, @@ -428,8 +428,7 @@ return; } - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = - prefs_->GetApp(icon_key_s_key); + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs_->GetApp(app_id); if (app_info) { base::OnceCallback<void(apps::ArcApps::AppConnectionHolder*)> pending = base::BindOnce(&LoadIcon0, icon_compression,
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h index d07e204ae..70f209b0 100644 --- a/chrome/browser/apps/app_service/arc_apps.h +++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -82,7 +82,7 @@ const base::FilePath GetCachedIconFilePath(const std::string& app_id, int32_t size_hint_in_dip); - void LoadIconFromVM(const std::string icon_key_s_key, + void LoadIconFromVM(const std::string app_id, apps::mojom::IconCompression icon_compression, int32_t size_hint_in_dip, bool allow_placeholder_icon,
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc index 6bba55f..cc4ab993 100644 --- a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc +++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
@@ -39,9 +39,8 @@ } app->icon_key = apps::mojom::IconKey::New( - apps::mojom::AppType::kBuiltIn, - static_cast<uint64_t>(internal_app.icon_resource_id), std::string(), - apps::IconEffects::kNone); + apps::mojom::AppType::kBuiltIn, internal_app.app_id, 0, + internal_app.icon_resource_id, apps::IconEffects::kNone); app->last_launch_time = base::Time(); app->install_time = base::Time(); @@ -118,12 +117,12 @@ bool allow_placeholder_icon, LoadIconCallback callback) { constexpr bool is_placeholder_icon = false; - if (!icon_key.is_null() && (icon_key->u_key != 0) && - (icon_key->u_key <= INT_MAX)) { - int resource_id = static_cast<int>(icon_key->u_key); - LoadIconFromResource( - icon_compression, size_hint_in_dip, resource_id, is_placeholder_icon, - static_cast<IconEffects>(icon_key->icon_effects), std::move(callback)); + if (icon_key && + (icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId)) { + LoadIconFromResource(icon_compression, size_hint_in_dip, + icon_key->resource_id, is_placeholder_icon, + static_cast<IconEffects>(icon_key->icon_effects), + std::move(callback)); return; } // On failure, we still run the callback, with the zero IconValue. @@ -143,7 +142,6 @@ break; case apps::mojom::LaunchSource::kFromAppListQuery: case apps::mojom::LaunchSource::kFromAppListQueryContextMenu: - app_list::RecordHistogram(app_list::APP_SEARCH_RESULT); app_list::InternalAppResult::RecordOpenHistogram(app_id); break; case apps::mojom::LaunchSource::kFromAppListRecommendation:
diff --git a/chrome/browser/apps/app_service/crostini_apps.cc b/chrome/browser/apps/app_service/crostini_apps.cc index 7555ae9..b424eccb 100644 --- a/chrome/browser/apps/app_service/crostini_apps.cc +++ b/chrome/browser/apps/app_service/crostini_apps.cc
@@ -65,36 +65,30 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon, LoadIconCallback callback) { - if (!icon_key.is_null()) { - // A non-empty s_key means that the icon is provided by the Crostini VM - // (and possibly cached on disk). - // - // An empty s_key means that the icon is a resource built into the Chrome - // OS binary. - if (!icon_key->s_key.empty()) { + if (icon_key) { + if (icon_key->resource_id != apps::mojom::IconKey::kInvalidResourceId) { + // The icon is a resource built into the Chrome OS binary. + constexpr bool is_placeholder_icon = false; + LoadIconFromResource(icon_compression, size_hint_in_dip, + icon_key->resource_id, is_placeholder_icon, + static_cast<IconEffects>(icon_key->icon_effects), + std::move(callback)); + return; + } else { auto scale_factor = apps_util::GetPrimaryDisplayUIScaleFactor(); // Try loading the icon from an on-disk cache. If that fails, fall back // to LoadIconFromVM. LoadIconFromFileWithFallback( icon_compression, size_hint_in_dip, - registry_->GetIconPath(icon_key->s_key, scale_factor), + registry_->GetIconPath(icon_key->app_id, scale_factor), static_cast<IconEffects>(icon_key->icon_effects), std::move(callback), base::BindOnce(&CrostiniApps::LoadIconFromVM, - weak_ptr_factory_.GetWeakPtr(), icon_key->s_key, + weak_ptr_factory_.GetWeakPtr(), icon_key->app_id, icon_compression, size_hint_in_dip, allow_placeholder_icon, scale_factor, static_cast<IconEffects>(icon_key->icon_effects))); return; - - } else if ((icon_key->u_key != 0) && (icon_key->u_key <= INT_MAX)) { - int resource_id = static_cast<int>(icon_key->u_key); - constexpr bool is_placeholder_icon = false; - LoadIconFromResource(icon_compression, size_hint_in_dip, resource_id, - is_placeholder_icon, - static_cast<IconEffects>(icon_key->icon_effects), - std::move(callback)); - return; } } @@ -147,7 +141,7 @@ Publish(std::move(app)); } -void CrostiniApps::LoadIconFromVM(const std::string icon_key_s_key, +void CrostiniApps::LoadIconFromVM(const std::string app_id, apps::mojom::IconCompression icon_compression, int32_t size_hint_in_dip, bool allow_placeholder_icon, @@ -177,7 +171,7 @@ // OnAppIconUpdated somehow doesn't write the cached icon file where we // expect, leading to another MaybeRequestIcon call, leading to another // OnAppIconUpdated call, leading to another MaybeRequestIcon call, etc. - registry_->MaybeRequestIcon(icon_key_s_key, scale_factor); + registry_->MaybeRequestIcon(app_id, scale_factor); } apps::mojom::AppPtr CrostiniApps::Convert( @@ -233,9 +227,8 @@ // should be showable even before the user has installed their first Crostini // app and before bringing up an Crostini VM for the first time. if (app_id == crostini::kCrostiniTerminalId) { - return apps::mojom::IconKey::New(apps::mojom::AppType::kCrostini, - IDR_LOGO_CROSTINI_TERMINAL, std::string(), - icon_effects); + return apps::mojom::IconKey::New(apps::mojom::AppType::kCrostini, app_id, 0, + IDR_LOGO_CROSTINI_TERMINAL, icon_effects); } return icon_key_factory_.MakeIconKey(apps::mojom::AppType::kCrostini, app_id,
diff --git a/chrome/browser/apps/app_service/crostini_apps.h b/chrome/browser/apps/app_service/crostini_apps.h index 64ef99c8..2e2676d 100644 --- a/chrome/browser/apps/app_service/crostini_apps.h +++ b/chrome/browser/apps/app_service/crostini_apps.h
@@ -68,7 +68,7 @@ void OnAppIconUpdated(const std::string& app_id, ui::ScaleFactor scale_factor) override; - void LoadIconFromVM(const std::string icon_key_s_key, + void LoadIconFromVM(const std::string app_id, apps::mojom::IconCompression icon_compression, int32_t size_hint_in_dip, bool allow_placeholder_icon,
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index c8fbb481..a4d89e1 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -130,9 +130,9 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon, LoadIconCallback callback) { - if (!icon_key.is_null() && !icon_key->s_key.empty()) { + if (icon_key) { LoadIconFromExtension( - icon_compression, size_hint_in_dip, profile_, icon_key->s_key, + icon_compression, size_hint_in_dip, profile_, icon_key->app_id, static_cast<IconEffects>(icon_key->icon_effects), std::move(callback)); return; } @@ -165,7 +165,6 @@ break; case apps::mojom::LaunchSource::kFromAppListQuery: case apps::mojom::LaunchSource::kFromAppListQueryContextMenu: - app_list::RecordHistogram(app_list::APP_SEARCH_RESULT); extensions::RecordAppListSearchLaunch(extension); break; case apps::mojom::LaunchSource::kFromAppListRecommendation:
diff --git a/chrome/browser/apps/app_service/icon_key_util.cc b/chrome/browser/apps/app_service/icon_key_util.cc index 285bb2e..7c22ca6 100644 --- a/chrome/browser/apps/app_service/icon_key_util.cc +++ b/chrome/browser/apps/app_service/icon_key_util.cc
@@ -6,13 +6,15 @@ namespace apps_util { -IncrementingIconKeyFactory::IncrementingIconKeyFactory() : u_key_(0) {} +IncrementingIconKeyFactory::IncrementingIconKeyFactory() : last_timeline_(0) {} apps::mojom::IconKeyPtr IncrementingIconKeyFactory::MakeIconKey( apps::mojom::AppType app_type, - const std::string& s_key, + const std::string& app_id, uint32_t icon_effects) { - return apps::mojom::IconKey::New(app_type, ++u_key_, s_key, icon_effects); + return apps::mojom::IconKey::New(app_type, app_id, ++last_timeline_, + apps::mojom::IconKey::kInvalidResourceId, + icon_effects); } } // namespace apps_util
diff --git a/chrome/browser/apps/app_service/icon_key_util.h b/chrome/browser/apps/app_service/icon_key_util.h index b7ea0d6..958386b0 100644 --- a/chrome/browser/apps/app_service/icon_key_util.h +++ b/chrome/browser/apps/app_service/icon_key_util.h
@@ -14,24 +14,27 @@ namespace apps_util { -// Converts strings (such as App IDs) to IconKeys, such that passing the same -// string twice to MakeIconKey will result in different IconKeys (different not -// just in the pointer sense, but their IconKey.u_key values will also differ). +// Creates IconKeys such that passing the same arguments twice to MakeIconKey +// will result in different IconKeys (different not just in the pointer sense, +// but their IconKey.timeline values will also differ). // // Callers (which are presumably App Service app publishers) can therefore -// publish such IconKeys whenever an app's icon changes, even though the App ID -// itself doesn't change, and App Service app subscribers will notice (and -// reload) the new icon from the new (changed) icon key. +// publish such IconKeys whenever an app's icon changes. Even though the app_id +// does not change, App Service app subscribers will notice (and reload) the +// new icon from the new (changed) IconKey. +// +// The IconKey.resource_id is always zero, as resource-backed icons do not +// change without a browser re-start. class IncrementingIconKeyFactory { public: IncrementingIconKeyFactory(); apps::mojom::IconKeyPtr MakeIconKey(apps::mojom::AppType app_type, - const std::string& s_key, + const std::string& app_id, uint32_t icon_effects); private: - uint64_t u_key_; + uint64_t last_timeline_; DISALLOW_COPY_AND_ASSIGN(IncrementingIconKeyFactory); };
diff --git a/chrome/browser/apps/app_shim/BUILD.gn b/chrome/browser/apps/app_shim/BUILD.gn index ffd8a3e7e..380edca5 100644 --- a/chrome/browser/apps/app_shim/BUILD.gn +++ b/chrome/browser/apps/app_shim/BUILD.gn
@@ -18,6 +18,8 @@ "apps_page_shim_handler.mm", "extension_app_shim_handler_mac.cc", "extension_app_shim_handler_mac.h", + "mach_bootstrap_acceptor.cc", + "mach_bootstrap_acceptor.h", "unix_domain_socket_acceptor.cc", "unix_domain_socket_acceptor.h", ]
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc index a73ecdad5..9d435cf 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc +++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.cc
@@ -19,10 +19,31 @@ // AppShimHostBootstrap is initially owned by itself until it receives a // LaunchApp message or a channel error. In LaunchApp, ownership is // transferred to a unique_ptr. - (new AppShimHostBootstrap)->ServeChannel(std::move(endpoint)); + DCHECK(endpoint.platform_handle().is_fd()); + + base::ProcessId pid; + socklen_t pid_size = sizeof(pid); + if (getsockopt(endpoint.platform_handle().GetFD().get(), SOL_LOCAL, + LOCAL_PEERPID, &pid, &pid_size)) { + LOG(ERROR) << "Failed to get peer pid for app shim."; + return; + } + (new AppShimHostBootstrap(pid))->ServeChannel(std::move(endpoint)); } -AppShimHostBootstrap::AppShimHostBootstrap() : host_bootstrap_binding_(this) {} +// static +void AppShimHostBootstrap::CreateForChannelAndPeerID( + mojo::PlatformChannelEndpoint endpoint, + base::ProcessId peer_pid) { + // AppShimHostBootstrap is initially owned by itself until it receives a + // LaunchApp message or a channel error. In LaunchApp, ownership is + // transferred to a unique_ptr. + DCHECK(endpoint.platform_handle().is_mach_send()); + (new AppShimHostBootstrap(peer_pid))->ServeChannel(std::move(endpoint)); +} + +AppShimHostBootstrap::AppShimHostBootstrap(base::ProcessId peer_pid) + : host_bootstrap_binding_(this), pid_(peer_pid) {} AppShimHostBootstrap::~AppShimHostBootstrap() { DCHECK(!launch_app_callback_); @@ -32,14 +53,6 @@ mojo::PlatformChannelEndpoint endpoint) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(endpoint.platform_handle().is_fd()); - socklen_t pid_size = sizeof(pid_); - if (getsockopt(endpoint.platform_handle().GetFD().get(), SOL_LOCAL, - LOCAL_PEERPID, &pid_, &pid_size)) { - LOG(ERROR) << "Failed to get peer pid for app shim."; - return; - } - mojo::ScopedMessagePipeHandle message_pipe = bootstrap_mojo_connection_.Connect(std::move(endpoint)); host_bootstrap_binding_.Bind(
diff --git a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h index 71b6bd3..bfbb1590 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h +++ b/chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h
@@ -24,6 +24,14 @@ // a file descriptor of a channel created by an UnixDomainSocketAcceptor, and // begins listening for messages on it. static void CreateForChannel(mojo::PlatformChannelEndpoint endpoint); + + // Creates a new server-side mojo channel at |endpoint|, which contains a + // a Mach port for a channel created by an MachBootstrapAcceptor, and + // begins listening for messages on it. The PID of the sender of |endpoint| + // is stored in |peer_pid|. + static void CreateForChannelAndPeerID(mojo::PlatformChannelEndpoint endpoint, + base::ProcessId peer_pid); + ~AppShimHostBootstrap() override; // Called in response to connecting (or failing to connect to) an @@ -44,7 +52,7 @@ const std::vector<base::FilePath>& GetLaunchFiles() const { return files_; } protected: - AppShimHostBootstrap(); + explicit AppShimHostBootstrap(base::ProcessId peer_pid); void ServeChannel(mojo::PlatformChannelEndpoint endpoint); void ChannelError(uint32_t custom_reason, const std::string& description); virtual apps::AppShimHandler* GetHandler();
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc index dbc91e62..3dc809f 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc +++ b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/apps/app_shim/app_shim_host_mac.h" +#include <unistd.h> + #include <memory> #include <tuple> #include <vector> @@ -87,7 +89,7 @@ public: explicit TestingAppShimHostBootstrap( chrome::mojom::AppShimHostBootstrapRequest host_request) - : test_weak_factory_(this) { + : AppShimHostBootstrap(getpid()), test_weak_factory_(this) { // AppShimHost will bind to the request from ServeChannel. For testing // purposes, have this request passed in at creation. host_bootstrap_binding_.Bind(std::move(host_request));
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.h b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.h index ae98c2c..cd8dd9a 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.h +++ b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h" #include "chrome/browser/apps/app_shim/unix_domain_socket_acceptor.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/platform/platform_channel_endpoint.h" @@ -28,6 +29,7 @@ // The AppShimHostManager receives connections from app shims on a UNIX // socket (|acceptor_|) and creates a helper object to manage the connection. class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate, + public apps::MachBootstrapAcceptor::Delegate, public base::RefCountedThreadSafe< AppShimHostManager, content::BrowserThread::DeleteOnUIThread> { @@ -55,6 +57,10 @@ void OnClientConnected(mojo::PlatformChannelEndpoint endpoint) override; void OnListenError() override; + // MachBootstrapAcceptor::Delegate: + void OnClientConnected(mojo::PlatformChannelEndpoint endpoint, + base::ProcessId peer_pid) override; + // The |acceptor_| must be created on a thread which allows blocking I/O. void InitOnBackgroundThread(); @@ -64,6 +70,7 @@ base::FilePath directory_in_tmp_; std::unique_ptr<apps::UnixDomainSocketAcceptor> acceptor_; + std::unique_ptr<apps::MachBootstrapAcceptor> mach_acceptor_; std::unique_ptr<apps::ExtensionAppShimHandler> extension_app_shim_handler_;
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm index bdda76c..07e32da2 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_host_manager_mac.mm
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" +#include "base/md5.h" #include "base/path_service.h" #include "base/task/post_task.h" #include "base/threading/scoped_blocking_call.h" @@ -21,6 +22,7 @@ #include "chrome/common/mac/app_mode_common.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_task_traits.h" +#include "mojo/public/cpp/platform/features.h" namespace { @@ -35,7 +37,8 @@ void DeleteSocketFiles(const base::FilePath& directory_in_tmp, const base::FilePath& symlink_path, - const base::FilePath& version_path) { + const base::FilePath& version_path, + const base::FilePath& mojo_channel_mac_signal_file) { base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::MAY_BLOCK); @@ -46,6 +49,8 @@ base::DeleteFile(symlink_path, false); if (!directory_in_tmp.empty()) base::DeleteFile(directory_in_tmp, true); + if (!mojo_channel_mac_signal_file.empty()) + base::DeleteFile(mojo_channel_mac_signal_file, false); } } // namespace @@ -69,6 +74,8 @@ AppShimHostManager::~AppShimHostManager() { base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}) ->DeleteSoon(FROM_HERE, std::move(acceptor_)); + base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO}) + ->DeleteSoon(FROM_HERE, std::move(mach_acceptor_)); // The AppShimHostManager is only initialized if the Chrome process // successfully took the singleton lock. If it was not initialized, do not @@ -80,16 +87,20 @@ base::FilePath user_data_dir; base::FilePath symlink_path; base::FilePath version_path; + base::FilePath mojo_channel_mac_signal_file; if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { symlink_path = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); version_path = user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName); + mojo_channel_mac_signal_file = + user_data_dir.Append(app_mode::kMojoChannelMacSignalFile); } - base::PostTaskWithTraits(FROM_HERE, - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(&DeleteSocketFiles, directory_in_tmp_, - symlink_path, version_path)); + base::PostTaskWithTraits( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + base::BindOnce(&DeleteSocketFiles, directory_in_tmp_, symlink_path, + version_path, mojo_channel_mac_signal_file)); } void AppShimHostManager::InitOnBackgroundThread() { @@ -99,6 +110,31 @@ if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) return; + base::FilePath mojo_channel_mac_signal_file = + user_data_dir.Append(app_mode::kMojoChannelMacSignalFile); + if (base::FeatureList::IsEnabled(mojo::features::kMojoChannelMac)) { + std::string name_fragment = + std::string(app_mode::kAppShimBootstrapNameFragment) + "." + + base::MD5String(user_data_dir.value()); + mach_acceptor_ = + std::make_unique<apps::MachBootstrapAcceptor>(name_fragment, this); + mach_acceptor_->Start(); + + // App shims do not have Finch initialized and so cannot test for the + // kMojoChannelMac feature. Instead, put a file in the profile directory. + // The presence of this file will indicate that app shims should connect + // over a Mach channel instead. + char data = 1; + if (base::WriteFile(mojo_channel_mac_signal_file, &data, 1) != 1) { + LOG(ERROR) << "Failed to write MojoChannelMac signal file."; + } + + // Also create the UNIX domain socket acceptor, so that app shims that for + // some reason fail to pick up the signal file still work. + } else { + base::DeleteFile(mojo_channel_mac_signal_file, false); + } + // The socket path must be shorter than 104 chars (IPC::kMaxSocketNameLength). // To accommodate this, we use a short path in /tmp/ that is generated from a // hash of the user data dir. @@ -165,6 +201,16 @@ std::move(endpoint))); } +void AppShimHostManager::OnClientConnected( + mojo::PlatformChannelEndpoint endpoint, + base::ProcessId peer_pid) { + base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI}) + ->PostTask( + FROM_HERE, + base::BindOnce(&AppShimHostBootstrap::CreateForChannelAndPeerID, + std::move(endpoint), peer_pid)); +} + void AppShimHostManager::OnListenError() { // TODO(tapted): Set a timeout and attempt to reconstruct the channel. Until // cases where the error could occur are better known, just reset the acceptor
diff --git a/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm index 37f8ad7..60587c29 100644 --- a/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm
@@ -5,6 +5,8 @@ // Tests behavior when quitting apps with app shims. #import <Cocoa/Cocoa.h> +#include <unistd.h> + #include <vector> #include "apps/switches.h" @@ -34,7 +36,7 @@ // Test class used to expose protected methods of AppShimHostBootstrap. class TestAppShimHostBootstrap : public AppShimHostBootstrap { public: - TestAppShimHostBootstrap() {} + TestAppShimHostBootstrap() : AppShimHostBootstrap(getpid()) {} using AppShimHostBootstrap::LaunchApp; private:
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc index 27e12a1..6d83230 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -415,7 +415,8 @@ void ExtensionAppShimHandler::SetHostedAppHidden(Profile* profile, const std::string& app_id, bool hidden) { - const AppBrowserMap::iterator it = app_browser_windows_.find(app_id); + const AppBrowserMap::iterator it = + app_browser_windows_.find(std::make_pair(profile, app_id)); if (it == app_browser_windows_.end()) return; @@ -478,7 +479,7 @@ if (host) OnShimQuit(host); else - CloseBrowsersForApp(app_id); + CloseBrowsersForApp(profile, app_id); } void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { @@ -620,8 +621,10 @@ return extension; } -void ExtensionAppShimHandler::CloseBrowsersForApp(const std::string& app_id) { - AppBrowserMap::iterator it = app_browser_windows_.find(app_id); +void ExtensionAppShimHandler::CloseBrowsersForApp(Profile* profile, + const std::string& app_id) { + AppBrowserMap::iterator it = + app_browser_windows_.find(std::make_pair(profile, app_id)); if (it == app_browser_windows_.end()) return; @@ -741,7 +744,8 @@ bool windows_focused; const std::string& app_id = host->GetAppId(); if (extension->is_hosted_app()) { - AppBrowserMap::iterator it = app_browser_windows_.find(app_id); + AppBrowserMap::iterator it = + app_browser_windows_.find(std::make_pair(profile, app_id)); if (it == app_browser_windows_.end()) return; @@ -788,7 +792,7 @@ return; if (extension->is_hosted_app()) { - CloseBrowsersForApp(app_id); + CloseBrowsersForApp(profile, app_id); } else { const AppWindowList windows = delegate_->GetWindows(profile, app_id); for (AppWindowRegistry::const_iterator it = windows.begin(); @@ -846,7 +850,8 @@ if (!extension) return; - BrowserSet& browsers = app_browser_windows_[extension->id()]; + BrowserSet& browsers = app_browser_windows_[std::make_pair( + browser->profile(), extension->id())]; browsers.insert(browser); if (browsers.size() == 1) OnAppActivated(browser->profile(), extension->id()); @@ -902,7 +907,7 @@ // |app_browser_windows_|. for (auto it = app_browser_windows_.begin(); it != app_browser_windows_.end(); ++it) { - const std::string& extension_id = it->first; + const std::string& extension_id = it->first.second; BrowserSet& browsers = it->second; auto found = browsers.find(browser); if (found == browsers.end())
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h index f15dafcbb..36ea686 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
@@ -172,7 +172,7 @@ protected: typedef std::map<std::pair<Profile*, std::string>, AppShimHost*> HostMap; typedef std::set<Browser*> BrowserSet; - typedef std::map<std::string, BrowserSet> AppBrowserMap; + typedef std::map<std::pair<Profile*, std::string>, BrowserSet> AppBrowserMap; // Virtual for tests. virtual bool IsAcceptablyCodeSigned(pid_t pid) const; @@ -192,7 +192,7 @@ Profile** profile); // Closes all browsers associated with an app. - void CloseBrowsersForApp(const std::string& app_id); + void CloseBrowsersForApp(Profile* profile, const std::string& app_id); // This is passed to Delegate::LoadProfileAsync for shim-initiated launches // where the profile was not yet loaded.
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc index 60fd2128..6f1ec04 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" +#include <unistd.h> + #include <map> #include <memory> #include <utility> @@ -181,7 +183,8 @@ const std::string& app_id, base::Optional<apps::AppShimLaunchResult>* launch_result, apps::AppShimHandler* handler) - : profile_path_(profile_path), + : AppShimHostBootstrap(getpid()), + profile_path_(profile_path), app_id_(app_id), launch_result_(launch_result), handler_(handler),
diff --git a/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.cc b/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.cc new file mode 100644 index 0000000..98f0ba7 --- /dev/null +++ b/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.cc
@@ -0,0 +1,93 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h" + +#include <bsm/libbsm.h> +#include <mach/message.h> + +#include <memory> +#include <utility> + +#include "base/mac/foundation_util.h" +#include "base/mac/mach_logging.h" +#include "base/mac/scoped_mach_msg_destroy.h" +#include "base/strings/stringprintf.h" +#include "chrome/common/mac/app_mode_common.h" + +namespace apps { + +MachBootstrapAcceptor::MachBootstrapAcceptor(const std::string& name_fragment, + Delegate* delegate) + : server_name_(base::StringPrintf("%s.%s", + base::mac::BaseBundleID(), + name_fragment.c_str()) + .c_str()), + delegate_(delegate) { + DCHECK(delegate_); +} + +MachBootstrapAcceptor::~MachBootstrapAcceptor() { + Stop(); +} + +void MachBootstrapAcceptor::Start() { + mojo::NamedPlatformChannel::Options options; + options.server_name = server_name_; + mojo::NamedPlatformChannel channel(options); + endpoint_ = channel.TakeServerEndpoint(); + dispatch_source_ = std::make_unique<base::DispatchSourceMach>( + server_name_.c_str(), port(), ^{ + HandleRequest(); + }); + dispatch_source_->Resume(); +} + +void MachBootstrapAcceptor::Stop() { + endpoint_.reset(); + dispatch_source_.reset(); +} + +void MachBootstrapAcceptor::HandleRequest() { + struct : mach_msg_base_t { + mach_msg_audit_trailer_t trailer; + } request{}; + request.header.msgh_size = sizeof(request); + request.header.msgh_local_port = port(); + kern_return_t kr = mach_msg( + &request.header, + MACH_RCV_MSG | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) | + MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT), + 0, sizeof(request), port(), MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (kr != KERN_SUCCESS) { + MACH_LOG(ERROR, kr) << "mach_msg"; + return; + } + + base::ScopedMachMsgDestroy scoped_message(&request.header); + + if (request.header.msgh_id != app_mode::kBootstrapMsgId || + request.header.msgh_size != sizeof(mach_msg_base_t)) { + return; + } + + pid_t sender_pid = audit_token_to_pid(request.trailer.msgh_audit); + + mojo::PlatformChannelEndpoint remote_endpoint(mojo::PlatformHandle( + base::mac::ScopedMachSendRight(request.header.msgh_remote_port))); + if (!remote_endpoint.is_valid()) { + return; + } + + scoped_message.Disarm(); + + delegate_->OnClientConnected(std::move(remote_endpoint), sender_pid); +} + +mach_port_t MachBootstrapAcceptor::port() { + DCHECK(endpoint_.is_valid()); + return endpoint_.platform_handle().GetMachReceiveRight().get(); +} + +} // namespace apps
diff --git a/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h b/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h new file mode 100644 index 0000000..be6420cb --- /dev/null +++ b/chrome/browser/apps/app_shim/mach_bootstrap_acceptor.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_APPS_APP_SHIM_MACH_BOOTSTRAP_ACCEPTOR_H_ +#define CHROME_BROWSER_APPS_APP_SHIM_MACH_BOOTSTRAP_ACCEPTOR_H_ + +#include <memory> + +#include "base/mac/dispatch_source_mach.h" +#include "base/macros.h" +#include "base/process/process_handle.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel_endpoint.h" +#include "mojo/public/cpp/platform/platform_channel_server_endpoint.h" + +namespace apps { + +// A simple Mach message server published in the system bootstrap namespace. +// When an app shim client sends a message, the server creates a +// mojo::PlatformChannelEndpoint from the Mach port specified in the +// msgh_remote_port (the Mach reply port) and passes it to its Delegate. The +// delegate then uses this to initialize a Mojo IPC channel. +class MachBootstrapAcceptor { + public: + class Delegate { + public: + // Called when a client identified by |peer_pid| connects with the + // Mach port it provided in |endpoint|. + virtual void OnClientConnected(mojo::PlatformChannelEndpoint endpoint, + base::ProcessId peer_pid) = 0; + }; + + // Initializes the server by specifying the |name_fragment|, which will be + // appended to the running process's bundle identifier, to be published in + // the bootstrap server. + MachBootstrapAcceptor(const std::string& name_fragment, Delegate* delegate); + ~MachBootstrapAcceptor(); + + // Creates a Mach receive port and publishes a send right to it in the system + // bootstrap namespace. Clients will then be able to send messages to this + // server. + void Start(); + + // Stops listening for client messages and un-publishes the server from the + // bootstrap namespace. + void Stop(); + + private: + // Called by |dispatch_source_| when a Mach message is ready to be received + // on |endpoint_|. + void HandleRequest(); + + mach_port_t port(); + + mojo::NamedPlatformChannel::ServerName server_name_; + Delegate* delegate_; + mojo::PlatformChannelServerEndpoint endpoint_; + std::unique_ptr<base::DispatchSourceMach> dispatch_source_; + + DISALLOW_COPY_AND_ASSIGN(MachBootstrapAcceptor); +}; + +} // namespace apps + +#endif // CHROME_BROWSER_APPS_APP_SHIM_MACH_BOOTSTRAP_ACCEPTOR_H_
diff --git a/chrome/browser/autofill/captured_sites_test_utils.cc b/chrome/browser/autofill/captured_sites_test_utils.cc index 0a3a774..57a9a00 100644 --- a/chrome/browser/autofill/captured_sites_test_utils.cc +++ b/chrome/browser/autofill/captured_sites_test_utils.cc
@@ -51,6 +51,19 @@ // Automation Framework will retry an autofill action a couple times before // concluding that Chrome Autofill does not work. const int kAutofillActionNumRetries = 5; + +// The public key hash for the certificate Web Page Replay (WPR) uses to serve +// HTTPS content. +// The Captured Sites Test Framework relies on WPR to serve captured site +// traffic. If a machine does not have the WPR certificate installed, Chrome +// will detect a server certificate validation failure when WPR serves Chrome +// HTTPS content. In response Chrome will block the WPR HTTPS content. +// The test framework avoids this problem by launching Chrome with the +// ignore-certificate-errors-spki-list flag set to the WPR certificate's +// public key hash. Doing so tells Chrome to ignore server certificate +// validation errors from WPR. +const char kWebPageReplayCertSPKI[] = + "PoNnQAwghMiLUPg1YNFtvTfGreNT8r9oeLEyzgNCJWc="; } // namespace namespace captured_sites_test_utils { @@ -264,12 +277,12 @@ // "EXCLUDE clients1.google.com," "EXCLUDE localhost", kHostHttpPort, kHostHttpsPort)); + command_line->AppendSwitchASCII( + network::switches::kIgnoreCertificateErrorsSPKIList, + kWebPageReplayCertSPKI); } void TestRecipeReplayer::Setup() { - EXPECT_TRUE(InstallWebPageReplayServerRootCert()) - << "Cannot install the root certificate " - << "for the local web page replay server."; CleanupSiteData(); // Bypass permission dialogs. @@ -283,9 +296,6 @@ CleanupSiteData(); EXPECT_TRUE(StopWebPageReplayServer()) << "Cannot stop the local Web Page Replay server."; - EXPECT_TRUE(RemoveWebPageReplayServerRootCert()) - << "Cannot remove the root certificate " - << "for the local Web Page Replay server."; } TestRecipeReplayChromeFeatureActionExecutor* @@ -377,16 +387,6 @@ return true; } -bool TestRecipeReplayer::InstallWebPageReplayServerRootCert() { - return RunWebPageReplayCmdAndWaitForExit("installroot", - std::vector<std::string>()); -} - -bool TestRecipeReplayer::RemoveWebPageReplayServerRootCert() { - return RunWebPageReplayCmdAndWaitForExit("removeroot", - std::vector<std::string>()); -} - bool TestRecipeReplayer::RunWebPageReplayCmdAndWaitForExit( const std::string& cmd, const std::vector<std::string>& args, @@ -407,14 +407,19 @@ const std::string& cmd, const std::vector<std::string>& args, base::Process* process) { + // Allow the function to block. Otherwise the subsequent call to + // base::PathExists will fail. base::PathExists must be called from + // a scope that allows blocking. + base::ScopedAllowBlockingForTesting allow_blocking; + base::LaunchOptions options = base::LaunchOptionsForTest(); - base::FilePath exe_dir; - if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &exe_dir)) { + base::FilePath src_dir; + if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) { ADD_FAILURE() << "Failed to extract the Chromium source directory!"; return false; } - base::FilePath web_page_replay_binary_dir = exe_dir.AppendASCII( + base::FilePath web_page_replay_binary_dir = src_dir.AppendASCII( "third_party/catapult/telemetry/telemetry/internal/bin"); options.current_directory = web_page_replay_binary_dir; @@ -431,18 +436,12 @@ web_page_replay_binary_dir.AppendASCII(wpr_executable_binary)); full_command.AppendArg(cmd); - // Ask web page replay to use the custom certifcate and key files used to + // Ask web page replay to use the custom certificate and key files used to // make the web page captures. // The capture files used in these browser tests are also used on iOS to // test autofill. // The custom cert and key files are different from those of the offical // WPR releases. The custom files are made to work on iOS. - base::FilePath src_dir; - if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) { - ADD_FAILURE() << "Failed to extract the Chromium source directory!"; - return false; - } - base::FilePath web_page_replay_support_file_dir = src_dir.AppendASCII( "components/test/data/autofill/web_page_replay_support_files"); full_command.AppendArg(base::StringPrintf( @@ -459,6 +458,8 @@ for (const auto arg : args) full_command.AppendArg(arg); + LOG(INFO) << full_command.GetArgumentsString(); + *process = base::LaunchProcess(full_command, options); return true; }
diff --git a/chrome/browser/autofill/captured_sites_test_utils.h b/chrome/browser/autofill/captured_sites_test_utils.h index 2c089e0..5ff7ec7 100644 --- a/chrome/browser/autofill/captured_sites_test_utils.h +++ b/chrome/browser/autofill/captured_sites_test_utils.h
@@ -244,8 +244,6 @@ void CleanupSiteData(); bool StartWebPageReplayServer(const base::FilePath& capture_file_path); bool StopWebPageReplayServer(); - bool InstallWebPageReplayServerRootCert(); - bool RemoveWebPageReplayServerRootCert(); bool RunWebPageReplayCmdAndWaitForExit( const std::string& cmd, const std::vector<std::string>& args,
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc index 43bbafd..f8c67a1 100644 --- a/chrome/browser/background/background_contents_service.cc +++ b/chrome/browser/background/background_contents_service.cc
@@ -164,7 +164,7 @@ {}, delegate); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); } // Show a popup notification balloon with a crash message for a given app/
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc index 965dc634..e178ac2 100644 --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc
@@ -13,18 +13,9 @@ "DoubleTapToZoomInTabletMode", base::FEATURE_DISABLED_BY_DEFAULT}; #endif -#if !defined(OS_ANDROID) -// Whether to enable "dark mode" enhancements in Mac Mojave or Windows 10 for -// UIs implemented with web technologies. -const base::Feature kWebUIDarkMode { - "WebUIDarkMode", -#if defined(OS_MACOSX) || defined(OS_WIN) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif // defined(OS_MACOSX) || defined(OS_WIN) -}; -#endif // !defined(OS_ANDROID) +// Enables an extension menu in the toolbar. See https://crbug.com/943702 +const base::Feature kExtensionsToolbarMenu{"ExtensionsToolbarMenu", + base::FEATURE_DISABLED_BY_DEFAULT}; // Enables grouping tabs together in the tab strip. https://crbug.com/905491 const base::Feature kTabGroups{"TabGroups", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -42,4 +33,17 @@ const base::Feature kTabHoverCardImages{"TabHoverCardImages", base::FEATURE_DISABLED_BY_DEFAULT}; +#if !defined(OS_ANDROID) +// Whether to enable "dark mode" enhancements in Mac Mojave or Windows 10 for +// UIs implemented with web technologies. +const base::Feature kWebUIDarkMode { + "WebUIDarkMode", +#if defined(OS_MACOSX) || defined(OS_WIN) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif // defined(OS_MACOSX) || defined(OS_WIN) +}; +#endif // !defined(OS_ANDROID) + } // namespace features
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index c46e261..33b9f08 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -20,9 +20,7 @@ extern const base::Feature kDoubleTapToZoomInTabletMode; #endif -#if !defined(OS_ANDROID) -extern const base::Feature kWebUIDarkMode; -#endif +extern const base::Feature kExtensionsToolbarMenu; extern const base::Feature kTabGroups; @@ -31,6 +29,10 @@ extern const base::Feature kTabHoverCardImages; +#if !defined(OS_ANDROID) +extern const base::Feature kWebUIDarkMode; +#endif + } // namespace features #endif // CHROME_BROWSER_BROWSER_FEATURES_H_
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 27092f63..ce5fa2d 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -474,7 +474,6 @@ metrics_services_manager_ = std::move(manager); metrics_services_manager_client_ = static_cast<ChromeMetricsServicesManagerClient*>(client); - metrics_services_manager_->GetVariationsService()->OverrideCachedUIStrings(); } namespace {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 6e16b1c..aa61cff8 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -487,6 +487,7 @@ <include name="IDR_USB_DEVICE_MANAGER_TEST_MOJOM_LITE_JS" file="${root_gen_dir}\device\usb\public\mojom\device_manager_test.mojom-lite.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_USB_DEVICE_MOJOM_LITE_JS" file="${root_gen_dir}\device\usb\public\mojom\device.mojom-lite.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_CSS" file="resources\usb_internals\usb_internals.css" type="BINDATA" compress="gzip" /> + <include name="IDR_USB_INTERNALS_DESCRIPTOR_PANEL_JS" file="resources\usb_internals\descriptor_panel.js" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_DEVICES_PAGE_JS" file="resources\usb_internals\devices_page.js" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_HTML" file="resources\usb_internals\usb_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_USB_INTERNALS_JS" file="resources\usb_internals\usb_internals.js" type="BINDATA" compress="gzip" />
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver.h b/chrome/browser/browser_switcher/alternative_browser_driver.h index 37e95fc..7d9e10cc 100644 --- a/chrome/browser/browser_switcher/alternative_browser_driver.h +++ b/chrome/browser/browser_switcher/alternative_browser_driver.h
@@ -33,6 +33,10 @@ // Tries to launch |browser| at the specified URL, using whatever // method is most appropriate. virtual bool TryLaunch(const GURL& url) = 0; + + // Returns the i18n code for the name of the alternative browser, if it was + // auto-detected. If the name couldn't be auto-detected, returns 0. + virtual std::string GetBrowserName() const = 0; }; // Default concrete implementation for |AlternativeBrowserDriver|. Uses a @@ -44,6 +48,7 @@ // AlternativeBrowserDriver bool TryLaunch(const GURL& url) override; + std::string GetBrowserName() const override; // Create the CommandLine object that would be used to launch an external // process.
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc b/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc index a9cb167..b8e471a 100644 --- a/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc +++ b/chrome/browser/browser_switcher/alternative_browser_driver_posix.cc
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_switcher/browser_switcher_prefs.h" +#include "chrome/grit/generated_resources.h" #include "url/gurl.h" #include "third_party/re2/src/re2/re2.h" @@ -43,12 +44,13 @@ const struct { const char* var_name; const char* executable_name; + const char* browser_name; } kBrowserVarMappings[] = { - {kChromeVarName, kChromeExecutableName}, - {kFirefoxVarName, kFirefoxExecutableName}, - {kOperaVarName, kOperaExecutableName}, + {kChromeVarName, kChromeExecutableName, ""}, + {kFirefoxVarName, kFirefoxExecutableName, "Mozilla Firefox"}, + {kOperaVarName, kOperaExecutableName, "Opera"}, #if defined(OS_MACOSX) - {kSafariVarName, kSafariExecutableName}, + {kSafariVarName, kSafariExecutableName, "Safari"}, #endif }; @@ -171,6 +173,21 @@ return true; } +std::string AlternativeBrowserDriverImpl::GetBrowserName() const { + std::string path = prefs_->GetAlternativeBrowserPath(); +#if defined(OS_MACOSX) + // Unlike most POSIX platforms, MacOS always has another browser than Chrome, + // so admins don't have to explicitly configure one. + if (path.empty()) + path = kSafariVarName; +#endif + for (const auto& mapping : kBrowserVarMappings) { + if (!path.compare(mapping.var_name)) + return std::string(mapping.browser_name); + } + return std::string(); +} + base::CommandLine AlternativeBrowserDriverImpl::CreateCommandLine( const GURL& url) { std::string path = prefs_->GetAlternativeBrowserPath();
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc b/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc index 7530040..7041afc 100644 --- a/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc +++ b/chrome/browser/browser_switcher/alternative_browser_driver_unittest.cc
@@ -11,6 +11,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/browser_switcher/browser_switcher_prefs.h" +#include "chrome/grit/generated_resources.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -100,6 +101,42 @@ EXPECT_EQ(UTF8ToNative("--flag=http://example.com/#fragment"), argv[1]); } +TEST_F(AlternativeBrowserDriverTest, GetBrowserName) { +#if defined(OS_WIN) + std::string expected = "Internet Explorer"; +#elif defined(OS_MACOSX) + std::string expected = "Safari"; +#else + std::string expected = ""; +#endif + std::string actual = driver()->GetBrowserName(); + EXPECT_EQ(expected, actual); + + SetBrowserPath("bogus.exe"); + actual = driver()->GetBrowserName(); + EXPECT_EQ("", actual); + +#if defined(OS_WIN) + SetBrowserPath("${ie}"); + actual = driver()->GetBrowserName(); + EXPECT_EQ("Internet Explorer", actual); +#endif + +#if defined(OS_WIN) || defined(OS_MACOSX) + SetBrowserPath("${safari}"); + actual = driver()->GetBrowserName(); + EXPECT_EQ("Safari", actual); +#endif + + SetBrowserPath("${firefox}"); + actual = driver()->GetBrowserName(); + EXPECT_EQ("Mozilla Firefox", actual); + + SetBrowserPath("${opera}"); + actual = driver()->GetBrowserName(); + EXPECT_EQ("Opera", actual); +} + #if defined(OS_WIN) TEST_F(AlternativeBrowserDriverTest, CreateCommandLineExpandsEnvVars) { _putenv("A=AAA");
diff --git a/chrome/browser/browser_switcher/alternative_browser_driver_win.cc b/chrome/browser/browser_switcher/alternative_browser_driver_win.cc index 02ea686..e07ff71 100644 --- a/chrome/browser/browser_switcher/alternative_browser_driver_win.cc +++ b/chrome/browser/browser_switcher/alternative_browser_driver_win.cc
@@ -17,6 +17,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/registry.h" #include "chrome/browser/browser_switcher/browser_switcher_prefs.h" +#include "chrome/grit/generated_resources.h" #include "url/gurl.h" namespace browser_switcher { @@ -48,10 +49,13 @@ const struct { const wchar_t* var_name; const wchar_t* registry_key; + const char* browser_name; } kBrowserVarMappings[] = { - {kChromeVarName, kChromeKey}, {kIEVarName, kIExploreKey}, - {kFirefoxVarName, kFirefoxKey}, {kOperaVarName, kOperaKey}, - {kSafariVarName, kSafariKey}, + {kChromeVarName, kChromeKey, ""}, + {kIEVarName, kIExploreKey, "Internet Explorer"}, + {kFirefoxVarName, kFirefoxKey, "Mozilla Firefox"}, + {kOperaVarName, kOperaKey, "Opera"}, + {kSafariVarName, kSafariKey, "Safari"}, }; // DDE Callback function which is not used in our case at all. @@ -163,6 +167,17 @@ return (TryLaunchWithDde(url) || TryLaunchWithExec(url)); } +std::string AlternativeBrowserDriverImpl::GetBrowserName() const { + std::wstring path = base::UTF8ToWide(prefs_->GetAlternativeBrowserPath()); + if (path.empty()) + path = kIEVarName; + for (const auto& mapping : kBrowserVarMappings) { + if (!path.compare(mapping.var_name)) + return std::string(mapping.browser_name); + } + return std::string(); +} + bool AlternativeBrowserDriverImpl::TryLaunchWithDde(const GURL& url) { if (!IsInternetExplorer(prefs_->GetAlternativeBrowserPath())) return false;
diff --git a/chrome/browser/browser_switcher/mock_alternative_browser_driver.h b/chrome/browser/browser_switcher/mock_alternative_browser_driver.h index e4f4f49..8c99d94 100644 --- a/chrome/browser/browser_switcher/mock_alternative_browser_driver.h +++ b/chrome/browser/browser_switcher/mock_alternative_browser_driver.h
@@ -21,6 +21,7 @@ MOCK_CONST_METHOD1(ExpandEnvVars, void(std::string*)); MOCK_CONST_METHOD1(ExpandPresetBrowsers, void(std::string*)); MOCK_METHOD1(TryLaunch, bool(const GURL&)); + MOCK_CONST_METHOD0(GetBrowserName, std::string()); }; } // namespace browser_switcher
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc index 682536b..537a7e3 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -784,8 +784,9 @@ { base::RunLoop run_loop; video_decode_perf_history->GetSaveCallback().Run( - ukm::kInvalidSourceId, kIsTopFrame, prediction_features, - prediction_targets, kPlayerId, run_loop.QuitWhenIdleClosure()); + ukm::kInvalidSourceId, media::learning::FeatureValue(0), kIsTopFrame, + prediction_features, prediction_targets, kPlayerId, + run_loop.QuitWhenIdleClosure()); run_loop.Run(); }
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index d36e3bd..a4b4584 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -526,8 +526,7 @@ if (glue && ![glue isRegisteredAndActive]) { // If profile loading has failed, we still need to handle other tasks // like marking of the product as active. - [glue updateProfileCountsWithNumProfiles:0 - numSignedInProfiles:0]; + [glue setRegistrationActive]; } }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0e0148e4..34d0bdf6 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -436,7 +436,7 @@ #include "services/proxy_resolver/proxy_resolver_service.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" #include "ui/base/resource/resource_bundle_android.h" #include "ui/base/ui_base_paths.h" #elif defined(OS_POSIX) @@ -3688,20 +3688,18 @@ // process handle is not yet available at this point so pass in a callback // to allow to retrieve a duplicate at the time the interface is actually // created. It is safe to pass a raw pointer to |render_process_host|: the - // callback will be invoked in the context of ModuleDatabase::GetInstance, - // which is invoked by Mojo initialization, which occurs while the - // |render_process_host| is alive. + // callback will be invoked during the Mojo initialization, which occurs while + // the |render_process_host| is alive. auto get_process = base::BindRepeating( [](content::RenderProcessHost* host) -> base::Process { return host->GetProcess().Duplicate(); }, base::Unretained(render_process_host)); - // The ModuleDatabase is a global singleton so passing an unretained pointer - // is safe. registry->AddInterface( - base::BindRepeating(&ModuleEventSinkImpl::Create, std::move(get_process), - content::PROCESS_TYPE_RENDERER, - base::Unretained(ModuleDatabase::GetInstance())), + base::BindRepeating( + &ModuleEventSinkImpl::Create, std::move(get_process), + content::PROCESS_TYPE_RENDERER, + base::BindRepeating(&ModuleDatabase::HandleModuleLoadEvent)), ui_task_runner); #endif #if defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 22ae180..7dfd5e6 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -58,6 +58,7 @@ "//chrome/app:command_ids", "//chrome/browser/apps/platform_apps", "//chrome/browser/apps/platform_apps/api", + "//chrome/browser/chromeos/kiosk_next_home/mojom", "//chrome/browser/chromeos/power/ml/smart_dim", "//chrome/browser/devtools", "//chrome/browser/extensions", @@ -211,6 +212,7 @@ "//services/data_decoder/public/cpp", "//services/device/public/mojom", "//services/identity/public/cpp", + "//services/identity/public/mojom", "//services/metrics/public/cpp:ukm_builders", "//services/preferences/public/mojom", "//services/resource_coordinator/public/cpp:resource_coordinator_cpp", @@ -1026,6 +1028,10 @@ "input_method/input_method_persistence.h", "input_method/input_method_syncer.cc", "input_method/input_method_syncer.h", + "kiosk_next_home/app_controller_impl.cc", + "kiosk_next_home/app_controller_impl.h", + "kiosk_next_home/kiosk_next_home_interface_broker_impl.cc", + "kiosk_next_home/kiosk_next_home_interface_broker_impl.h", "language_preferences.cc", "language_preferences.h", "launcher_search_provider/error_reporter.cc",
diff --git a/chrome/browser/chromeos/android_sms/pairing_lost_notifier.cc b/chrome/browser/chromeos/android_sms/pairing_lost_notifier.cc index 613a70d..07b6f196 100644 --- a/chrome/browser/chromeos/android_sms/pairing_lost_notifier.cc +++ b/chrome/browser/chromeos/android_sms/pairing_lost_notifier.cc
@@ -125,7 +125,8 @@ &PairingLostNotifier::OnPairingLostNotificationClick, weak_ptr_factory_.GetWeakPtr())), ash::kNotificationMessagesIcon, - message_center::SystemNotificationWarningLevel::NORMAL)); + message_center::SystemNotificationWarningLevel::NORMAL), + /*metadata=*/nullptr); } void PairingLostNotifier::ClosePairingLostNotificationIfVisible() {
diff --git a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc index 94ccad3..fabde3b 100644 --- a/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc +++ b/chrome/browser/chromeos/arc/arc_migration_guide_notification.cc
@@ -72,7 +72,8 @@ notification->set_renotify(true); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc index 8e77dfe2..5de194c5f 100644 --- a/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc +++ b/chrome/browser/chromeos/arc/file_system_watcher/arc_file_system_watcher_service.cc
@@ -52,6 +52,10 @@ constexpr base::FilePath::CharType kAndroidMyFilesDir[] = FILE_PATH_LITERAL("/storage/MyFiles"); +// The path for Downloads under MyFiles inside ARC container. +constexpr base::FilePath::CharType kAndroidMyFilesDownloadsDir[] = + FILE_PATH_LITERAL("/storage/MyFiles/Downloads/"); + // The removable media path in ChromeOS. This is the actual directory to be // watched. constexpr base::FilePath::CharType kCrosRemovableMediaDir[] = @@ -479,7 +483,19 @@ arc_bridge_service_->file_system(), RequestMediaScan); if (!instance) return; - instance->RequestMediaScan(paths); + + std::vector<std::string> filtered_paths; + for (const std::string& path : paths) { + if (base::StartsWith(path, kAndroidMyFilesDownloadsDir, + base::CompareCase::SENSITIVE)) { + // Exclude files under /storage/MyFiles/Downloads/ because they are also + // indexed as files under /storage/emulated/0/Download/ + continue; + } + filtered_paths.push_back(path); + } + + instance->RequestMediaScan(filtered_paths); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc b/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc index e1520299..484b542 100644 --- a/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc +++ b/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc
@@ -83,7 +83,8 @@ ash::kNotificationStorageFullIcon, message_center::SystemNotificationWarningLevel::CRITICAL_WARNING); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } // Singleton factory for ArcBootErrorNotificationFactory.
diff --git a/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc b/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc index 30c18a7..ea7ed4b 100644 --- a/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc +++ b/chrome/browser/chromeos/arc/notification/arc_provision_notification_service.cc
@@ -97,7 +97,7 @@ notifier_id, optional_fields, new message_center::NotificationDelegate()); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); } void ArcProvisionNotificationService::HideNotification() {
diff --git a/chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.cc b/chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.cc index 478cd42..6cf1487 100644 --- a/chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.cc +++ b/chrome/browser/chromeos/arc/notification/arc_supervision_transition_notification.cc
@@ -108,7 +108,8 @@ new NotificationDelegate(profile), ash::kNotificationFamilyLinkIcon, message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/screen_capture/arc_screen_capture_session.cc b/chrome/browser/chromeos/arc/screen_capture/arc_screen_capture_session.cc index 83097fc1..83f37d1 100644 --- a/chrome/browser/chromeos/arc/screen_capture/arc_screen_capture_session.cc +++ b/chrome/browser/chromeos/arc/screen_capture/arc_screen_capture_session.cc
@@ -284,9 +284,10 @@ return; // Get the source texture - GLuint src_texture = gl_helper_->ConsumeMailboxToTexture( - result->GetTextureResult()->mailbox, - result->GetTextureResult()->sync_token); + gl->WaitSyncTokenCHROMIUM( + result->GetTextureResult()->sync_token.GetConstData()); + GLuint src_texture = gl->CreateAndConsumeTextureCHROMIUM( + result->GetTextureResult()->mailbox.name); std::unique_ptr<viz::SingleReleaseCallback> release_callback = result->TakeTextureOwnership();
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc index 12056c7..66a8dd76 100644 --- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc +++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
@@ -27,7 +27,7 @@ #include "chromeos/components/account_manager/account_manager.h" #include "chromeos/components/account_manager/account_manager_factory.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_state.h" @@ -286,7 +286,8 @@ // Add the notification. NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); shown_notifications_.insert(message_id); }
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager_unittest.cc b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager_unittest.cc index 8d02676..543e0016 100644 --- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager_unittest.cc +++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager_unittest.cc
@@ -16,8 +16,8 @@ #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/network/network_handler.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc index 0dfdb96..85816ff9 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.cc
@@ -64,10 +64,11 @@ } // namespace std::unique_ptr<base::DictionaryValue> ConvertGoldenInputToProcessorInput( - ConsistencyGoldenInput input) { - // An arbitrary date representing the last time the policies were updated, - // since the tests won't take this into account for now. - base::Time last_updated = utils::TimeFromString("1 Jan 2018 10:00 GMT+0300"); + const ConsistencyGoldenInput& input) { + // Random date representing the last time the policies were updated, + // used whenever the last_updated field is not specified in the input proto. + base::Time default_last_updated = + utils::TimeFromString("1 Jan 2018 10:00 GMT+0300"); base::TimeDelta resets_at = input.has_usage_limit_resets_at() ? utils::CreateTime(input.usage_limit_resets_at().hour(), @@ -88,7 +89,9 @@ window_limit.starts_at().minute()), utils::CreateTime(window_limit.ends_at().hour(), window_limit.ends_at().minute()), - last_updated); + window_limit.has_last_updated_millis() + ? base::Time::FromJavaTime(window_limit.last_updated_millis()) + : default_last_updated); } /* End Window Limits data */ @@ -100,16 +103,37 @@ policy.get(), ConvertGoldenDayToProcessorDay(usage_limit.effective_day()), base::TimeDelta::FromMinutes(usage_limit.usage_quota_mins()), - last_updated); + usage_limit.has_last_updated_millis() + ? base::Time::FromJavaTime(usage_limit.last_updated_millis()) + : default_last_updated); } /* End Usage Limits data */ + /* Begin Overrides data */ + + for (const ConsistencyGoldenOverride& override_entry : input.overrides()) { + if (override_entry.action() == UNLOCK_UNTIL_LOCK_DEADLINE) { + utils::AddOverrideWithDuration( + policy.get(), usage_time_limit::TimeLimitOverride::Action::kUnlock, + base::Time::FromJavaTime(override_entry.created_at_millis()), + base::TimeDelta::FromMilliseconds(override_entry.duration_millis())); + } else { + utils::AddOverride( + policy.get(), + override_entry.action() == LOCK + ? usage_time_limit::TimeLimitOverride::Action::kLock + : usage_time_limit::TimeLimitOverride::Action::kUnlock, + base::Time::FromJavaTime(override_entry.created_at_millis())); + } + } + + /* End Overrides data */ return policy; } ConsistencyGoldenOutput ConvertProcessorOutputToGoldenOutput( - usage_time_limit::State state) { + const usage_time_limit::State& state) { ConsistencyGoldenOutput golden_output; golden_output.set_is_locked(state.is_locked); @@ -118,7 +142,8 @@ golden_output.set_next_active_policy( ConvertProcessorPolicyToGoldenPolicy(state.next_state_active_policy)); - if (state.is_time_usage_limit_enabled) { + if (state.is_time_usage_limit_enabled && + golden_output.active_policy() != OVERRIDE) { golden_output.set_remaining_quota_millis( state.remaining_usage.InMilliseconds()); } @@ -131,5 +156,35 @@ return golden_output; } +base::Optional<usage_time_limit::State> +GenerateUnlockUsageLimitOverrideStateFromInput( + const ConsistencyGoldenInput& input) { + const ConsistencyGoldenOverride* usage_limit_override = nullptr; + for (const ConsistencyGoldenOverride& override_entry : input.overrides()) { + if (override_entry.action() == UNLOCK_USAGE_LIMIT && + (!usage_limit_override || + override_entry.created_at_millis() > + usage_limit_override->created_at_millis())) { + usage_limit_override = &override_entry; + } + } + + if (!usage_limit_override) + return base::nullopt; + + usage_time_limit::State previous_state; + previous_state.is_locked = true; + previous_state.active_policy = usage_time_limit::ActivePolicies::kUsageLimit; + previous_state.is_time_usage_limit_enabled = true; + previous_state.remaining_usage = base::TimeDelta::FromMinutes(0); + + // Usage limit started one minute before the override was created. + previous_state.time_usage_limit_started = + base::Time::FromJavaTime(usage_limit_override->created_at_millis()) - + base::TimeDelta::FromMinutes(1); + + return previous_state; +} + } // namespace time_limit_consistency } // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h index 5d55e1a..1357471f 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h
@@ -10,6 +10,7 @@ #include <memory> +#include "base/optional.h" #include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h" #include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h" @@ -23,12 +24,21 @@ // Converts the input part of a consistency golden case to the structure used by // the time limit processor. std::unique_ptr<base::DictionaryValue> ConvertGoldenInputToProcessorInput( - ConsistencyGoldenInput input); + const ConsistencyGoldenInput& input); // Converts the output struct generated by the time limit processor to the // consistency golden output proto. ConsistencyGoldenOutput ConvertProcessorOutputToGoldenOutput( - usage_time_limit::State state); + const usage_time_limit::State& state); + +// Generates a State struct representing the previous state required by the +// processor if there is a UNLOCK_USAGE_LIMIT override present. The generated +// state simulates being locked by usage limit since one minute before the +// override was created. +// If the override is of another type, base::nullopt will be returned. +base::Optional<usage_time_limit::State> +GenerateUnlockUsageLimitOverrideStateFromInput( + const ConsistencyGoldenInput& input); } // namespace time_limit_consistency } // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc index 711c3ee..0c035e0 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter_unittest.cc
@@ -47,15 +47,17 @@ utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); // First window: Wednesday, 22:30 to 8:00 - consistency_utils::AddWindowLimitEntryToGoldenInput(&input, WEDNESDAY, 22, 30, - 8, 0); + consistency_utils::AddWindowLimitEntryToGoldenInput( + &input, WEDNESDAY, consistency_utils::TimeOfDay({22, 30}), + consistency_utils::TimeOfDay({8, 0}), base::nullopt); utils::AddTimeWindowLimit(expected_output.get(), utils::kWednesday, utils::CreateTime(22, 30), utils::CreateTime(8, 0), kTestLastUpdated); // Second window: Saturday, 18:45 to 22:30 - consistency_utils::AddWindowLimitEntryToGoldenInput(&input, SATURDAY, 18, 45, - 22, 30); + consistency_utils::AddWindowLimitEntryToGoldenInput( + &input, SATURDAY, consistency_utils::TimeOfDay({18, 45}), + consistency_utils::TimeOfDay({22, 30}), base::nullopt); utils::AddTimeWindowLimit(expected_output.get(), utils::kSaturday, utils::CreateTime(18, 45), utils::CreateTime(22, 30), kTestLastUpdated); @@ -66,6 +68,25 @@ EXPECT_TRUE(*actual_output == *expected_output); } +TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithBedtimesLastUpdated) { + ConsistencyGoldenInput input; + std::unique_ptr<base::DictionaryValue> expected_output = + utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); + + // First window: Wednesday, 22:30 to 8:00 + consistency_utils::AddWindowLimitEntryToGoldenInput( + &input, WEDNESDAY, consistency_utils::TimeOfDay({22, 30}), + consistency_utils::TimeOfDay({8, 0}), kTestTimestamp); + utils::AddTimeWindowLimit(expected_output.get(), utils::kWednesday, + utils::CreateTime(22, 30), utils::CreateTime(8, 0), + base::Time::FromJavaTime(kTestTimestamp)); + + std::unique_ptr<base::DictionaryValue> actual_output = + ConvertGoldenInputToProcessorInput(input); + + EXPECT_TRUE(*actual_output == *expected_output); +} + TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithUsageLimit) { ConsistencyGoldenInput input; std::unique_ptr<base::DictionaryValue> expected_output = @@ -75,12 +96,14 @@ input.mutable_usage_limit_resets_at()->set_minute(30); // First quota: Tuesday, 60 minutes - consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60); + consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60, + base::nullopt); utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday, base::TimeDelta::FromMinutes(60), kTestLastUpdated); // Second quota: Friday, 30 minutes - consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30); + consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30, + base::nullopt); utils::AddTimeUsageLimit(expected_output.get(), utils::kFriday, base::TimeDelta::FromMinutes(30), kTestLastUpdated); @@ -96,12 +119,14 @@ utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); // First quota: Tuesday, 60 minutes - consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60); + consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60, + base::nullopt); utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday, base::TimeDelta::FromMinutes(60), kTestLastUpdated); // Second quota: Friday, 30 minutes - consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30); + consistency_utils::AddUsageLimitEntryToGoldenInput(&input, FRIDAY, 30, + base::nullopt); utils::AddTimeUsageLimit(expected_output.get(), utils::kFriday, base::TimeDelta::FromMinutes(30), kTestLastUpdated); @@ -111,6 +136,63 @@ EXPECT_TRUE(*actual_output == *expected_output); } +TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithUsageLimitLastUpdated) { + ConsistencyGoldenInput input; + std::unique_ptr<base::DictionaryValue> expected_output = + utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); + + // First quota: Tuesday, 60 minutes + consistency_utils::AddUsageLimitEntryToGoldenInput(&input, TUESDAY, 60, + kTestTimestamp); + utils::AddTimeUsageLimit(expected_output.get(), utils::kTuesday, + base::TimeDelta::FromMinutes(60), + base::Time::FromJavaTime(kTestTimestamp)); + + std::unique_ptr<base::DictionaryValue> actual_output = + ConvertGoldenInputToProcessorInput(input); + + EXPECT_TRUE(*actual_output == *expected_output); +} + +TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithOverride) { + ConsistencyGoldenInput input; + std::unique_ptr<base::DictionaryValue> expected_output = + utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); + + // Override: Unlock bedtime + consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_WINDOW_LIMIT, + kTestTimestamp); + utils::AddOverride(expected_output.get(), + usage_time_limit::TimeLimitOverride::Action::kUnlock, + base::Time::FromJavaTime(kTestTimestamp)); + + std::unique_ptr<base::DictionaryValue> actual_output = + ConvertGoldenInputToProcessorInput(input); + + EXPECT_TRUE(*actual_output == *expected_output); +} + +TEST_F(ConsistencyGoldenConverterTest, ConvertInputWithTimedOverride) { + ConsistencyGoldenInput input; + std::unique_ptr<base::DictionaryValue> expected_output = + utils::CreateTimeLimitPolicy(base::TimeDelta::FromHours(6)); + const int64_t override_duration_millis = 10000; + + // Override: Grant more time + consistency_utils::AddTimedOverrideToGoldenInput( + &input, override_duration_millis, kTestTimestamp); + utils::AddOverrideWithDuration( + expected_output.get(), + usage_time_limit::TimeLimitOverride::Action::kUnlock, + base::Time::FromJavaTime(kTestTimestamp), + base::TimeDelta::FromMilliseconds(override_duration_millis)); + + std::unique_ptr<base::DictionaryValue> actual_output = + ConvertGoldenInputToProcessorInput(input); + + EXPECT_TRUE(*actual_output == *expected_output); +} + TEST_F(ConsistencyGoldenConverterTest, ConvertOutputWhenUnlocked) { usage_time_limit::State state; state.is_locked = false; @@ -175,5 +257,34 @@ EXPECT_THAT(actual_output, EqualsProto(expected_output)); } +TEST_F(ConsistencyGoldenConverterTest, GeneratePreviousStateUnlockUsageLimit) { + ConsistencyGoldenInput input; + consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_USAGE_LIMIT, + kTestTimestamp); + + base::Optional<usage_time_limit::State> generated_state = + GenerateUnlockUsageLimitOverrideStateFromInput(input); + + EXPECT_TRUE(generated_state->is_locked); + EXPECT_TRUE(generated_state->is_time_usage_limit_enabled); + EXPECT_EQ(generated_state->active_policy, + usage_time_limit::ActivePolicies::kUsageLimit); + EXPECT_EQ(generated_state->remaining_usage, base::TimeDelta::FromMinutes(0)); + EXPECT_EQ(generated_state->time_usage_limit_started, + base::Time::FromJavaTime(kTestTimestamp) - + base::TimeDelta::FromMinutes(1)); +} + +TEST_F(ConsistencyGoldenConverterTest, GeneratePreviousStateOtherOverrides) { + ConsistencyGoldenInput input; + consistency_utils::AddOverrideToGoldenInput(&input, UNLOCK_WINDOW_LIMIT, + kTestTimestamp); + + base::Optional<usage_time_limit::State> generated_state = + GenerateUnlockUsageLimitOverrideStateFromInput(input); + + EXPECT_EQ(generated_state, base::nullopt); +} + } // namespace time_limit_consistency } // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc index 789c563d..ecb2d8a 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test.cc
@@ -34,14 +34,15 @@ base::Time::FromJavaTime(current_state.time_millis()); base::Time usage_timestamp = base::Time::FromJavaTime(current_state.usage_timestamp()); + base::Optional<usage_time_limit::State> previous_state = + GenerateUnlockUsageLimitOverrideStateFromInput(golden_case.input()); std::unique_ptr<base::DictionaryValue> policy = ConvertGoldenInputToProcessorInput(golden_case.input()); usage_time_limit::State state = usage_time_limit::GetState( policy, /* local_override */ nullptr, base::TimeDelta::FromMilliseconds(current_state.usage_millis()), - usage_timestamp, current_time, timezone, - /* previous_state */ base::nullopt); + usage_timestamp, current_time, timezone, previous_state); ConsistencyGoldenOutput actual_output = ConvertProcessorOutputToGoldenOutput(state);
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc index b45e8886f..ba83796 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.cc
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_golden_converter.h" +#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h" +#include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h" namespace chromeos { namespace time_limit_consistency_utils { @@ -10,27 +11,57 @@ void AddWindowLimitEntryToGoldenInput( time_limit_consistency::ConsistencyGoldenInput* golden_input, time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day, - int starts_at_hour, - int starts_at_minute, - int ends_at_hour, - int ends_at_minute) { + const TimeOfDay& starts_at, + const TimeOfDay& ends_at, + base::Optional<int64_t> last_updated) { time_limit_consistency::ConsistencyGoldenWindowLimitEntry* window = golden_input->add_window_limits(); - window->mutable_starts_at()->set_hour(starts_at_hour); - window->mutable_starts_at()->set_minute(starts_at_minute); - window->mutable_ends_at()->set_hour(ends_at_hour); - window->mutable_ends_at()->set_minute(ends_at_minute); + window->mutable_starts_at()->set_hour(starts_at.hour); + window->mutable_starts_at()->set_minute(starts_at.minute); + window->mutable_ends_at()->set_hour(ends_at.hour); + window->mutable_ends_at()->set_minute(ends_at.minute); window->set_effective_day(effective_day); + + if (last_updated) + window->set_last_updated_millis(last_updated.value()); } void AddUsageLimitEntryToGoldenInput( time_limit_consistency::ConsistencyGoldenInput* golden_input, time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day, - int usage_quota_mins) { + int usage_quota_mins, + base::Optional<int64_t> last_updated) { time_limit_consistency::ConsistencyGoldenUsageLimitEntry* usage_limit = golden_input->add_usage_limits(); usage_limit->set_usage_quota_mins(usage_quota_mins); usage_limit->set_effective_day(effective_day); + + if (last_updated) + usage_limit->set_last_updated_millis(last_updated.value()); +} + +void AddOverrideToGoldenInput( + time_limit_consistency::ConsistencyGoldenInput* golden_input, + time_limit_consistency::ConsistencyGoldenOverrideAction action, + int64_t created_at) { + DCHECK(action != time_limit_consistency::UNLOCK_UNTIL_LOCK_DEADLINE); + + time_limit_consistency::ConsistencyGoldenOverride* override_entry = + golden_input->add_overrides(); + override_entry->set_action(action); + override_entry->set_created_at_millis(created_at); +} + +void AddTimedOverrideToGoldenInput( + time_limit_consistency::ConsistencyGoldenInput* golden_input, + int64_t duration_millis, + int64_t created_at) { + time_limit_consistency::ConsistencyGoldenOverride* override_entry = + golden_input->add_overrides(); + override_entry->set_action( + time_limit_consistency::UNLOCK_UNTIL_LOCK_DEADLINE); + override_entry->set_duration_millis(duration_millis); + override_entry->set_created_at_millis(created_at); } } // namespace time_limit_consistency_utils
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h index 4f6c76d..cb16c00 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/consistency_test_utils.h
@@ -7,25 +7,48 @@ #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_CONSISTENCY_TEST_CONSISTENCY_TEST_UTILS_H_ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMIT_CONSISTENCY_TEST_CONSISTENCY_TEST_UTILS_H_ +#include "base/optional.h" #include "chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.pb.h" namespace chromeos { namespace time_limit_consistency_utils { +// A time of day composed of hours and minutes, used when generating bedtime +// entries. +struct TimeOfDay { + int hour; + int minute; +}; + // Adds a time window limit entry to the provided ConsistencyGoldenInput. void AddWindowLimitEntryToGoldenInput( time_limit_consistency::ConsistencyGoldenInput* golden_input, time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day, - int starts_at_hour, - int starts_at_minute, - int ends_at_hour, - int ends_at_minute); + const TimeOfDay& starts_at, + const TimeOfDay& ends_at, + base::Optional<int64_t> last_updated); // Adds a usage limit entry to the provided ConsistencyGoldenInput. void AddUsageLimitEntryToGoldenInput( time_limit_consistency::ConsistencyGoldenInput* golden_input, time_limit_consistency::ConsistencyGoldenEffectiveDay effective_day, - int usage_quota_mins); + int usage_quota_mins, + base::Optional<int64_t> last_updated); + +// Adds an override to the provided ConsistencyGoldenInput. Must not be used +// for UNLOCK_UNTIL_LOCK_DEADLINE actions (will DCHECK()), use +// AddTimedOverrideToGoldenInput() instead. +void AddOverrideToGoldenInput( + time_limit_consistency::ConsistencyGoldenInput* golden_input, + time_limit_consistency::ConsistencyGoldenOverrideAction action, + int64_t created_at); + +// Adds a timed override (UNLOCK_UNTIL_LOCK_DEADLINE action) with duration set +// to |duration_millis| to the provided ConsistencyGoldenInput. +void AddTimedOverrideToGoldenInput( + time_limit_consistency::ConsistencyGoldenInput* golden_input, + int64_t duration_millis, + int64_t created_at); } // namespace time_limit_consistency_utils } // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto index 29d87af1..f187160 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto
@@ -23,6 +23,18 @@ USAGE_LIMIT = 4; } +// Actions that an override can take. +enum ConsistencyGoldenOverrideAction { + UNSPECIFIED_ACTION = 0; + LOCK = 1; + UNLOCK_USAGE_LIMIT = 2; + UNLOCK_WINDOW_LIMIT = 3; + // Deprecated but kept here for easier conversion to/from the original enum. + UNLOCK_LOCK_OVERRIDE = 4 [deprecated = true]; + UNLOCK_WITH_DEADLINE = 5; + UNLOCK_UNTIL_LOCK_DEADLINE = 6; +} + // Days of the week. enum ConsistencyGoldenEffectiveDay { UNSPECIFIED_EFFECTIVE_DAY = 0; @@ -68,6 +80,9 @@ // List of usage time configurations for different days of the week. repeated ConsistencyGoldenUsageLimitEntry usage_limits = 3; + + // List of overrides currently active. + repeated ConsistencyGoldenOverride overrides = 4; } // Bedtime configuration for a given day. @@ -80,6 +95,10 @@ // At which hour and minute this bedtime should end. Required optional ConsistencyGoldenTimeOfDay ends_at = 3; + + // The moment when this configuration was last updated. Optional but some more + // complex scenarios may require it. + optional int64 last_updated_millis = 4; } // Usage limit configuration for a given day. @@ -89,6 +108,22 @@ // Available usage quota for this day in minutes. Required (0 means no quota). optional int32 usage_quota_mins = 2; + + // The moment when this configuration was last updated. Optional but some more + // complex scenarios may require it. + optional int64 last_updated_millis = 3; +} + +// Represents an override that is currently active. +message ConsistencyGoldenOverride { + // What this override does. Required + optional ConsistencyGoldenOverrideAction action = 1; + + // Moment when this override was created, in millis. Required. + optional int64 created_at_millis = 2; + + // The duration of the unlock, if it is of type "UNLOCK_UNTIL_LOCK_DEADLINE". + optional int64 duration_millis = 3; } // Represents a moment of a day.
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto new file mode 100644 index 0000000..d929032 --- /dev/null +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_bedtimes.textproto
@@ -0,0 +1,110 @@ +supported_platforms: [ANDROID, CHROME_OS] + +# Override created while bedtime is active +cases { + input { + window_limits { + effective_day: MONDAY + starts_at { + hour: 23 + minute: 0 + } + ends_at { + hour: 8 + minute: 0 + } + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Monday, Jan 28th 2019 at 11:29pm + created_at_millis: 1548718140000 + } + } + current_state { + # Monday, Jan 28th 2019 at 11:30pm + time_millis: 1548718200000 + timezone: "GMT" + } + output { + is_locked: false + active_policy: OVERRIDE + next_active_policy: FIXED_LIMIT + } +} + +# Override created before bedtime started +cases { + input { + window_limits { + effective_day: MONDAY + starts_at { + hour: 23 + minute: 0 + } + ends_at { + hour: 8 + minute: 0 + } + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Monday, Jan 28th 2019 at 10:30pm + created_at_millis: 1548714600000 + } + } + current_state { + # Monday, Jan 28th 2019 at 11:30pm + time_millis: 1548718200000 + timezone: "GMT" + } + output { + is_locked: true + active_policy: FIXED_LIMIT + # Tuesday, Jan 29th 2019 at 8:00am + next_unlocking_time_millis: 1548748800000 + next_active_policy: NO_ACTIVE_POLICY + } +} + +# Override created during intersection of bedtimes +cases { + input { + window_limits { + effective_day: MONDAY + starts_at { + hour: 23 + minute: 0 + } + ends_at { + hour: 8 + minute: 0 + } + } + window_limits { + effective_day: TUESDAY + starts_at { + hour: 2 + minute: 0 + } + ends_at { + hour: 11 + minute: 0 + } + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Tuesday, Jan 29th 2019 at 2:20am + created_at_millis: 1548728400000 + } + } + current_state { + # Tuesday, Jan 29th 2019 at 2:30am + time_millis: 1548729000000 + timezone: "GMT" + } + output { + is_locked: false + active_policy: OVERRIDE + next_active_policy: FIXED_LIMIT + } +}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto new file mode 100644 index 0000000..515e1db5 --- /dev/null +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_then_modify.textproto
@@ -0,0 +1,102 @@ +supported_platforms: [ANDROID, CHROME_OS] + +# Override created for bedtime, then bedtime is altered. +cases { + input { + window_limits { + effective_day: MONDAY + starts_at { + hour: 23 + minute: 0 + } + ends_at { + hour: 8 + minute: 0 + } + # Monday, Jan 28th 2019 at 11:25pm + last_updated_millis: 1548717900000 + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Monday, Jan 28th 2019 at 11:20pm + created_at_millis: 1548717600000 + } + } + current_state { + # Monday, Jan 28th 2019 at 11:30pm + time_millis: 1548718200000 + timezone: "GMT" + } + output { + is_locked: true + active_policy: FIXED_LIMIT + next_active_policy: NO_ACTIVE_POLICY + # Tuesday, Jan 29th 2019 at 8:00am + next_unlocking_time_millis: 1548748800000 + } +} + +# Override created after hitting usage limit, then usage limit quota is updated +# to a value bigger than the current usage. +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 120 + # Thursday, Feb 21st 2019 at 2:50pm + last_updated_millis: 1550760600000 + } + overrides { + action: UNLOCK_USAGE_LIMIT + # Thursday, Feb 21st 2019 at 2:40pm + created_at_millis: 1550760000000 + } + } + current_state { + # Thursday, Feb 21st 2019 at 3:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 1 hour + usage_millis: 3600000 + } + output { + is_locked: false + active_policy: NO_ACTIVE_POLICY + next_active_policy: USAGE_LIMIT + # 1 hour + remaining_quota_millis: 3600000 + } +} + +# Override created after hitting usage limit, then usage limit quota is updated +# to a value smaller than the current usage. +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 45 + # Thursday, Feb 21st 2019 at 2:50pm + last_updated_millis: 1550760600000 + } + overrides { + action: UNLOCK_USAGE_LIMIT + # Thursday, Feb 21st 2019 at 2:40pm + created_at_millis: 1550760000000 + } + } + current_state { + # Thursday, Feb 21st 2019 at 3:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 1 hour + usage_millis: 3600000 + } + output { + is_locked: true + active_policy: USAGE_LIMIT + # Friday, Feb 22nd 2019 at 6:00am + next_unlocking_time_millis: 1550815200000 + next_active_policy: NO_ACTIVE_POLICY + remaining_quota_millis: 0 + } +}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto new file mode 100644 index 0000000..77ce4298 --- /dev/null +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_android.textproto
@@ -0,0 +1,61 @@ +# There is a different behavior on Android and ChromeOS for the first test case +# so they are split in two different suites temporarily. + +supported_platforms: [ANDROID] + +# Override created while usage limit is active +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 120 + } + overrides { + action: UNLOCK_USAGE_LIMIT + # Thursday, Feb 21th 2019 at 14:50pm + created_at_millis: 1550760600000 + } + } + current_state { + # Thursday, Feb 21th 2019 at 15:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 2 hours + usage_millis: 7200000 + } + output { + is_locked: false + active_policy: OVERRIDE + next_active_policy: USAGE_LIMIT + } +} + +# Usage limit reached while other override is in place +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 120 + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Thursday, Feb 21th 2019 at 14:50pm + created_at_millis: 1550760600000 + } + } + current_state { + # Thursday, Feb 21th 2019 at 15:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 2 hours + usage_millis: 7200000 + } + output { + is_locked: true + active_policy: USAGE_LIMIT + next_active_policy: NO_ACTIVE_POLICY + remaining_quota_millis: 0 + # Friday, Feb 22nd 2019 at 6:00am + next_unlocking_time_millis: 1550815200000 + } +}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto new file mode 100644 index 0000000..e123418d --- /dev/null +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/override_usage_limits_cros.textproto
@@ -0,0 +1,61 @@ +# There is a different behavior on Android and ChromeOS for the first test case +# so they are split in two different suites temporarily. + +supported_platforms: [CHROME_OS] + +# Override created while usage limit is active +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 120 + } + overrides { + action: UNLOCK_USAGE_LIMIT + # Thursday, Feb 21th 2019 at 14:50pm + created_at_millis: 1550760600000 + } + } + current_state { + # Thursday, Feb 21th 2019 at 15:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 2 hours + usage_millis: 7200000 + } + output { + is_locked: false + active_policy: OVERRIDE + next_active_policy: NO_ACTIVE_POLICY + } +} + +# Usage limit reached while other override is in place +cases { + input { + usage_limits { + effective_day: THURSDAY + usage_quota_mins: 120 + } + overrides { + action: UNLOCK_WINDOW_LIMIT + # Thursday, Feb 21th 2019 at 14:50pm + created_at_millis: 1550760600000 + } + } + current_state { + # Thursday, Feb 21th 2019 at 15:00pm + time_millis: 1550761200000 + timezone: "GMT" + # 2 hours + usage_millis: 7200000 + } + output { + is_locked: true + active_policy: USAGE_LIMIT + next_active_policy: NO_ACTIVE_POLICY + remaining_quota_millis: 0 + # Friday, Feb 22nd 2019 at 6:00am + next_unlocking_time_millis: 1550815200000 + } +}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto new file mode 100644 index 0000000..db0ceed --- /dev/null +++ b/chrome/browser/chromeos/child_accounts/time_limit_consistency_test/goldens/simple_override.textproto
@@ -0,0 +1,24 @@ +supported_platforms: [ANDROID, CHROME_OS] + +# Create a simple lock override. +cases { + input { + overrides { + action: LOCK + # Thursday, Feb 21st 2019 at 14:50pm + created_at_millis: 1550760600000 + } + } + current_state { + # Thursday, Feb 21st 2019 at 15:00pm + time_millis: 1550761200000 + timezone: "GMT" + } + output { + is_locked: true + active_policy: OVERRIDE + # Friday, Feb 22nd 2019 at 6:00am + next_unlocking_time_millis: 1550815200000 + next_active_policy: NO_ACTIVE_POLICY + } +}
diff --git a/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc b/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc index 93d5d76..bce0e26 100644 --- a/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc +++ b/chrome/browser/chromeos/child_accounts/time_limit_notifier.cc
@@ -59,7 +59,8 @@ message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile( Profile::FromBrowserContext(context)) - ->Display(NotificationHandler::Type::TRANSIENT, *notification); + ->Display(NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } } // namespace
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import_notification.cc b/chrome/browser/chromeos/crostini/crostini_export_import_notification.cc index 476420d3..480a54e 100644 --- a/chrome/browser/chromeos/crostini/crostini_export_import_notification.cc +++ b/chrome/browser/chromeos/crostini/crostini_export_import_notification.cc
@@ -115,7 +115,8 @@ NOTREACHED(); } NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification_); + NotificationHandler::Type::TRANSIENT, *notification_, + /*metadata=*/nullptr); } void CrostiniExportImportNotification::Close(bool by_user) {
diff --git a/chrome/browser/chromeos/crostini/crostini_package_notification.cc b/chrome/browser/chromeos/crostini/crostini_package_notification.cc index 29698c3..1be09cd 100644 --- a/chrome/browser/chromeos/crostini/crostini_package_notification.cc +++ b/chrome/browser/chromeos/crostini/crostini_package_notification.cc
@@ -224,8 +224,8 @@ NotificationDisplayService* display_service = NotificationDisplayService::GetForProfile(profile_); - display_service->Display(NotificationHandler::Type::TRANSIENT, - *notification_); + display_service->Display(NotificationHandler::Type::TRANSIENT, *notification_, + /*metadata=*/nullptr); } } // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.cc b/chrome/browser/chromeos/crostini/crostini_share_path.cc index 99622b2..edfe05c 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/optional.h" +#include "base/task/post_task.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" #include "chrome/browser/chromeos/crostini/crostini_share_path_factory.h" @@ -16,12 +17,14 @@ #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/volume_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chromeos/components/drivefs/mojom/drivefs.mojom.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/concierge/service.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/seneschal_client.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_url.h" @@ -36,6 +39,7 @@ std::move(callback).Run(base::FilePath(), false, "System error"); return; } + std::move(callback).Run(base::FilePath(response.value().path()), response.value().success(), response.value().failure_reason()); @@ -122,19 +126,43 @@ namespace crostini { +SharedPathInfo::SharedPathInfo(const std::string& vm_name) { + vm_names.insert(vm_name); +} +SharedPathInfo::SharedPathInfo(SharedPathInfo&&) = default; +SharedPathInfo::~SharedPathInfo() = default; + CrostiniSharePath* CrostiniSharePath::GetForProfile(Profile* profile) { return CrostiniSharePathFactory::GetForProfile(profile); } CrostiniSharePath::CrostiniSharePath(Profile* profile) : profile_(profile), + sequenced_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE})), mount_event_seneschal_callback_(base::BindRepeating(LogErrorResult)) { if (auto* vmgr = file_manager::VolumeManager::Get(profile_)) { vmgr->AddObserver(this); } + + // We receive notifications from DriveFS about any deleted paths so + // that we can remove any that are shared paths. + if (auto* integration_service = + drive::DriveIntegrationServiceFactory::FindForProfile(profile_)) { + if (integration_service->GetDriveFsHost()) { + integration_service->GetDriveFsHost()->AddObserver(this); + } + } } -CrostiniSharePath::~CrostiniSharePath() {} +CrostiniSharePath::~CrostiniSharePath() { + for (auto& shared_path : shared_paths_) { + if (shared_path.second.watcher) { + sequenced_task_runner_->DeleteSoon(FROM_HERE, + shared_path.second.watcher.release()); + } + } +} void CrostiniSharePath::AddObserver(Observer* obs) { observers_.AddObserver(obs); @@ -249,6 +277,7 @@ if (persist) { RegisterPersistedPath(path); } + RegisterSharedPath(path, vm_name); request.mutable_shared_path()->set_path(relative_path.value()); request.mutable_shared_path()->set_writable(true); @@ -340,16 +369,30 @@ void CrostiniSharePath::UnsharePath( const std::string& vm_name, const base::FilePath& path, + bool unpersist, base::OnceCallback<void(bool, std::string)> callback) { - PrefService* pref_service = profile_->GetPrefs(); - ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); - base::ListValue* shared_paths = update.Get(); - if (!shared_paths->Remove(base::Value(path.value()), nullptr)) { - LOG(WARNING) << "Unshared path not in prefs: " << path.value(); + if (auto* info = FindSharedPathInfo(path)) { + info->vm_names.erase(vm_name); + if (info->vm_names.empty()) { + if (info->watcher) { + sequenced_task_runner_->DeleteSoon(FROM_HERE, info->watcher.release()); + } + shared_paths_.erase(path); + } } + + if (unpersist) { + PrefService* pref_service = profile_->GetPrefs(); + ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); + base::ListValue* shared_paths = update.Get(); + if (!shared_paths->Remove(base::Value(path.value()), nullptr)) { + LOG(WARNING) << "Unshared path not in prefs: " << path.value(); + } + } + CallSeneschalUnsharePath(vm_name, path, std::move(callback)); for (Observer& observer : observers_) { - observer.OnUnshare(path); + observer.OnUnshare(path, vm_name); } } @@ -378,6 +421,7 @@ } migrated_paths.AppendString(path.value()); result.emplace_back(path); + RegisterSharedPath(path, kCrostiniDefaultVmName); } // If any paths were modified during migration, update prefs. @@ -419,12 +463,17 @@ void CrostiniSharePath::OnVolumeMounted(chromeos::MountError error_code, const file_manager::Volume& volume) { - if (error_code != chromeos::MountError::MOUNT_ERROR_NONE || - !crostini::CrostiniManager::GetForProfile(profile_)->IsVmRunning( + if (error_code != chromeos::MountError::MOUNT_ERROR_NONE) { + return; + } + + // Fetch list of shared paths even if VM is not running so that + // FilePathWatchers will be added. + auto paths = GetPersistedSharedPaths(); + if (!crostini::CrostiniManager::GetForProfile(profile_)->IsVmRunning( kCrostiniDefaultVmName)) { return; } - auto paths = GetPersistedSharedPaths(); for (const auto& path : paths) { if (path == volume.mount_path() || volume.mount_path().IsParent(path)) { CallSeneschalSharePath(kCrostiniDefaultVmName, path, false, @@ -436,20 +485,142 @@ void CrostiniSharePath::OnVolumeUnmounted(chromeos::MountError error_code, const file_manager::Volume& volume) { - if (error_code != chromeos::MountError::MOUNT_ERROR_NONE || - !crostini::CrostiniManager::GetForProfile(profile_)->IsVmRunning( - kCrostiniDefaultVmName)) { + if (error_code != chromeos::MountError::MOUNT_ERROR_NONE) { return; } - auto paths = GetPersistedSharedPaths(); - for (const auto& path : paths) { + for (auto it = shared_paths_.begin(); it != shared_paths_.end();) { + // Defensive copy of path since unsharing modifies shared_paths_. + base::FilePath path(it->first); if (path == volume.mount_path() || volume.mount_path().IsParent(path)) { - CallSeneschalUnsharePath( - kCrostiniDefaultVmName, path, - base::BindOnce(mount_event_seneschal_callback_, "unshare-on-unmount", - path, path)); + // Defensive copy of vm_names for same reason. + const std::set<std::string> vm_names(it->second.vm_names); + ++it; + for (auto& vm_name : vm_names) { + // Unshare with unpersist=false since we still want the path + // to be persisted when volume is next mounted. + UnsharePath(vm_name, path, false /* unpersist */, + base::BindOnce(mount_event_seneschal_callback_, + "unshare-on-unmount", path, path)); + } + } else { + ++it; } } } +void CrostiniSharePath::StartFileWatcher(const base::FilePath& path) { + auto* info = FindSharedPathInfo(path); + if (!info || info->watcher) { + return; + } + info->watcher = std::make_unique<base::FilePathWatcher>(); + info->watcher->Watch(path, false, + base::BindRepeating(&CrostiniSharePath::OnFileChanged, + base::Unretained(this))); +} + +void CrostiniSharePath::RegisterSharedPath(const base::FilePath& path, + const std::string& vm_name) { + // Paths may be called to be shared multiple times for the same or different + // vm. If path is already registered, add vm_name to list of VMs shared with + // and return. + if (auto* info = FindSharedPathInfo(path)) { + info->vm_names.insert(vm_name); + return; + } + + shared_paths_.emplace(path, SharedPathInfo(vm_name)); + if (!no_file_watchers_for_testing_) { + sequenced_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&CrostiniSharePath::StartFileWatcher, + base::Unretained(this), path)); + } +} + +void CrostiniSharePath::OnFileChanged(const base::FilePath& path, bool error) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (shared_paths_.find(path) == shared_paths_.end()) { + return; + } + if (error) { + shared_paths_.erase(path); + return; + } + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&CrostiniSharePath::CheckIfPathDeletedOnIOThread, + base::Unretained(this), path)); +} + +void CrostiniSharePath::CheckIfPathDeletedOnIOThread( + const base::FilePath& path) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (base::PathExists(path)) { + return; + } + + // If we can't find the path, check if the volume was unmounted. + // FileWatchers may fire before VolumeManager::OnVolumeUnmounted. + bool volume_still_mounted = false; + const std::vector<base::WeakPtr<file_manager::Volume>>& volume_list = + file_manager::VolumeManager::Get(profile_)->GetVolumeList(); + for (const auto& volume : volume_list) { + if ((path == volume->mount_path() || volume->mount_path().IsParent(path)) && + base::PathExists(volume->mount_path())) { + volume_still_mounted = true; + break; + } + } + if (!volume_still_mounted) { + return; + } + + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&CrostiniSharePath::PathDeleted, + base::Unretained(this), path)); +} + +void CrostiniSharePath::PathDeleted(const base::FilePath& path) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + auto* info = FindSharedPathInfo(path); + if (!info) { + return; + } + + // Defensive copy of vm_names since unsharing modifies shared_paths_. + const std::set<std::string> vm_names(info->vm_names); + for (auto& vm_name : vm_names) { + UnsharePath(vm_name, path, true /* unpersist */, + base::BindOnce(mount_event_seneschal_callback_, + "unshare-on-delete", path, path)); + } +} + +void CrostiniSharePath::OnFilesChanged( + const std::vector<drivefs::mojom::FileChange>& changes) { + auto* integration_service = + drive::DriveIntegrationServiceFactory::FindForProfile(profile_); + if (!integration_service) { + return; + } + // Paths come as absolute from the drivefs mount point. E.g. /root/folder. + base::FilePath root("/"); + for (const auto& change : changes) { + base::FilePath path = integration_service->GetMountPointPath(); + if (change.type == drivefs::mojom::FileChange_Type::kDelete && + root.AppendRelativePath(change.path, &path)) { + PathDeleted(path); + } + } +} + +SharedPathInfo* CrostiniSharePath::FindSharedPathInfo( + const base::FilePath& path) { + auto it = shared_paths_.find(path); + if (it == shared_paths_.end()) { + return nullptr; + } + return &it->second; +} + } // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.h b/chrome/browser/chromeos/crostini/crostini_share_path.h index 5f0d7c04..68fd05bd 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path.h +++ b/chrome/browser/chromeos/crostini/crostini_share_path.h
@@ -5,13 +5,19 @@ #ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_SHARE_PATH_H_ #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_SHARE_PATH_H_ +#include <map> +#include <memory> +#include <set> #include <vector> #include "base/callback.h" #include "base/files/file_path.h" +#include "base/files/file_path_watcher.h" #include "base/observer_list.h" +#include "base/sequenced_task_runner.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h" +#include "chromeos/components/drivefs/drivefs_host_observer.h" #include "chromeos/dbus/seneschal/seneschal_service.pb.h" #include "components/keyed_service/core/keyed_service.h" @@ -19,10 +25,20 @@ namespace crostini { +struct SharedPathInfo { + explicit SharedPathInfo(const std::string& vm_name); + SharedPathInfo(SharedPathInfo&&); + ~SharedPathInfo(); + + std::unique_ptr<base::FilePathWatcher> watcher; + std::set<std::string> vm_names; +}; + // Handles sharing and unsharing paths from the Chrome OS host to the crostini // VM via seneschal. class CrostiniSharePath : public KeyedService, - public file_manager::VolumeManagerObserver { + public file_manager::VolumeManagerObserver, + public drivefs::DriveFsHostObserver { public: using SharePathCallback = base::OnceCallback<void(const base::FilePath&, bool, std::string)>; @@ -34,7 +50,8 @@ std::string failure_reason)>; class Observer { public: - virtual void OnUnshare(const base::FilePath& path) = 0; + virtual void OnUnshare(const base::FilePath& path, + const std::string& vm_name) = 0; }; static CrostiniSharePath* GetForProfile(Profile* profile); @@ -60,10 +77,12 @@ bool persist, base::OnceCallback<void(bool, std::string)> callback); - // Unshare specified |path| with vm. + // Unshare specified |path| with |vm_name|. If |unpersist| is set, the path + // is removed from prefs, and will not be shared at container startup. // Callback receives success bool and failure reason string. void UnsharePath(const std::string& vm_name, const base::FilePath& path, + bool unpersist, base::OnceCallback<void(bool, std::string)> callback); // Returns true the first time it is called on this service. @@ -86,6 +105,25 @@ void OnVolumeUnmounted(chromeos::MountError error_code, const file_manager::Volume& volume) override; + // drivefs::DriveFsHostObserver + void OnFilesChanged( + const std::vector<drivefs::mojom::FileChange>& changes) override; + + // Registers |path| as shared with |vm_name|. Adds a FilePathWatcher to + // detect when the path has been deleted. If the path is deleted, we unshare + // the path, and remove it from prefs if it was persisted. + // Visible for testing. + void RegisterSharedPath(const base::FilePath& path, + const std::string& vm_name); + + // Runs on UI Thread to handle when a path is deleted. + // Visible for testing. + void PathDeleted(const base::FilePath& path); + + // Don't run file watchers for tests. + void set_no_file_watchers_for_testing() { + no_file_watchers_for_testing_ = true; + } // Allow seneschal callback for mount events to be overridden for testing. void set_mount_event_seneschal_callback_for_testing( MountEventSeneschalCallback callback) { @@ -103,12 +141,26 @@ const base::FilePath& path, base::OnceCallback<void(bool, std::string)> callback); + void StartFileWatcher(const base::FilePath& path); + + // Callback for FilePathWatcher. + void OnFileChanged(const base::FilePath& path, bool error); + + // Runs on IO Thread to check if a path is deleted. + void CheckIfPathDeletedOnIOThread(const base::FilePath& path); + + // Returns info for specified path or nullptr if not found. + SharedPathInfo* FindSharedPathInfo(const base::FilePath& path); + Profile* profile_; + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; bool first_for_session_ = true; // Allow callback for mount event to be overidden for testing. MountEventSeneschalCallback mount_event_seneschal_callback_; base::ObserverList<Observer>::Unchecked observers_; + std::map<base::FilePath, SharedPathInfo> shared_paths_; + bool no_file_watchers_for_testing_ = false; DISALLOW_COPY_AND_ASSIGN(CrostiniSharePath); }; // class
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc index ff8415f3..2e91484 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
@@ -203,12 +203,15 @@ base::ListValue* shared_paths = update.Get(); shared_paths->Append(std::make_unique<base::Value>(shared_path_.value())); volume_downloads_ = file_manager::Volume::CreateForDownloads(root_); + crostini_share_path_->RegisterSharedPath(shared_path_, + kCrostiniDefaultVmName); } void SetUp() override { run_loop_ = std::make_unique<base::RunLoop>(); profile_ = std::make_unique<TestingProfile>(); crostini_share_path_ = std::make_unique<CrostiniSharePath>(profile()); + crostini_share_path_->set_no_file_watchers_for_testing(); // Setup for DriveFS. scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( @@ -664,7 +667,7 @@ features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); crostini_share_path()->UnsharePath( - "vm-running", shared_path_, + "vm-running", shared_path_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), shared_path_, Persist::NO, SeneschalClientCalled::YES, "MyFiles/already-shared", @@ -676,7 +679,7 @@ features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); crostini_share_path()->UnsharePath( - "vm-running", root_, + "vm-running", root_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), root_, Persist::NO, SeneschalClientCalled::YES, "MyFiles", Success::YES, "")); @@ -686,7 +689,7 @@ TEST_F(CrostiniSharePathTest, UnsharePathVmNotRunning) { SetUpVolume(); crostini_share_path()->UnsharePath( - "vm-not-running", shared_path_, + "vm-not-running", shared_path_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), shared_path_, Persist::NO, SeneschalClientCalled::NO, "", Success::YES, @@ -698,7 +701,7 @@ SetUpVolume(); base::FilePath invalid("invalid/path"); crostini_share_path()->UnsharePath( - "vm-running", invalid, + "vm-running", invalid, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), invalid, Persist::NO, SeneschalClientCalled::NO, "", Success::NO, @@ -858,4 +861,20 @@ run_loop()->Run(); } +TEST_F(CrostiniSharePathTest, UnshareOnDelete) { + features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); + SetUpVolume(); + CrostiniManager::GetForProfile(profile())->AddRunningVmForTesting( + kCrostiniDefaultVmName); + auto volume_shared_path = + file_manager::Volume::CreateForDownloads(shared_path_); + crostini_share_path_->set_mount_event_seneschal_callback_for_testing( + base::BindRepeating(&CrostiniSharePathTest::MountEventUnsharePathCallback, + base::Unretained(this), "unshare-on-delete", + shared_path_, Persist::NO, SeneschalClientCalled::YES, + "MyFiles/already-shared", Success::YES, "")); + crostini_share_path_->PathDeleted(shared_path_); + run_loop()->Run(); +} + } // namespace crostini
diff --git a/chrome/browser/chromeos/eol_notification.cc b/chrome/browser/chromeos/eol_notification.cc index 4c56fd0..de36459 100644 --- a/chrome/browser/chromeos/eol_notification.cc +++ b/chrome/browser/chromeos/eol_notification.cc
@@ -165,7 +165,8 @@ message_center::SystemNotificationWarningLevel::CRITICAL_WARNING); NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc index 2d9f484..ffcfe233 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -1119,7 +1119,11 @@ event.entries.emplace_back(std::move(entry)); } -void EventRouter::OnUnshare(const base::FilePath& path) { +void EventRouter::OnUnshare(const base::FilePath& path, + const std::string& vm_name) { + if (vm_name != crostini::kCrostiniDefaultVmName) { + return; + } std::string mount_name; std::string file_system_name; std::string full_path;
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h index 71b8dc3..504c43d 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.h +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -152,7 +152,8 @@ void OnFileSystemMountFailed() override; // crostini::CrostiniSharePath::Observer overrides - void OnUnshare(const base::FilePath& path) override; + void OnUnshare(const base::FilePath& path, + const std::string& vm_name) override; // Returns a weak pointer for the event router. base::WeakPtr<EventRouter> GetWeakPtr();
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc index cf2bee756..48617d3 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -720,7 +720,7 @@ storage::FileSystemURL cracked = file_system_context->CrackURL(GURL(params->url)); crostini::CrostiniSharePath::GetForProfile(profile)->UnsharePath( - crostini::kCrostiniDefaultVmName, cracked.path(), + crostini::kCrostiniDefaultVmName, cracked.path(), /*unpersist=*/true, base::BindOnce( &FileManagerPrivateInternalUnsharePathWithCrostiniFunction:: UnsharePathCallback,
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 22e13b7..61dac79 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -292,7 +292,8 @@ TestCase("fileDisplayUnmountFirstPartition"), TestCase("fileDisplayUnmountLastPartition"), TestCase("fileSearchCaseInsensitive"), - TestCase("fileSearchNotFound"))); + TestCase("fileSearchNotFound"), + TestCase("fileDisplayDownloadsWithBlockedFileTaskRunner"))); WRAPPED_INSTANTIATE_TEST_SUITE_P( OpenVideoFiles, /* open_video_files.js */ @@ -982,6 +983,7 @@ Metadata, /* metadata.js */ FilesAppBrowserTest, ::testing::Values( + TestCase("metadataDocumentsProvider").EnableDocumentsProvider(), TestCase("metadataDownloads"), TestCase("metadataDownloads").EnableMyFilesVolume(), TestCase("metadataDrive").DisableDriveFs(),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc index 9848ef5..b489a026 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -71,6 +71,7 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "content/public/test/network_connection_change_simulator.h" #include "content/public/test/test_navigation_observer.h" @@ -88,6 +89,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/service_manager/public/cpp/connector.h" #include "storage/browser/fileapi/external_mount_points.h" +#include "storage/browser/fileapi/file_system_context.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/events/event.h" @@ -551,6 +553,29 @@ DISALLOW_COPY_AND_ASSIGN(OfflineGetDriveConnectionState); }; +base::Lock& GetLockForBlockingDefaultFileTaskRunner() { + static base::NoDestructor<base::Lock> lock; + return *lock; +} + +// Ensures the default HTML filesystem API blocking task runner is blocked for a +// test. +void BlockFileTaskRunner(Profile* profile) { + GetLockForBlockingDefaultFileTaskRunner().Acquire(); + + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetFileSystemContext() + ->default_file_task_runner() + ->PostTask(FROM_HERE, base::BindOnce([] { + base::AutoLock l(GetLockForBlockingDefaultFileTaskRunner()); + })); +} + +// Undo the effects of |BlockFileTaskRunner()|. +void UnblockFileTaskRunner() { + GetLockForBlockingDefaultFileTaskRunner().Release(); +} + } // anonymous namespace // LocalTestVolume: test volume for a local drive. @@ -2126,6 +2151,16 @@ return; } + if (name == "blockFileTaskRunner") { + BlockFileTaskRunner(profile()); + return; + } + + if (name == "unblockFileTaskRunner") { + UnblockFileTaskRunner(); + return; + } + FAIL() << "Unknown test message: " << name; }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index 98a4ac18..a07bd87 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -74,6 +74,10 @@ RunGeneratedTest("/background/js/media_import_handler_unittest.html"); } +IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MountMetricsTest) { + RunGeneratedTest("/background/js/mount_metrics_unittest.html"); +} + IN_PROC_BROWSER_TEST_F(FileManagerJsTest, TaskQueueTest) { RunGeneratedTest("/background/js/task_queue_unittest.html"); }
diff --git a/chrome/browser/chromeos/file_system_provider/notification_manager.cc b/chrome/browser/chromeos/file_system_provider/notification_manager.cc index d5e5f72..4aba0f8 100644 --- a/chrome/browser/chromeos/file_system_provider/notification_manager.cc +++ b/chrome/browser/chromeos/file_system_provider/notification_manager.cc
@@ -113,7 +113,7 @@ notification.SetSystemPriority(); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); } void NotificationManager::OnNotificationResult(NotificationResult result) {
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc index b695deee..efdeb46 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -12,6 +12,8 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/stl_util.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" #include "chrome/browser/chromeos/fileapi/file_access_permissions.h" #include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h" @@ -29,6 +31,7 @@ #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/common/fileapi/file_system_mount_option.h" +#include "storage/common/fileapi/file_system_types.h" #include "storage/common/fileapi/file_system_util.h" namespace chromeos { @@ -341,14 +344,21 @@ std::make_unique<storage::FileSystemOperationContext>( context, MediaFileSystemBackend::MediaTaskRunner().get())); } + if (url.type() == storage::kFileSystemTypeNativeLocal || + url.type() == storage::kFileSystemTypeRestrictedNativeLocal || + url.type() == storage::kFileSystemTypeDriveFs) { + return storage::FileSystemOperation::Create( + url, context, + std::make_unique<storage::FileSystemOperationContext>( + context, base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}) + .get())); + } - DCHECK(url.type() == storage::kFileSystemTypeNativeLocal || - url.type() == storage::kFileSystemTypeRestrictedNativeLocal || - url.type() == storage::kFileSystemTypeDrive || + DCHECK(url.type() == storage::kFileSystemTypeDrive || url.type() == storage::kFileSystemTypeProvided || url.type() == storage::kFileSystemTypeArcContent || - url.type() == storage::kFileSystemTypeArcDocumentsProvider || - url.type() == storage::kFileSystemTypeDriveFs); + url.type() == storage::kFileSystemTypeArcDocumentsProvider); return storage::FileSystemOperation::Create( url, context, std::make_unique<storage::FileSystemOperationContext>(context)); @@ -405,8 +415,11 @@ case storage::kFileSystemTypeRestrictedNativeLocal: case storage::kFileSystemTypeDriveFs: return std::unique_ptr<storage::FileStreamReader>( - storage::FileStreamReader::CreateForFileSystemFile( - context, url, offset, expected_modification_time)); + storage::FileStreamReader::CreateForLocalFile( + base::CreateTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}) + .get(), + url.path(), offset, expected_modification_time)); case storage::kFileSystemTypeDeviceMediaAsFileStorage: return mtp_delegate_->CreateFileStreamReader( url, offset, max_bytes_to_read, expected_modification_time, context); @@ -441,8 +454,10 @@ case storage::kFileSystemTypeNativeLocal: case storage::kFileSystemTypeDriveFs: return storage::FileStreamWriter::CreateForLocalFile( - context->default_file_task_runner(), url.path(), offset, - storage::FileStreamWriter::OPEN_EXISTING_FILE); + base::CreateTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}) + .get(), + url.path(), offset, storage::FileStreamWriter::OPEN_EXISTING_FILE); case storage::kFileSystemTypeDeviceMediaAsFileStorage: return mtp_delegate_->CreateFileStreamWriter(url, offset, context); // Read only file systems.
diff --git a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc index 855caba9..ca4b4c2 100644 --- a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc +++ b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
@@ -459,7 +459,7 @@ data, std::move(delegate)); notification.set_priority(message_center::LOW_PRIORITY); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/hats/hats_notification_controller.cc b/chrome/browser/chromeos/hats/hats_notification_controller.cc index 46b83ff..d4ff2a3 100644 --- a/chrome/browser/chromeos/hats/hats_notification_controller.cc +++ b/chrome/browser/chromeos/hats/hats_notification_controller.cc
@@ -220,7 +220,8 @@ message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void HatsNotificationController::UpdateLastInteractionTime() {
diff --git a/chrome/browser/chromeos/kiosk_next_home/BUILD.gn b/chrome/browser/chromeos/kiosk_next_home/BUILD.gn deleted file mode 100644 index cdf787e..0000000 --- a/chrome/browser/chromeos/kiosk_next_home/BUILD.gn +++ /dev/null
@@ -1,17 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("kiosk_next_home") { - sources = [ - "kiosk_next_home_interface_broker_impl.cc", - "kiosk_next_home_interface_broker_impl.h", - ] - - deps = [ - "//base", - "//chrome/browser/chromeos/kiosk_next_home/mojom", - "//services/identity/public/mojom", - "//services/service_manager/public/cpp", - ] -}
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.cc b/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.cc new file mode 100644 index 0000000..fcfb541 --- /dev/null +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.cc
@@ -0,0 +1,59 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/kiosk_next_home/app_controller_impl.h" + +#include <utility> +#include <vector> + +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/services/app_service/public/mojom/types.mojom.h" +#include "ui/display/types/display_constants.h" +#include "ui/events/event_constants.h" + +namespace chromeos { +namespace kiosk_next_home { + +AppControllerImpl::AppControllerImpl(Profile* profile) + : app_service_proxy_(apps::AppServiceProxy::Get(profile)) {} + +AppControllerImpl::~AppControllerImpl() = default; + +void AppControllerImpl::BindRequest(mojom::AppControllerRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void AppControllerImpl::GetApps( + mojom::AppController::GetAppsCallback callback) { + std::vector<chromeos::kiosk_next_home::mojom::AppPtr> app_list; + // Using AppUpdate objects here since that's how the app list is intended to + // be consumed. Refer to AppRegistryCache::ForEachApp for more information. + app_service_proxy_->AppRegistryCache().ForEachApp( + [this, &app_list](const apps::AppUpdate& update) { + app_list.push_back(CreateAppPtr(update)); + }); + std::move(callback).Run(std::move(app_list)); +} + +void AppControllerImpl::LaunchApp(const std::string& app_id) { + // TODO(ltenorio): Create a new launch source for Kiosk Next Home and use it + // here. + app_service_proxy_->Launch(app_id, ui::EventFlags::EF_NONE, + apps::mojom::LaunchSource::kFromAppListGrid, + display::kDefaultDisplayId); +} + +chromeos::kiosk_next_home::mojom::AppPtr AppControllerImpl::CreateAppPtr( + const apps::AppUpdate& update) { + auto app = chromeos::kiosk_next_home::mojom::App::New(); + app->app_id = update.AppId(); + app->type = update.AppType(); + app->display_name = update.Name(); + app->readiness = update.Readiness(); + return app; +} + +} // namespace kiosk_next_home +} // namespace chromeos
diff --git a/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.h b/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.h new file mode 100644 index 0000000..42e9e88 --- /dev/null +++ b/chrome/browser/chromeos/kiosk_next_home/app_controller_impl.h
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_APP_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_APP_CONTROLLER_IMPL_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/chromeos/kiosk_next_home/mojom/app_controller.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +class Profile; + +namespace apps { +class AppServiceProxy; +class AppUpdate; +} + +namespace chromeos { +namespace kiosk_next_home { + +// Implementation for the Kiosk Next AppController. +// This class is responsible for managing Chrome OS apps and returning useful +// information about them to the Kiosk Next Home. +class AppControllerImpl : public mojom::AppController { + public: + explicit AppControllerImpl(Profile* profile); + ~AppControllerImpl() override; + + // Binds this implementation instance to an AppController request. + void BindRequest(mojom::AppControllerRequest request); + + // mojom::AppController: + void GetApps(mojom::AppController::GetAppsCallback callback) override; + void LaunchApp(const std::string& app_id) override; + + private: + // Creates a new Kiosk Next App from a delta app update coming from + // AppServiceProxy. + chromeos::kiosk_next_home::mojom::AppPtr CreateAppPtr( + const apps::AppUpdate& update); + + mojo::BindingSet<mojom::AppController> bindings_; + apps::AppServiceProxy* app_service_proxy_; + + DISALLOW_COPY_AND_ASSIGN(AppControllerImpl); +}; + +} // namespace kiosk_next_home +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_KIOSK_NEXT_HOME_APP_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc index 9a0e759..4582690d 100644 --- a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc +++ b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.cc
@@ -6,6 +6,9 @@ #include <utility> +#include "chrome/browser/chromeos/kiosk_next_home/app_controller_impl.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_context.h" #include "services/identity/public/mojom/constants.mojom.h" #include "services/identity/public/mojom/identity_accessor.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -14,8 +17,10 @@ namespace kiosk_next_home { KioskNextHomeInterfaceBrokerImpl::KioskNextHomeInterfaceBrokerImpl( - service_manager::Connector* connector) - : connector_(connector->Clone()) {} + content::BrowserContext* context) + : connector_(content::BrowserContext::GetConnectorFor(context)->Clone()), + app_controller_(std::make_unique<AppControllerImpl>( + Profile::FromBrowserContext(context))) {} KioskNextHomeInterfaceBrokerImpl::~KioskNextHomeInterfaceBrokerImpl() = default; @@ -25,6 +30,11 @@ std::move(request)); } +void KioskNextHomeInterfaceBrokerImpl::GetAppController( + mojom::AppControllerRequest request) { + app_controller_->BindRequest(std::move(request)); +} + void KioskNextHomeInterfaceBrokerImpl::BindRequest( mojom::KioskNextHomeInterfaceBrokerRequest request) { bindings_.AddBinding(this, std::move(request));
diff --git a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h index c241c4b..068cd3502 100644 --- a/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h +++ b/chrome/browser/chromeos/kiosk_next_home/kiosk_next_home_interface_broker_impl.h
@@ -13,6 +13,10 @@ #include "mojo/public/cpp/bindings/binding_set.h" #include "services/identity/public/mojom/identity_accessor.mojom.h" +namespace content { +class BrowserContext; +} + namespace service_manager { class Connector; } @@ -20,14 +24,15 @@ namespace chromeos { namespace kiosk_next_home { +class AppControllerImpl; + // Implementation of interface responsible for brokering other interfaces needed // to support Kiosk Next Home functionality. class KioskNextHomeInterfaceBrokerImpl : public mojom::KioskNextHomeInterfaceBroker, public base::SupportsUserData::Data { public: - explicit KioskNextHomeInterfaceBrokerImpl( - service_manager::Connector* connector); + explicit KioskNextHomeInterfaceBrokerImpl(content::BrowserContext* context); ~KioskNextHomeInterfaceBrokerImpl() override; // Binds client requests to this implementation. @@ -36,12 +41,14 @@ // mojom::KioskNextHomeInterfaceBroker: void GetIdentityAccessor( ::identity::mojom::IdentityAccessorRequest request) override; + void GetAppController(mojom::AppControllerRequest request) override; private: mojo::BindingSet<mojom::KioskNextHomeInterfaceBroker> bindings_; // Clone of BrowserContext's Connector, which allows binding to other // services. std::unique_ptr<service_manager::Connector> connector_; + std::unique_ptr<AppControllerImpl> app_controller_; DISALLOW_COPY_AND_ASSIGN(KioskNextHomeInterfaceBrokerImpl); };
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn b/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn index 9ed56ed..198be69 100644 --- a/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn +++ b/chrome/browser/chromeos/kiosk_next_home/mojom/BUILD.gn
@@ -6,10 +6,12 @@ mojom("mojom") { sources = [ + "app_controller.mojom", "kiosk_next_home_interface_broker.mojom", ] public_deps = [ + "//chrome/services/app_service/public/mojom:types", "//services/identity/public/mojom", ] }
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/app_controller.mojom b/chrome/browser/chromeos/kiosk_next_home/mojom/app_controller.mojom new file mode 100644 index 0000000..2e47439 --- /dev/null +++ b/chrome/browser/chromeos/kiosk_next_home/mojom/app_controller.mojom
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module chromeos.kiosk_next_home.mojom; + +import "chrome/services/app_service/public/mojom/types.mojom"; + +// Represents an app on Chrome OS. This struct has all the information +// necessary to display the app in the Kiosk Next Home app list/grid, including +// readiness, thumbnail image, display name, etc. +struct App { + // Stable and unique identifier for this app. + string app_id; + + // The type of this app (e.g. ARC, Crostini, extension, etc). + apps.mojom.AppType type; + + // Name used when displaying the app in an app list or grid. + string display_name; + + // The current state of readiness for this app. + // It can tell if the app is suspended, uninstalled, etc. + apps.mojom.Readiness readiness; +}; + +// Interface for managing Chrome OS apps from the Kiosk Next Home. +interface AppController { + // Returns all the local apps installed on this Chrome OS device. + // It reads from all the app sources, including ARC++ (Android), + // Crostini (Linux), extensions and PWAs. + // Note that as soon as this method returns, some of the apps might have + // changed. To always get the most updated information, attach an app + // observer through the AddObserver method. + GetApps() => (array<App> apps); + + // TODO(ltenorio): Add a way to attach app observers. + + // Launches the app with the given app_id. + LaunchApp(string app_id); +};
diff --git a/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom b/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom index 2d613b2..21ecd83 100644 --- a/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom +++ b/chrome/browser/chromeos/kiosk_next_home/mojom/kiosk_next_home_interface_broker.mojom
@@ -4,6 +4,7 @@ module chromeos.kiosk_next_home.mojom; +import "chrome/browser/chromeos/kiosk_next_home/mojom/app_controller.mojom"; import "services/identity/public/mojom/identity_accessor.mojom"; // Single entry point for any interface requests issued by the Kiosk Next @@ -12,4 +13,7 @@ interface KioskNextHomeInterfaceBroker { // Binds IdentityAccessor service request. GetIdentityAccessor(identity.mojom.IdentityAccessor& request); + + // Binds the AppController service request. + GetAppController(AppController& request); };
diff --git a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc index 70f96ad2..ea0617b 100644 --- a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc +++ b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
@@ -25,9 +25,9 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "chromeos/constants/chromeos_switches.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/util/tpm_util.h" #include "chromeos/login/auth/authpolicy_login_helper.h" #include "components/account_id/account_id.h"
diff --git a/chrome/browser/chromeos/login/active_directory_test_helper.cc b/chrome/browser/chromeos/login/active_directory_test_helper.cc index 02c1839..0ecc814 100644 --- a/chrome/browser/chromeos/login/active_directory_test_helper.cc +++ b/chrome/browser/chromeos/login/active_directory_test_helper.cc
@@ -13,7 +13,7 @@ #include "base/threading/thread_restrictions.h" #include "chrome/common/chrome_paths.h" #include "chromeos/constants/chromeos_paths.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/authpolicy/active_directory_info.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/upstart/upstart_client.h"
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.cc index 00ac029..9b7bcbc5 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.cc
@@ -128,7 +128,8 @@ std::unique_ptr<message_center::Notification> notification) { notification->SetSystemPriority(); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void EasyUnlockNotificationController::LaunchEasyUnlockSettings() {
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc index e98b2d4..2c84b697 100644 --- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc +++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -22,9 +22,9 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/constants/dbus_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/upstart/upstart_client.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index 262a162..5662e479 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -39,7 +39,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/fake_auth_policy_client.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/dbus/util/tpm_util.h" #include "chromeos/login/auth/key.h"
diff --git a/chrome/browser/chromeos/login/screens/eula_screen.cc b/chrome/browser/chromeos/login/screens/eula_screen.cc index 958ca4a..fd4f170 100644 --- a/chrome/browser/chromeos/login/screens/eula_screen.cc +++ b/chrome/browser/chromeos/login/screens/eula_screen.cc
@@ -20,7 +20,6 @@ constexpr const char kUserActionAcceptButtonClicked[] = "accept-button"; constexpr const char kUserActionBackButtonClicked[] = "back-button"; -constexpr const char kContextKeyUsageStatsEnabled[] = "usageStatsEnabled"; // Reflects the value of usage statistics reporting checkbox shown in eula // UI. The value is expected to survive EulaScreen res-hows within a single @@ -72,6 +71,10 @@ } } +void EulaScreen::SetUsageStatsEnabled(bool enabled) { + g_usage_statistics_reporting_enabled = enabled; +} + bool EulaScreen::IsUsageStatsEnabled() const { return g_usage_statistics_reporting_enabled; } @@ -108,14 +111,6 @@ } } -void EulaScreen::OnContextKeyUpdated( - const ::login::ScreenContext::KeyType& key) { - if (key == kContextKeyUsageStatsEnabled) { - g_usage_statistics_reporting_enabled = - context_.GetBoolean(kContextKeyUsageStatsEnabled); - } -} - void EulaScreen::OnPasswordFetched(const std::string& tpm_password) { tpm_password_ = tpm_password; if (view_)
diff --git a/chrome/browser/chromeos/login/screens/eula_screen.h b/chrome/browser/chromeos/login/screens/eula_screen.h index 5eb9eee..2944f11 100644 --- a/chrome/browser/chromeos/login/screens/eula_screen.h +++ b/chrome/browser/chromeos/login/screens/eula_screen.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "chrome/browser/chromeos/login/screens/base_screen.h" #include "chromeos/tpm/tpm_password_fetcher.h" -#include "components/login/screens/screen_context.h" #include "url/gurl.h" namespace chromeos { @@ -44,6 +43,8 @@ // done. void InitiatePasswordFetch(); + void SetUsageStatsEnabled(bool enabled); + // Returns true if usage statistics reporting is enabled. bool IsUsageStatsEnabled() const; @@ -59,7 +60,6 @@ void Show() override; void Hide() override; void OnUserAction(const std::string& action_id) override; - void OnContextKeyUpdated(const ::login::ScreenContext::KeyType& key) override; // TpmPasswordFetcherDelegate implementation: void OnPasswordFetched(const std::string& tpm_password) override;
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.cc b/chrome/browser/chromeos/login/screens/user_image_screen.cc index a40adfe..cae8f03 100644 --- a/chrome/browser/chromeos/login/screens/user_image_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_image_screen.cc
@@ -48,14 +48,6 @@ namespace { -constexpr const char kContextKeyIsCameraPresent[] = "isCameraPresent"; -constexpr const char kContextKeyProfilePictureDataURL[] = - "profilePictureDataURL"; -constexpr const char kContextKeyIsProfilePictureAvailable[] = - "isProfilePictureAvailable"; -constexpr const char kContextKeySelectedImageIndex[] = "selectedImageIndex"; -constexpr const char kContextKeySelectedImageURL[] = "selectedImageURL"; - // Time histogram suffix for profile image download. const char kProfileDownloadReason[] = "OOBE"; @@ -67,10 +59,11 @@ UserImageScreen::UserImageScreen(UserImageView* view) : BaseScreen(OobeScreen::SCREEN_USER_IMAGE_PICKER), view_(view) { - if (view_) + if (view_) { view_->Bind(this); + view_->SetProfilePictureDataURL(std::string()); + } user_manager::UserManager::Get()->AddObserver(this); - GetContextEditor().SetString(kContextKeyProfilePictureDataURL, std::string()); } UserImageScreen::~UserImageScreen() { @@ -218,16 +211,16 @@ view_->Show(); selected_image_ = GetUser()->image_index(); - GetContextEditor().SetInteger(kContextKeySelectedImageIndex, selected_image_); - GetContextEditor().SetString( - kContextKeySelectedImageURL, + + view_->SetSelectedImageIndex(selected_image_); + view_->SetSelectedImageURL( default_user_image::GetDefaultImageUrl(selected_image_)); const user_manager::User* user = GetUser(); // Active Directory accounts do not use a profile image so skip the download // and inform the UI that no profile image exists. if (user && user->IsActiveDirectoryUser()) { - GetContextEditor().SetBoolean(kContextKeyIsProfilePictureAvailable, false); + view_->SetIsProfilePictureAvailable(false); } else { // Start fetching the profile image. GetUserImageManager()->DownloadProfileImage(kProfileDownloadReason); @@ -246,7 +239,8 @@ } void UserImageScreen::OnCameraPresenceCheckDone(bool is_camera_present) { - GetContextEditor().SetBoolean(kContextKeyIsCameraPresent, is_camera_present); + if (view_) + view_->SetIsCameraPresent(is_camera_present); } void UserImageScreen::OnImageDecoded(const SkBitmap& decoded_image) { @@ -260,26 +254,29 @@ } void UserImageScreen::OnUserImageChanged(const user_manager::User& user) { - GetContextEditor().SetInteger(kContextKeySelectedImageIndex, - GetUser()->image_index()); - GetContextEditor().SetString( - kContextKeySelectedImageURL, - default_user_image::GetDefaultImageUrl(GetUser()->image_index())); + if (view_) { + view_->SetSelectedImageIndex(GetUser()->image_index()); + view_->SetSelectedImageURL( + default_user_image::GetDefaultImageUrl(GetUser()->image_index())); + } } void UserImageScreen::OnUserProfileImageUpdateFailed( const user_manager::User& user) { - // User has a default profile image or fetching profile image has failed. - GetContextEditor().SetString(kContextKeyProfilePictureDataURL, std::string()); + if (view_) { + // User has a default profile image or fetching profile image has failed. + view_->SetProfilePictureDataURL(std::string()); + } } void UserImageScreen::OnUserProfileImageUpdated( const user_manager::User& user, const gfx::ImageSkia& profile_image) { - // We've got a new profile image. - GetContextEditor().SetString( - kContextKeyProfilePictureDataURL, - webui::GetBitmapDataUrl(*profile_image.bitmap())); + if (view_) { + // We've got a new profile image. + view_->SetProfilePictureDataURL( + webui::GetBitmapDataUrl(*profile_image.bitmap())); + } } void UserImageScreen::OnInitialSync(bool local_image_updated) {
diff --git a/chrome/browser/chromeos/login/screens/user_image_view.h b/chrome/browser/chromeos/login/screens/user_image_view.h index 3464a10..e36221e 100644 --- a/chrome/browser/chromeos/login/screens/user_image_view.h +++ b/chrome/browser/chromeos/login/screens/user_image_view.h
@@ -31,6 +31,16 @@ // Hides curtain with spinner. virtual void HideCurtain() = 0; + + virtual void SetIsCameraPresent(bool value) = 0; + + virtual void SetProfilePictureDataURL(const std::string& value) = 0; + + virtual void SetIsProfilePictureAvailable(bool value) = 0; + + virtual void SetSelectedImageIndex(int value) = 0; + + virtual void SetSelectedImageURL(const std::string& value) = 0; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 78e2ac7..df96289 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1269,7 +1269,8 @@ notification->set_priority(message_center::SYSTEM_PRIORITY); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void UserSessionManager::InitProfilePreferences(
diff --git a/chrome/browser/chromeos/network_change_manager_client.cc b/chrome/browser/chromeos/network_change_manager_client.cc index f64f37f..c3800e7c 100644 --- a/chrome/browser/chromeos/network_change_manager_client.cc +++ b/chrome/browser/chromeos/network_change_manager_client.cc
@@ -12,6 +12,7 @@ #include "chromeos/network/network_state_handler.h" #include "content/public/browser/network_service_instance.h" #include "content/public/common/network_service_util.h" +#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier_posix.h" #include "services/network/public/mojom/network_service.mojom.h" @@ -19,8 +20,8 @@ NetworkChangeManagerClient::NetworkChangeManagerClient( net::NetworkChangeNotifierPosix* network_change_notifier) - : connection_type_(net::NetworkChangeNotifier::CONNECTION_NONE), - connection_subtype_(net::NetworkChangeNotifier::SUBTYPE_NONE), + : connection_type_(net::NetworkChangeNotifier::GetConnectionType()), + connection_subtype_(net::NetworkChangeNotifier::GetConnectionSubtype()), network_change_notifier_(network_change_notifier) { PowerManagerClient::Get()->AddObserver(this); NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
diff --git a/chrome/browser/chromeos/network_change_manager_client.h b/chrome/browser/chromeos/network_change_manager_client.h index 9731798..36cc507f 100644 --- a/chrome/browser/chromeos/network_change_manager_client.h +++ b/chrome/browser/chromeos/network_change_manager_client.h
@@ -42,6 +42,8 @@ friend class NetworkChangeManagerClientUpdateTest; FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest, ConnectionTypeFromShill); + FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest, + NetworkChangeNotifierConnectionTypeUpdated); void ConnectToNetworkChangeManager(); void ReconnectToNetworkChangeManager();
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc index 23e42a6..585ee71 100644 --- a/chrome/browser/chromeos/network_change_manager_client_unittest.cc +++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_split.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power/power_manager_client.h" +#include "chromeos/dbus/shill_service_client.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_state.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -106,6 +107,43 @@ } } +TEST(NetworkChangeManagerClientTest, + NetworkChangeNotifierConnectionTypeUpdated) { + // Create a NetworkChangeNotifier with a non-NONE connection type. + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<net::NetworkChangeNotifierPosix> network_change_notifier( + static_cast<net::NetworkChangeNotifierPosix*>( + net::NetworkChangeNotifier::Create())); + network_change_notifier->OnConnectionChanged( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + net::NetworkChangeNotifier::GetConnectionType()); + + // Initialize DBus and clear services so NetworkHandler thinks we're offline. + DBusThreadManager::Initialize(); + PowerManagerClient::InitializeFake(); + NetworkHandler::Initialize(); + DBusThreadManager::Get() + ->GetShillServiceClient() + ->GetTestInterface() + ->ClearServices(); + + auto client = std::make_unique<NetworkChangeManagerClient>( + network_change_notifier.get()); + + // NetworkChangeManagerClient should have read the network state from DBus + // and notified NetworkChangeNotifier that we're offline. + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_NONE, + client->connection_type_); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_NONE, + net::NetworkChangeNotifier::GetConnectionType()); + + client.reset(); + NetworkHandler::Shutdown(); + PowerManagerClient::Shutdown(); + DBusThreadManager::Shutdown(); +} + class NetworkChangeManagerClientUpdateTest : public testing::Test { protected: NetworkChangeManagerClientUpdateTest() : default_network_("") {}
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc index df63cab..c15be7aa 100644 --- a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc +++ b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chromeos/cryptohome/cryptohome_parameters.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/login_manager/policy_descriptor.pb.h" #include "chromeos/network/onc/variable_expander.h"
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc index 0e6cf54..3783d7b14 100644 --- a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
@@ -15,7 +15,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
diff --git a/chrome/browser/chromeos/policy/affiliation_test_helper.cc b/chrome/browser/chromeos/policy/affiliation_test_helper.cc index 7274dd4e..2299301 100644 --- a/chrome/browser/chromeos/policy/affiliation_test_helper.cc +++ b/chrome/browser/chromeos/policy/affiliation_test_helper.cc
@@ -22,9 +22,9 @@ #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/cryptohome/cryptohome_parameters.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/constants/dbus_paths.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "chromeos/login/auth/key.h"
diff --git a/chrome/browser/chromeos/policy/device_account_initializer.cc b/chrome/browser/chromeos/policy/device_account_initializer.cc index 143bbd8..0b11fdb 100644 --- a/chrome/browser/chromeos/policy/device_account_initializer.cc +++ b/chrome/browser/chromeos/policy/device_account_initializer.cc
@@ -30,7 +30,7 @@ #include "chrome/browser/profiles/profile.h" #include "chromeos/attestation/attestation_flow.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/cryptohome/rpc.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/policy/core/common/cloud/dm_auth.h"
diff --git a/chrome/browser/chromeos/policy/device_account_initializer.h b/chrome/browser/chromeos/policy/device_account_initializer.h index 64944931..93845f7f 100644 --- a/chrome/browser/chromeos/policy/device_account_initializer.h +++ b/chrome/browser/chromeos/policy/device_account_initializer.h
@@ -14,7 +14,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_store.h"
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc index 40746bf..561b79f 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -28,7 +28,7 @@ #include "chrome/browser/profiles/profile.h" #include "chromeos/attestation/attestation_flow.h" #include "chromeos/constants/chromeos_switches.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/cryptohome/rpc.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/upstart/upstart_client.h"
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h index c432301..478fac7 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -17,7 +17,7 @@ #include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h" #include "chrome/browser/chromeos/policy/device_cloud_policy_validator.h" #include "chrome/browser/chromeos/policy/enrollment_config.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/constants/attestation_constants.h" #include "chromeos/tpm/install_attributes.h" #include "components/policy/core/common/cloud/cloud_policy_client.h"
diff --git a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc index 9f32714..2b76ee7 100644 --- a/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_affiliation_browsertest.cc
@@ -21,10 +21,10 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/cryptohome/cryptohome_parameters.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "chromeos/dbus/upstart/upstart_client.h"
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc index 377df41e..78e91a09 100644 --- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc +++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/stringprintf.h" #include "base/time/default_tick_clock.h" #include "chrome/browser/chromeos/power/auto_screen_brightness/utils.h" #include "chrome/browser/profiles/profile.h" @@ -22,6 +23,30 @@ namespace power { namespace auto_screen_brightness { +namespace { + +const char* BrightnessChangeCauseToString( + Adapter::BrightnessChangeCause cause) { + switch (cause) { + case Adapter::BrightnessChangeCause::kInitialAlsReceived: + return "InitialAlsReceived"; + case Adapter::BrightnessChangeCause::kBrightneningThresholdExceeded: + return "BrightneningThresholdExceeded"; + case Adapter::BrightnessChangeCause::kDarkeningThresholdExceeded: + return "DarkeningThresholdExceeded"; + // |kImmediateBrightneningThresholdExceeded| and + // |kImmediateDarkeningThresholdExceeded| are deprecated, and shouldn't show + // up. + case Adapter::BrightnessChangeCause:: + kImmediateBrightneningThresholdExceeded: + case Adapter::BrightnessChangeCause::kImmediateDarkeningThresholdExceeded: + return "UnexpectedImmediateTransition"; + } + return "Unknown"; +} + +} // namespace + Adapter::Params::Params() {} Adapter::Adapter(Profile* profile, @@ -89,7 +114,9 @@ } void Adapter::OnUserBrightnessChanged(double old_brightness_percent, - double new_brightness_percent) {} + double new_brightness_percent) { + current_brightness_ = new_brightness_percent; +} void Adapter::OnUserBrightnessChangeRequested() { if (params_.user_adjustment_effect != UserAdjustmentEffect::kContinueAuto) { @@ -371,10 +398,10 @@ const double log_average_ambient_lux = ConvertToLog(average_ambient_lux_opt.value()); - const base::Optional<BrightnessChangeCause> can_adjust_brightness = + const base::Optional<BrightnessChangeCause> brightness_change_cause = CanAdjustBrightness(log_average_ambient_lux); - if (!can_adjust_brightness.has_value()) + if (!brightness_change_cause.has_value()) return; const base::Optional<double> brightness = @@ -400,10 +427,15 @@ } latest_brightness_change_time_ = brightness_change_time; - const BrightnessChangeCause cause = *can_adjust_brightness; + const BrightnessChangeCause cause = *brightness_change_cause; UMA_HISTOGRAM_ENUMERATION("AutoScreenBrightness.BrightnessChange.Cause", cause); + WriteLogMessages(log_average_ambient_lux, *brightness, cause); + + current_brightness_ = *brightness; + brightness_change_counter_++; + log_average_ambient_lux_ = log_average_ambient_lux; UpdateBrightnessChangeThresholds(); @@ -435,6 +467,27 @@ } } +void Adapter::WriteLogMessages(double new_log_als, + double new_brightness, + BrightnessChangeCause cause) const { + const std::string old_log_als = + log_average_ambient_lux_ + ? base::StringPrintf("%.4f", log_average_ambient_lux_.value()) + "->" + : ""; + + const std::string old_brightness = + current_brightness_ + ? base::StringPrintf("%.4f", current_brightness_.value()) + "%->" + : ""; + + VLOG(1) << "Screen brightness change #" << brightness_change_counter_ << ": " + << "brightness=" << old_brightness + << base::StringPrintf("%.4f", new_brightness) << "%" + << " cause=" << BrightnessChangeCauseToString(cause) + << " log_als=" << old_log_als + << base::StringPrintf("%.4f", new_log_als); +} + } // namespace auto_screen_brightness } // namespace power } // namespace chromeos
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h index 40b128a..51df676 100644 --- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h +++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h
@@ -199,6 +199,11 @@ base::Optional<double> GetBrightnessBasedOnAmbientLogLux( double ambient_log_lux) const; + // Called by |MaybeAdjustBrightness| when brightness should be changed. + void WriteLogMessages(double new_log_als, + double new_brightness, + BrightnessChangeCause cause) const; + Profile* const profile_; ScopedObserver<AlsReader, AlsReader::Observer> als_reader_observer_; @@ -263,6 +268,13 @@ // Last time brightness change occurred. base::TimeTicks latest_brightness_change_time_; + // Current recorded brightness. It can be either the user requested brightness + // or the model requested brightness. + base::Optional<double> current_brightness_; + + // Used to record number of model-triggered brightness changes. + int brightness_change_counter_ = 1; + base::WeakPtrFactory<Adapter> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(Adapter);
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index f391461..0a449d9 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -296,6 +296,10 @@ ash::prefs::kAccessibilityAutoclickMovementThreshold, ash::kDefaultAutoclickMovementThreshold, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); + registry->RegisterIntegerPref( + ash::prefs::kAccessibilityAutoclickMenuPosition, + static_cast<int>(ash::kDefaultAutoclickMenuPosition), + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterBooleanPref( ash::prefs::kAccessibilityVirtualKeyboardEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC);
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification.cc b/chrome/browser/chromeos/printing/cups_print_job_notification.cc index 07404c0..cc5bb09 100644 --- a/chrome/browser/chromeos/printing/cups_print_job_notification.cc +++ b/chrome/browser/chromeos/printing/cups_print_job_notification.cc
@@ -152,16 +152,17 @@ print_job_->state() == CupsPrintJob::State::STATE_PAGE_DONE) { // If the notification was closed during the printing, prevent showing the // following printing progress. - if (!closed_in_middle_) + if (!closed_in_middle_) { display_service->Display(NotificationHandler::Type::TRANSIENT, - *notification_); + *notification_, /*metadata=*/nullptr); + } } else { closed_in_middle_ = false; // In order to make sure it pop up, we should delete it before readding it. display_service->Close(NotificationHandler::Type::TRANSIENT, notification_id_); display_service->Display(NotificationHandler::Type::TRANSIENT, - *notification_); + *notification_, /*metadata=*/nullptr); } // |print_job_| will be deleted by CupsPrintJobManager if the job is finished
diff --git a/chrome/browser/chromeos/printing/printer_configurer.cc b/chrome/browser/chromeos/printing/printer_configurer.cc index 382b8fd..c178e6d 100644 --- a/chrome/browser/chromeos/printing/printer_configurer.cc +++ b/chrome/browser/chromeos/printing/printer_configurer.cc
@@ -337,7 +337,10 @@ out << "fatal error"; break; case kSuccess: - out << "success"; + out << "add success"; + break; + case kEditSuccess: + out << "edit success"; break; case kPrinterUnreachable: out << "printer unreachable";
diff --git a/chrome/browser/chromeos/printing/printer_configurer.h b/chrome/browser/chromeos/printing/printer_configurer.h index a67df981..00f9d8e 100644 --- a/chrome/browser/chromeos/printing/printer_configurer.h +++ b/chrome/browser/chromeos/printing/printer_configurer.h
@@ -25,6 +25,7 @@ kNativePrintersNotAllowed = 4, // Tried adding/editing printers policy set kInvalidPrinterUpdate = 5, // Tried updating printer with invalid values kComponentUnavailable = 6, // Could not install component + kEditSuccess = 7, // Printer editted successfully // Space left for additional errors // PPD errors
diff --git a/chrome/browser/chromeos/tpm_firmware_update_notification.cc b/chrome/browser/chromeos/tpm_firmware_update_notification.cc index d1fcd32..6eddfe5 100644 --- a/chrome/browser/chromeos/tpm_firmware_update_notification.cc +++ b/chrome/browser/chromeos/tpm_firmware_update_notification.cc
@@ -86,7 +86,8 @@ message_center::SystemNotificationWarningLevel::WARNING); NotificationDisplayServiceFactory::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } } // namespace
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc index bf69e1a..4485eac 100644 --- a/chrome/browser/conflicts/module_database_win.cc +++ b/chrome/browser/conflicts/module_database_win.cc
@@ -207,6 +207,15 @@ } } +// static +void ModuleDatabase::HandleModuleLoadEvent(content::ProcessType process_type, + const base::FilePath& module_path, + uint32_t module_size, + uint32_t module_time_date_stamp) { + ModuleDatabase::GetInstance()->OnModuleLoad( + process_type, module_path, module_size, module_time_date_stamp); +} + void ModuleDatabase::OnModuleBlocked(const base::FilePath& module_path, uint32_t module_size, uint32_t module_time_date_stamp) {
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h index e5949fe87..5fa1580 100644 --- a/chrome/browser/conflicts/module_database_win.h +++ b/chrome/browser/conflicts/module_database_win.h
@@ -104,6 +104,13 @@ uint32_t module_size, uint32_t module_time_date_stamp); + // Forwards the module load event to the ModuleDatabase global instance via + // OnModuleLoad(). Provided for convenience. + static void HandleModuleLoadEvent(content::ProcessType process_type, + const base::FilePath& module_path, + uint32_t module_size, + uint32_t module_time_date_stamp); + void OnModuleBlocked(const base::FilePath& module_path, uint32_t module_size, uint32_t module_time_date_stamp);
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win.cc b/chrome/browser/conflicts/module_event_sink_impl_win.cc index 19370d64..22d630b4 100644 --- a/chrome/browser/conflicts/module_event_sink_impl_win.cc +++ b/chrome/browser/conflicts/module_event_sink_impl_win.cc
@@ -15,11 +15,11 @@ #include "base/bind.h" #include "base/callback.h" #include "base/files/file_path.h" -#include "base/macros.h" +#include "base/sequenced_task_runner.h" #include "base/strings/string_piece.h" #include "base/task/post_task.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/conflicts/module_database_win.h" -#include "chrome/common/conflicts/module_watcher_win.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -97,12 +97,14 @@ } // Handles the module event on a background task. Looks up the path, size and -// time date stamp of the remote process and forwards the event to the -// ModuleDatabase. -void HandleModuleEvent(ModuleDatabase* module_database, - base::Process process, - content::ProcessType process_type, - uint64_t load_address) { +// time date stamp of the remote process and forwards the event to the callback +// on the task runner where the ModuleEventSinkImpl lives. +void HandleModuleEvent( + base::Process process, + content::ProcessType process_type, + uint64_t load_address, + scoped_refptr<base::SequencedTaskRunner> task_runner, + const ModuleEventSinkImpl::OnModuleLoadCallback& on_module_load_callback) { // Load addresses must be aligned with the allocation granularity which is at // least 64KB on any supported Windows OS. if (load_address == 0 || load_address % (64 * 1024) != 0) @@ -128,47 +130,54 @@ uint32_t module_time_date_stamp = 0; if (!GetModuleTimeDateStamp(process.Handle(), load_address, - &module_time_date_stamp)) + &module_time_date_stamp)) { return; + } - // Forward this to the module database. - module_database->OnModuleLoad(process_type, module_path, module_size, - module_time_date_stamp); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(on_module_load_callback, process_type, module_path, + module_size, module_time_date_stamp)); } } // namespace -ModuleEventSinkImpl::ModuleEventSinkImpl(base::Process process, - content::ProcessType process_type, - ModuleDatabase* module_database) +ModuleEventSinkImpl::ModuleEventSinkImpl( + base::Process process, + content::ProcessType process_type, + const OnModuleLoadCallback& on_module_load_callback) : process_(std::move(process)), - module_database_(module_database), - process_type_(process_type) {} + process_type_(process_type), + on_module_load_callback_(on_module_load_callback) {} ModuleEventSinkImpl::~ModuleEventSinkImpl() = default; // static -void ModuleEventSinkImpl::Create(GetProcessCallback get_process, - content::ProcessType process_type, - ModuleDatabase* module_database, - mojom::ModuleEventSinkRequest request) { +void ModuleEventSinkImpl::Create( + GetProcessCallback get_process, + content::ProcessType process_type, + const OnModuleLoadCallback& on_module_load_callback, + mojom::ModuleEventSinkRequest request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::Process process = get_process.Run(); auto module_event_sink_impl = std::make_unique<ModuleEventSinkImpl>( - std::move(process), process_type, module_database); + std::move(process), process_type, on_module_load_callback); mojo::MakeStrongBinding(std::move(module_event_sink_impl), std::move(request)); } void ModuleEventSinkImpl::OnModuleEvents( const std::vector<uint64_t>& module_load_addresses) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + for (uint64_t load_address : module_load_addresses) { // Handle the event on a background sequence. base::PostTaskWithTraits( FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()}, - base::BindOnce(&HandleModuleEvent, module_database_, - process_.Duplicate(), process_type_, load_address)); + base::BindOnce(&HandleModuleEvent, process_.Duplicate(), process_type_, + load_address, base::SequencedTaskRunnerHandle::Get(), + on_module_load_callback_)); } }
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win.h b/chrome/browser/conflicts/module_event_sink_impl_win.h index de588d6..8058e13e 100644 --- a/chrome/browser/conflicts/module_event_sink_impl_win.h +++ b/chrome/browser/conflicts/module_event_sink_impl_win.h
@@ -10,36 +10,45 @@ #include <vector> #include "base/callback_forward.h" +#include "base/macros.h" #include "base/process/process.h" #include "chrome/common/conflicts/module_event_sink_win.mojom.h" #include "content/public/common/process_type.h" -class ModuleDatabase; +namespace base { +class FilePath; +} // Implementation of the mojom::ModuleEventSink interface. This is the endpoint -// in the browser process. This redirects calls to the singleton ModuleDatabase -// object. +// in the browser process. This redirects module events to the provided +// callback. class ModuleEventSinkImpl : public mojom::ModuleEventSink { public: // Callback for retrieving the handle associated with a process. This is used // by "Create" to get a handle to the remote process. using GetProcessCallback = base::Callback<base::Process()>; + using OnModuleLoadCallback = + base::RepeatingCallback<void(content::ProcessType process_type, + const base::FilePath& module_path, + uint32_t module_size, + uint32_t module_time_date_stamp)>; + // Creates a service endpoint that forwards notifications from the remote - // |process| of the provided |process_type| to the provided |module_database|. - // The |module_database| must outlive this object. + // |process| of the provided |process_type| to the provided + // |on_module_load_callback|. ModuleEventSinkImpl(base::Process process, content::ProcessType process_type, - ModuleDatabase* module_database); + const OnModuleLoadCallback& on_module_load_callback); ~ModuleEventSinkImpl() override; // Factory function for use with service_manager::InterfaceRegistry. This - // creates a concrete implementation of mojom::ModuleDatabase interface in the - // current process, for the remote process represented by the provided + // creates a concrete implementation of mojom::ModuleEventSink interface in + // the current process, for the remote process represented by the provided // |request|. This should only be called on the UI thread. static void Create(GetProcessCallback get_process, content::ProcessType process_type, - ModuleDatabase* module_database, + const OnModuleLoadCallback& on_module_load_callback, mojom::ModuleEventSinkRequest request); // mojom::ModuleEventSink implementation: @@ -52,14 +61,13 @@ // A handle to the process on the other side of the pipe. base::Process process_; - // The module database this forwards events to. The |module_database| must - // outlive this object. - ModuleDatabase* module_database_; - // The process ID of the remote process on the other end of the pipe. This is // forwarded along to the ModuleDatabase for each call. content::ProcessType process_type_; + // The callback this forwards events to. + OnModuleLoadCallback on_module_load_callback_; + DISALLOW_COPY_AND_ASSIGN(ModuleEventSinkImpl); };
diff --git a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc b/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc index d0d65fd..9e1cf6bb 100644 --- a/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc +++ b/chrome/browser/conflicts/module_event_sink_impl_win_unittest.cc
@@ -4,18 +4,13 @@ #include "chrome/browser/conflicts/module_event_sink_impl_win.h" +#include <windows.h> + #include <memory> -#include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/conflicts/module_database_win.h" -#include "chrome/common/conflicts/module_watcher_win.h" -#include "chrome/test/base/scoped_testing_local_state.h" -#include "chrome/test/base/testing_browser_process.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" -#include <windows.h> - namespace { // The address of this module in memory. The linker will take care of defining @@ -29,38 +24,40 @@ class ModuleEventSinkImplTest : public testing::Test { protected: - ModuleEventSinkImplTest() - : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()), - module_database_(std::make_unique<ModuleDatabase>( - base::SequencedTaskRunnerHandle::Get())) {} + ModuleEventSinkImplTest() = default; + ~ModuleEventSinkImplTest() override = default; bool CreateModuleSinkImpl() { HANDLE process_handle = 0; if (!::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(), - ::GetCurrentProcess(), &process_handle, - - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) { + ::GetCurrentProcess(), &process_handle, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { return false; } module_event_sink_impl_ = std::make_unique<ModuleEventSinkImpl>( base::Process(process_handle), content::PROCESS_TYPE_BROWSER, - module_database_.get()); + base::BindRepeating(&ModuleEventSinkImplTest::OnModuleEvent, + base::Unretained(this))); return true; } - const ModuleDatabase::ModuleMap& modules() { - return module_database_->modules_; + void OnModuleEvent(content::ProcessType process_type, + const base::FilePath& module_path, + uint32_t module_size, + uint32_t module_time_date_stamp) { + ++module_event_count_; } - // Must be before |module_database_|. + int module_event_count() { return module_event_count_; } + + // Must be first. content::TestBrowserThreadBundle test_browser_thread_bundle_; - ScopedTestingLocalState scoped_testing_local_state_; - std::unique_ptr<ModuleDatabase> module_database_; + std::unique_ptr<ModuleEventSinkImpl> module_event_sink_impl_; + int module_event_count_ = 0; + private: DISALLOW_COPY_AND_ASSIGN(ModuleEventSinkImplTest); }; @@ -68,20 +65,20 @@ TEST_F(ModuleEventSinkImplTest, CallsForwardedAsExpected) { const uintptr_t kValidLoadAddress = reinterpret_cast<uintptr_t>(&__ImageBase); - EXPECT_EQ(0u, modules().size()); + EXPECT_EQ(0, module_event_count()); ASSERT_TRUE(CreateModuleSinkImpl()); - EXPECT_EQ(0u, modules().size()); + EXPECT_EQ(0, module_event_count()); // An invalid load event should not cause a module entry. module_event_sink_impl_->OnModuleEvents({kInvalidLoadAddress}); test_browser_thread_bundle_.RunUntilIdle(); - EXPECT_EQ(0u, modules().size()); + EXPECT_EQ(0, module_event_count()); // A valid load event should cause a module entry. module_event_sink_impl_->OnModuleEvents({kValidLoadAddress}); test_browser_thread_bundle_.RunUntilIdle(); - EXPECT_EQ(1u, modules().size()); + EXPECT_EQ(1, module_event_count()); } TEST_F(ModuleEventSinkImplTest, MultipleEvents) { @@ -90,9 +87,9 @@ reinterpret_cast<uintptr_t>(::GetModuleHandle(L"kernel32.dll")); ASSERT_TRUE(CreateModuleSinkImpl()); - EXPECT_EQ(0u, modules().size()); + EXPECT_EQ(0, module_event_count()); module_event_sink_impl_->OnModuleEvents({kLoadAddress1, kLoadAddress2}); test_browser_thread_bundle_.RunUntilIdle(); - EXPECT_EQ(2u, modules().size()); + EXPECT_EQ(2, module_event_count()); }
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc index 4bb29ad..73c6beb 100644 --- a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc +++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
@@ -337,8 +337,8 @@ module_analysis_disabled_ = true; if (incompatible_applications_updater_) incompatible_applications_updater_->DisableModuleAnalysis(); - if (incompatible_applications_updater_) - incompatible_applications_updater_->DisableModuleAnalysis(); + if (module_blacklist_cache_updater_) + module_blacklist_cache_updater_->DisableModuleAnalysis(); } void ThirdPartyConflictsManager::OnModuleListFilterCreated(
diff --git a/chrome/browser/data_saver/data_saver_browsertest.cc b/chrome/browser/data_saver/data_saver_browsertest.cc index a704b6f8..27152ef5 100644 --- a/chrome/browser/data_saver/data_saver_browsertest.cc +++ b/chrome/browser/data_saver/data_saver_browsertest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" @@ -27,6 +26,15 @@ namespace { +void SetDataSaverEnabled(content::BrowserContext* browser_context, + bool enabled) { + data_reduction_proxy::DataReductionProxySettings* + data_reduction_proxy_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser_context); + data_reduction_proxy_settings->SetDataReductionProxyEnabled(enabled); +} + // Test version of the observer. Used to wait for the event when the network // quality tracker sends the network quality change notification. class TestEffectiveConnectionTypeObserver @@ -147,10 +155,7 @@ class DataSaverBrowserTest : public InProcessBrowserTest { protected: void EnableDataSaver(bool enabled) { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, enabled); - // Give the setting notification a chance to propagate. - content::RunAllPendingInMessageLoop(); + SetDataSaverEnabled(browser()->profile(), enabled); } void VerifySaveDataHeader(const std::string& expected_header_value) { @@ -186,11 +191,9 @@ base::Unretained(this))); test_server_->ServeFilesFromSourceDirectory("chrome/test/data"); } + void EnableDataSaver(bool enabled) { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, enabled); - // Give the setting notification a chance to propagate. - content::RunAllPendingInMessageLoop(); + SetDataSaverEnabled(browser()->profile(), enabled); } net::EffectiveConnectionType GetEffectiveConnectionType() const { @@ -320,10 +323,7 @@ class DataSaverForWorkerBrowserTest : public InProcessBrowserTest { protected: void EnableDataSaver(bool enabled) { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, enabled); - // Give the setting notification a chance to propagate. - content::RunAllPendingInMessageLoop(); + SetDataSaverEnabled(browser()->profile(), enabled); } std::unique_ptr<net::test_server::HttpResponse> CaptureHeaderHandler(
diff --git a/chrome/browser/data_saver/data_saver_holdback_browsertest.cc b/chrome/browser/data_saver/data_saver_holdback_browsertest.cc index 3826465..a0b50d9 100644 --- a/chrome/browser/data_saver/data_saver_holdback_browsertest.cc +++ b/chrome/browser/data_saver/data_saver_holdback_browsertest.cc
@@ -5,10 +5,11 @@ #include <string> #include "base/metrics/field_trial_param_associator.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" @@ -29,9 +30,11 @@ } void EnableDataSaver(bool enabled) { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, enabled); - content::RunAllPendingInMessageLoop(); + data_reduction_proxy::DataReductionProxySettings* + data_reduction_proxy_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser()->profile()); + data_reduction_proxy_settings->SetDataReductionProxyEnabled(enabled); } void VerifySaveDataHeader(const std::string& expected_header_value) {
diff --git a/chrome/browser/data_saver/data_saver_webapis_browsertest.cc b/chrome/browser/data_saver/data_saver_webapis_browsertest.cc index 83385c5f..e6504dd 100644 --- a/chrome/browser/data_saver/data_saver_webapis_browsertest.cc +++ b/chrome/browser/data_saver/data_saver_webapis_browsertest.cc
@@ -6,11 +6,12 @@ #include <string> #include "base/command_line.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/prefs/pref_service.h" @@ -26,10 +27,11 @@ class DataSaverWebAPIsBrowserTest : public InProcessBrowserTest { protected: void EnableDataSaver(bool enabled) { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, enabled); - // Give the setting notification a chance to propagate. - content::RunAllPendingInMessageLoop(); + data_reduction_proxy::DataReductionProxySettings* + data_reduction_proxy_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser()->profile()); + data_reduction_proxy_settings->SetDataReductionProxyEnabled(enabled); } void SetUp() override {
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc index 0e77bff..d65fbe3 100644 --- a/chrome/browser/download/notification/download_item_notification.cc +++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -250,7 +250,8 @@ notification_->set_priority(message_center::LOW_PRIORITY); closed_ = false; NotificationDisplayServiceFactory::GetForProfile(profile())->Display( - NotificationHandler::Type::TRANSIENT, *notification_); + NotificationHandler::Type::TRANSIENT, *notification_, + /*metadata=*/nullptr); } void DownloadItemNotification::Close(bool by_user) { @@ -450,7 +451,8 @@ if (display) { closed_ = false; NotificationDisplayServiceFactory::GetForProfile(profile())->Display( - NotificationHandler::Type::TRANSIENT, *notification_); + NotificationHandler::Type::TRANSIENT, *notification_, + /*metadata=*/nullptr); } if (item_->IsDone() && image_decode_status_ == NOT_STARTED) {
diff --git a/chrome/browser/download/notification/download_item_notification_unittest.cc b/chrome/browser/download/notification/download_item_notification_unittest.cc index e11255e9..80be557 100644 --- a/chrome/browser/download/notification/download_item_notification_unittest.cc +++ b/chrome/browser/download/notification/download_item_notification_unittest.cc
@@ -129,7 +129,7 @@ download_notification_manager_->items_.at(id).get(); NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( NotificationHandler::Type::TRANSIENT, - *download_item_notification_->notification_); + *download_item_notification_->notification_, /*metadata=*/nullptr); } content::TestBrowserThreadBundle test_browser_thread_bundle_;
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 5cb018b74..e750e240 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -967,7 +967,6 @@ } deps += [ "//ash/public/cpp", - "//chrome/browser/chromeos/kiosk_next_home", "//chrome/browser/chromeos/kiosk_next_home/mojom", "//chrome/browser/resources/chromeos/camera:chrome_camera_app", "//chromeos/attestation", @@ -987,6 +986,7 @@ "//components/constrained_window", "//components/drive", "//components/user_manager", + "//media/capture:capture_lib", "//media/capture/video/chromeos/mojo:cros_camera", "//remoting/base", "//remoting/host",
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc index e87786b..0e9dad5 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -41,11 +41,13 @@ #if defined(OS_CHROMEOS) if (arc::IsArcPlayStoreEnabledForProfile( Profile::FromBrowserContext(browser_context))) { - return IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX_ARC; + return IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX_ARC; + } else { + return IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX; } -#endif - +#else return IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX; +#endif } } // namespace
diff --git a/chrome/browser/extensions/api/file_system/request_file_system_notification.cc b/chrome/browser/extensions/api/file_system/request_file_system_notification.cc index cbb73bb..f4672d8 100644 --- a/chrome/browser/extensions/api/file_system/request_file_system_notification.cc +++ b/chrome/browser/extensions/api/file_system/request_file_system_notification.cc
@@ -60,7 +60,8 @@ pending_notification_->set_icon(*extension_icon_); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *pending_notification_); + NotificationHandler::Type::TRANSIENT, *pending_notification_, + /*metadata=*/nullptr); delete this; }
diff --git a/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc b/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc index 1e3bff25..b140a5d1 100644 --- a/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc +++ b/chrome/browser/extensions/api/notifications/extension_notification_display_helper.cc
@@ -31,7 +31,7 @@ std::make_unique<message_center::Notification>(notification)); GetDisplayService()->Display(NotificationHandler::Type::EXTENSION, - notification); + notification, /*metadata=*/nullptr); } message_center::Notification*
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index 08610ed..1882be6 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -35,6 +35,7 @@ #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/window_controller.h" #include "chrome/browser/extensions/window_controller_list.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" @@ -97,7 +98,6 @@ #include "ui/base/ui_base_types.h" #if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" @@ -746,23 +746,23 @@ } #if defined(OS_CHROMEOS) - const bool is_window_trusted_pinned = - ash::IsWindowTrustedPinned(browser->window()); + const bool is_locked_fullscreen = + platform_util::IsBrowserLockedFullscreen(browser); // Don't allow locked fullscreen operations on a window without the proper // permission (also don't allow any operations on a locked window if the // extension doesn't have the permission). - if (is_window_trusted_pinned && + if (is_locked_fullscreen && !ExtensionHasLockedFullscreenPermission(extension())) { return RespondNow( Error(tabs_constants::kMissingLockWindowFullscreenPrivatePermission)); } // state will be WINDOW_STATE_NONE if the state parameter wasn't passed from // the JS side, and in that case we don't want to change the locked state. - if (is_window_trusted_pinned && + if (is_locked_fullscreen && params->update_info.state != windows::WINDOW_STATE_LOCKED_FULLSCREEN && params->update_info.state != windows::WINDOW_STATE_NONE) { SetLockedFullscreenState(browser, false); - } else if (!is_window_trusted_pinned && + } else if (!is_locked_fullscreen && params->update_info.state == windows::WINDOW_STATE_LOCKED_FULLSCREEN) { SetLockedFullscreenState(browser, true); @@ -873,13 +873,11 @@ return RespondNow(Error(error)); } -#if defined(OS_CHROMEOS) - if (ash::IsWindowTrustedPinned(browser->window()) && + if (platform_util::IsBrowserLockedFullscreen(browser) && !ExtensionHasLockedFullscreenPermission(extension())) { return RespondNow( Error(tabs_constants::kMissingLockWindowFullscreenPrivatePermission)); } -#endif WindowController* controller = browser->extension_window_controller(); WindowController::Reason reason;
diff --git a/chrome/browser/extensions/chrome_extensions_interface_registration.cc b/chrome/browser/extensions/chrome_extensions_interface_registration.cc index 401c43b..d70b7d4 100644 --- a/chrome/browser/extensions/chrome_extensions_interface_registration.cc +++ b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
@@ -28,10 +28,15 @@ #include "chromeos/services/ime/public/mojom/constants.mojom.h" #include "chromeos/services/ime/public/mojom/input_engine.mojom.h" #include "chromeos/services/media_perception/public/mojom/media_perception.mojom.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/media_device_id.h" #include "content/public/common/service_manager_connection.h" #include "extensions/browser/api/extensions_api_client.h" #include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h" #include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#include "media/capture/video/chromeos/renderer_facing_cros_image_capture.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/connector.h" #include "services/video_capture/public/mojom/constants.mojom.h" #endif @@ -61,18 +66,64 @@ static_cast<chromeos::kiosk_next_home::KioskNextHomeInterfaceBrokerImpl*>( context->GetUserData(kKioskNextHomeInterfaceBrokerImplKey)); if (!impl) { - auto* connector = content::BrowserContext::GetConnectorFor(context); - if (!connector) - return; auto new_impl = std::make_unique< - chromeos::kiosk_next_home::KioskNextHomeInterfaceBrokerImpl>(connector); + chromeos::kiosk_next_home::KioskNextHomeInterfaceBrokerImpl>(context); impl = new_impl.get(); context->SetUserData(kKioskNextHomeInterfaceBrokerImplKey, std::move(new_impl)); } impl->BindRequest(std::move(request)); } + +// Translates the renderer-side source ID to video device id. +void TranslateVideoDeviceId( + const std::string& salt, + const url::Origin& origin, + const std::string& source_id, + base::OnceCallback<void(const base::Optional<std::string>&)> callback) { + auto callback_on_io_thread = base::BindOnce( + [](const std::string& salt, const url::Origin& origin, + const std::string& source_id, + base::OnceCallback<void(const base::Optional<std::string>&)> + callback) { + content::GetMediaDeviceIDForHMAC(blink::MEDIA_DEVICE_VIDEO_CAPTURE, + salt, std::move(origin), source_id, + std::move(callback)); + }, + salt, std::move(origin), source_id, std::move(callback)); + base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, + std::move(callback_on_io_thread)); +} + +// Binds CrosImageCaptureRequest to a proxy which translates the source id into +// video device id and then forward the request to video capture service. +void BindRendererFacingCrosImageCapture( + cros::mojom::CrosImageCaptureRequest request, + content::RenderFrameHost* source) { + cros::mojom::CrosImageCapturePtr proxy_ptr; + auto proxy_request = mojo::MakeRequest(&proxy_ptr); + + // Bind proxy request to video_capture service. + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(video_capture::mojom::kServiceName, + std::move(proxy_request)); + + auto security_origin = source->GetLastCommittedOrigin(); + auto media_device_id_salt = + source->GetProcess()->GetBrowserContext()->GetMediaDeviceIDSalt(); + + auto mapping_callback = + base::BindRepeating(&TranslateVideoDeviceId, media_device_id_salt, + std::move(security_origin)); + + // Bind origin request to proxy implementation. + auto api_proxy = std::make_unique<media::RendererFacingCrosImageCapture>( + std::move(proxy_ptr), std::move(mapping_callback)); + mojo::MakeStrongBinding(std::move(api_proxy), std::move(request)); +} #endif + } // namespace void RegisterChromeInterfacesForExtension( @@ -128,8 +179,7 @@ if (extension->id().compare(extension_misc::kChromeCameraAppId) == 0 || extension->id().compare(extension_misc::kChromeCameraAppDevId) == 0) { registry->AddInterface( - base::BindRepeating(&ForwardRequest<cros::mojom::CrosImageCapture>, - video_capture::mojom::kServiceName)); + base::BindRepeating(&BindRendererFacingCrosImageCapture)); } #endif }
diff --git a/chrome/browser/extensions/extension_storage_monitor.cc b/chrome/browser/extensions/extension_storage_monitor.cc index 50f7a416..b00bfed1 100644 --- a/chrome/browser/extensions/extension_storage_monitor.cc +++ b/chrome/browser/extensions/extension_storage_monitor.cc
@@ -437,7 +437,7 @@ weak_ptr_factory_.GetWeakPtr(), extension_id))); notification.SetSystemPriority(); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); notified_extension_ids_.insert(extension_id); }
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index 5d5e34f..848a6d9 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/tab_helper.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h" #include "chrome/browser/sessions/session_tab_helper.h" @@ -49,10 +50,6 @@ #include "extensions/common/permissions/permissions_data.h" #include "url/gurl.h" -#if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" -#endif - using content::NavigationEntry; using content::WebContents; @@ -453,10 +450,8 @@ window_state = tabs_constants::kShowStateValueMinimized; } else if (window->IsFullscreen()) { window_state = tabs_constants::kShowStateValueFullscreen; -#if defined(OS_CHROMEOS) - if (ash::IsWindowTrustedPinned(window)) + if (platform_util::IsBrowserLockedFullscreen(&browser)) window_state = tabs_constants::kShowStateValueLockedFullscreen; -#endif } else if (window->IsMaximized()) { window_state = tabs_constants::kShowStateValueMaximized; } else {
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc index 8f60e60d..ea311eb9 100644 --- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc +++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -15,11 +15,12 @@ #include "base/task/post_task.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/channel_info.h" -#include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/sync/driver/about_sync_util.h" #include "components/sync/driver/sync_service.h" @@ -350,12 +351,15 @@ void ChromeInternalLogSource::PopulateDataReductionProxyLogs( SystemLogsResponse* response) { - PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - bool is_data_reduction_proxy_enabled = - prefs->HasPrefPath(prefs::kDataSaverEnabled) && - prefs->GetBoolean(prefs::kDataSaverEnabled); + data_reduction_proxy::DataReductionProxySettings* + data_reduction_proxy_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + ProfileManager::GetActiveUserProfile()); + bool data_saver_enabled = + data_reduction_proxy_settings && + data_reduction_proxy_settings->IsDataReductionProxyEnabled(); response->emplace(kDataReductionProxyKey, - is_data_reduction_proxy_enabled ? "enabled" : "disabled"); + data_saver_enabled ? "enabled" : "disabled"); } #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 84e5a4ce..93d80c5 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -695,6 +695,11 @@ "expiry_milestone": 76 }, { + "name": "draw-vertically-edge-to-edge", + "owners": [ "chrome-android-app@chromium.org" ], + "expiry_milestone": 88 + }, + { "name": "enable-accessibility-object-model", "owners": [ "//ui/accessibility/OWNERS" ], "expiry_milestone": 76 @@ -2032,6 +2037,11 @@ "expiry_milestone": 76 }, { + "name": "extensions-toolbar-menu", + "owners": [ "//extensions/OWNERS", "pbos" ], + "expiry_milestone": 80 + }, + { "name": "extensions-on-chrome-urls", "owners": [ "//extensions/OWNERS" ], // This enables the use of extensions on chrome:// URLs. This is useful for
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 15365bf..732c062 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -81,6 +81,11 @@ const char kDelegateOverscrollSwipesDescription[] = "Delegate overscroll swipes to websites first"; +const char kDrawVerticallyEdgeToEdgeName[] = + "Draw contents vertically from edge to edge."; +const char kDrawVerticallyEdgeToEdgeDescription[] = + "Draw contents vertically from edge to edge."; + const char kEnableBlinkHeapUnifiedGarbageCollectionName[] = "Blink Heap Unified Garbage Collection"; const char kEnableBlinkHeapUnifiedGarbageCollectionDescription[] = @@ -1044,6 +1049,10 @@ const char kExtensionContentVerificationEnforceStrict[] = "Enforce strict (hard fail if we can't get hashes)"; +const char kExtensionsToolbarMenuName[] = "Extensions Toolbar Menu"; +const char kExtensionsToolbarMenuDescription[] = + "Enable a separate toolbar button and menu for extensions"; + const char kExtensionsOnChromeUrlsName[] = "Extensions on chrome:// URLs"; const char kExtensionsOnChromeUrlsDescription[] = "Enables running extensions on chrome:// URLs, where extensions explicitly "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 6657f67..ef7fe77 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -172,6 +172,9 @@ extern const char kDelegateOverscrollSwipesName[]; extern const char kDelegateOverscrollSwipesDescription[]; +extern const char kDrawVerticallyEdgeToEdgeName[]; +extern const char kDrawVerticallyEdgeToEdgeDescription[]; + extern const char kExperimentalAccessibilityFeaturesName[]; extern const char kExperimentalAccessibilityFeaturesDescription[]; @@ -618,6 +621,9 @@ extern const char kExtensionContentVerificationEnforce[]; extern const char kExtensionContentVerificationEnforceStrict[]; +extern const char kExtensionsToolbarMenuName[]; +extern const char kExtensionsToolbarMenuDescription[]; + extern const char kExtensionsOnChromeUrlsName[]; extern const char kExtensionsOnChromeUrlsDescription[];
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc index e6b510d..1d034c55 100644 --- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc +++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
@@ -85,8 +85,12 @@ PopulateStringsForSharedHTML(load_time_data); - load_time_data->SetString("tabTitle", - l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_TITLE)); + load_time_data->SetString( + "tabTitle", + l10n_util::GetStringFUTF16( + IDS_LOOKALIKE_URL_TITLE, + security_interstitials::common_string_util::GetFormattedHostName( + request_url()))); load_time_data->SetString( "heading", l10n_util::GetStringFUTF16( @@ -98,6 +102,9 @@ l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH)); load_time_data->SetString( "proceedButtonText", l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_IGNORE)); + load_time_data->SetString( + "primaryButtonText", + l10n_util::GetStringUTF16(IDS_LOOKALIKE_URL_CONTINUE)); } void LookalikeUrlInterstitialPage::OnInterstitialClosing() { @@ -170,7 +177,6 @@ load_time_data->SetString("openDetails", ""); load_time_data->SetString("explanationParagraph", ""); load_time_data->SetString("finalParagraph", ""); - load_time_data->SetString("primaryButtonText", ""); load_time_data->SetString("type", "LOOKALIKE"); }
diff --git a/chrome/browser/mac/keystone_glue.h b/chrome/browser/mac/keystone_glue.h index 80dde92b..624637184 100644 --- a/chrome/browser/mac/keystone_glue.h +++ b/chrome/browser/mac/keystone_glue.h
@@ -96,10 +96,6 @@ // YES if an update was ever successfully installed by -installUpdate. BOOL updateSuccessfullyInstalled_; - - // Profile count information. - uint32_t numProfiles_; - uint32_t numSignedInProfiles_; } // Return the default Keystone Glue object. @@ -172,16 +168,13 @@ // asynchronous mode. - (void)promoteTicket; +// Set the registration active. +- (void)setRegistrationActive; + // Sets a new value for appPath. Used during installation to point a ticket // at the installed copy. - (void)setAppPath:(NSString*)appPath; -// Sets the total number of profiles and the number of signed in profiles. -// Passing zeroes sets the application as active, but does not update -// profile metrics. -- (void)updateProfileCountsWithNumProfiles:(uint32_t)profiles - numSignedInProfiles:(uint32_t)signedInProfiles; - @end // @interface KeystoneGlue @interface KeystoneGlue(ExposedForTesting)
diff --git a/chrome/browser/mac/keystone_glue.mm b/chrome/browser/mac/keystone_glue.mm index a9e43d3..941c95d 100644 --- a/chrome/browser/mac/keystone_glue.mm +++ b/chrome/browser/mac/keystone_glue.mm
@@ -133,9 +133,6 @@ // Called when Keystone registration completes. - (void)registrationComplete:(NSNotification*)notification; -// Set the registration active and pass profile count parameters. -- (void)setRegistrationActive; - // Called periodically to announce activity by pinging the Keystone server. - (void)markActive:(NSTimer*)timer; @@ -492,43 +489,10 @@ - (void)setRegistrationActive { DCHECK(registration_); - registrationActive_ = YES; - - // During startup, numProfiles_ defaults to 0. - if (!numProfiles_) { - [registration_ setActive]; - return; - } - - NSError* reportingError = nil; - - KSReportingAttribute* numAccountsAttr = - [ksUnsignedReportingAttributeClass_ - reportingAttributeWithValue:numProfiles_ - name:@"_NumAccounts" - aggregationType:kKSReportingAggregationSum - error:&reportingError]; - if (reportingError != nil) - VLOG(1) << [reportingError localizedDescription]; - reportingError = nil; - - KSReportingAttribute* numSignedInAccountsAttr = - [ksUnsignedReportingAttributeClass_ - reportingAttributeWithValue:numSignedInProfiles_ - name:@"_NumSignedIn" - aggregationType:kKSReportingAggregationSum - error:&reportingError]; - if (reportingError != nil) - VLOG(1) << [reportingError localizedDescription]; - reportingError = nil; - - NSArray* profileCountsInformation = - [NSArray arrayWithObjects:numAccountsAttr, numSignedInAccountsAttr, nil]; - - if (![registration_ setActiveWithReportingAttributes:profileCountsInformation - error:&reportingError]) { - VLOG(1) << [reportingError localizedDescription]; + NSError* setActiveError = nil; + if (![registration_ setActiveWithError:&setActiveError]) { + VLOG(1) << [setActiveError localizedDescription]; } } @@ -1179,14 +1143,6 @@ return tagSuffix; } - -- (void)updateProfileCountsWithNumProfiles:(uint32_t)profiles - numSignedInProfiles:(uint32_t)signedInProfiles { - numProfiles_ = profiles; - numSignedInProfiles_ = signedInProfiles; - [self setRegistrationActive]; -} - @end // @implementation KeystoneGlue namespace {
diff --git a/chrome/browser/mac/keystone_glue_unittest.mm b/chrome/browser/mac/keystone_glue_unittest.mm index ee7aefd..eb51945 100644 --- a/chrome/browser/mac/keystone_glue_unittest.mm +++ b/chrome/browser/mac/keystone_glue_unittest.mm
@@ -36,12 +36,7 @@ return NO; } -- (BOOL)setActive { - return NO; -} - -- (BOOL)setActiveWithReportingAttributes:(NSArray*)reportingAttributes - error:(NSError**)error { +- (BOOL)setActiveWithError:(NSError**)error { return NO; }
diff --git a/chrome/browser/mac/keystone_registration.h b/chrome/browser/mac/keystone_registration.h index 1771ca6..f09ca58 100644 --- a/chrome/browser/mac/keystone_registration.h +++ b/chrome/browser/mac/keystone_registration.h
@@ -51,19 +51,10 @@ extern NSString* KSUpdateCheckSuccessfullyInstalledKey; extern NSString* KSRegistrationRemoveExistingTag; - -extern NSString* KSReportingAttributeValueKey; -extern NSString* KSReportingAttributeExpirationDateKey; -extern NSString* KSReportingAttributeAggregationTypeKey; #define KSRegistrationPreserveExistingTag nil } // namespace keystone_registration -typedef enum { - kKSReportingAggregationSum = 0, // Adds attribute value across user accounts - kKSReportingAggregationDefault = kKSReportingAggregationSum, -} KSReportingAggregationType; - @interface KSRegistration : NSObject + (id)registrationWithProductID:(NSString*)productID; @@ -73,31 +64,11 @@ - (BOOL)promoteWithParameters:(NSDictionary*)args authorization:(AuthorizationRef)authorization; -- (BOOL)setActive; -- (BOOL)setActiveWithReportingAttributes:(NSArray*)reportingAttributes - error:(NSError**)error; +- (BOOL)setActiveWithError:(NSError**)error; - (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated; - (void)startUpdate; - (keystone_registration::KSRegistrationTicketType)ticketType; @end // @interface KSRegistration - -// Declarations of the Keystone attribute reporting bits needed here. -// Full definition is at: -// //depot/googlemac/opensource/update-engine/Common/KSReportingAttribute.h -@interface KSReportingAttribute : NSObject - -@end // @interface KSReportingAttribute - -@interface KSUnsignedReportingAttribute : KSReportingAttribute - -+ (KSUnsignedReportingAttribute *)reportingAttributeWithValue:(uint32_t)value - name:(NSString *)name - aggregationType:(KSReportingAggregationType)aggregationType - error:(NSError **)error; - -@end // @interface KSUnsignedReportingAttribute - - #endif // CHROME_BROWSER_MAC_KEYSTONE_REGISTRATION_H_
diff --git a/chrome/browser/media/android/cdm/media_drm_origin_id_manager_factory.cc b/chrome/browser/media/android/cdm/media_drm_origin_id_manager_factory.cc index 87106d0..a6f96f1 100644 --- a/chrome/browser/media/android/cdm/media_drm_origin_id_manager_factory.cc +++ b/chrome/browser/media/android/cdm/media_drm_origin_id_manager_factory.cc
@@ -54,5 +54,6 @@ // pre-provisioning at startup. Creation will end up calling // GetBrowserContextToUse() above which returns NULL for incognito contexts, // and thus no instance will be created for them. - return base::FeatureList::IsEnabled(media::kMediaDrmPreprovisioningAtStartup); + return base::FeatureList::IsEnabled(media::kMediaDrmPreprovisioning) && + base::FeatureList::IsEnabled(media::kMediaDrmPreprovisioningAtStartup); }
diff --git a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc index 15cdfeb..484b6b3 100644 --- a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc +++ b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc
@@ -21,12 +21,17 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "media/base/android/media_drm_bridge.h" +#include "media/base/media_switches.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace { -void CreateOriginId(Profile* profile, - MediaDrmOriginIdManager::ProvisionedOriginIdCB callback) { +using MediaDrmOriginId = media::MediaDrmStorage::MediaDrmOriginId; +using OriginIdReadyCB = + base::OnceCallback<void(bool success, const MediaDrmOriginId& origin_id)>; + +void CreateOriginIdWithMediaDrmOriginIdManager(Profile* profile, + OriginIdReadyCB callback) { // Only need to origin IDs if MediaDrm supports it. DCHECK(media::MediaDrmBridge::IsPerOriginProvisioningSupported()); @@ -40,6 +45,16 @@ origin_id_manager->GetOriginId(std::move(callback)); } +void CreateOriginId(OriginIdReadyCB callback) { + // Only need to origin IDs if MediaDrm supports it. + DCHECK(media::MediaDrmBridge::IsPerOriginProvisioningSupported()); + + auto origin_id = base::UnguessableToken::Create(); + DVLOG(2) << __func__ << ": origin_id = " << origin_id; + + std::move(callback).Run(true, origin_id); +} + void AllowEmptyOriginId(content::RenderFrameHost* render_frame_host, base::OnceCallback<void(bool)> callback) { DCHECK(media::MediaDrmBridge::IsPerOriginProvisioningSupported()); @@ -82,11 +97,18 @@ return; } + // Only use MediaDrmOriginIdManager's preprovisioned origin IDs when feature + // kMediaDrmPreprovisioning is enabled. + auto get_origin_id_cb = + base::FeatureList::IsEnabled(media::kMediaDrmPreprovisioning) + ? base::BindRepeating(&CreateOriginIdWithMediaDrmOriginIdManager, + profile) + : base::BindRepeating(&CreateOriginId); + // The object will be deleted on connection error, or when the frame navigates // away. See FrameServiceBase for details. new cdm::MediaDrmStorageImpl( - render_frame_host, pref_service, - base::BindRepeating(&CreateOriginId, profile), + render_frame_host, pref_service, get_origin_id_cb, base::BindRepeating(&AllowEmptyOriginId, render_frame_host), std::move(request)); }
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc index bf711fb..d5a7429 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.cc +++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -90,6 +90,10 @@ metrics_services_manager_->GetVariationsService()->EnsureLocaleEquals(locale); } +void ChromeFeatureListCreator::OverrideCachedUIStrings() { + metrics_services_manager_->GetVariationsService()->OverrideCachedUIStrings(); +} + metrics_services_manager::MetricsServicesManagerClient* ChromeFeatureListCreator::GetMetricsServicesManagerClient() { return metrics_services_manager_client_;
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h index 1b3434c..4df5a25 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.h +++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -41,6 +41,9 @@ // what was used when creating field trials. void SetApplicationLocale(const std::string& locale); + // Overrides cached UI strings on the resource bundle once it is initialized. + void OverrideCachedUIStrings(); + // Gets the MetricsServicesManagerClient* used in this class. metrics_services_manager::MetricsServicesManagerClient* GetMetricsServicesManagerClient();
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 49bf153..36c4106 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -103,8 +103,6 @@ #include "base/android/build_info.h" #include "chrome/browser/metrics/android_metrics_provider.h" #include "chrome/browser/metrics/page_load_metrics_provider.h" -#include "chrome/browser/ui/android/tab_model/tab_model_list.h" -#include "chrome/browser/ui/android/tab_model/tab_model_list_observer.h" #endif #if defined(OS_POSIX) @@ -356,25 +354,6 @@ } #endif // OS_WIN -#if defined(OS_ANDROID) -class AndroidIncognitoObserver : public TabModelListObserver { - public: - explicit AndroidIncognitoObserver(ChromeMetricsServiceClient* parent) - : parent_(parent) { - TabModelList::AddObserver(this); - } - - ~AndroidIncognitoObserver() override { TabModelList::RemoveObserver(this); } - - void OnTabModelAdded() override { parent_->UpdateRunningServices(); } - - void OnTabModelRemoved() override { parent_->UpdateRunningServices(); } - - private: - ChromeMetricsServiceClient* parent_; -}; -#endif - ChromeMetricsServiceClient::IsProcessRunningFunction g_is_process_running = nullptr; @@ -420,10 +399,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); RecordCommandLineMetrics(); notification_listeners_active_ = RegisterForNotifications(); -#if defined(OS_ANDROID) - incognito_observer_ = std::make_unique<AndroidIncognitoObserver>(this); - notification_listeners_active_ &= (incognito_observer_ != nullptr); -#endif + incognito_observer_ = std::make_unique<IncognitoObserver>( + base::BindRepeating(&ChromeMetricsServiceClient::UpdateRunningServices, + weak_ptr_factory_.GetWeakPtr())); } ChromeMetricsServiceClient::~ChromeMetricsServiceClient() { @@ -899,8 +877,6 @@ // Observe history deletions for all profiles. registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, - content::NotificationService::AllBrowserContextsAndSources()); bool all_profiles_succeeded = true; for (Profile* profile : @@ -955,8 +931,6 @@ switch (type) { case chrome::NOTIFICATION_BROWSER_OPENED: - // May have opened an incognito window. - UpdateRunningServices(); metrics_service_->OnApplicationNotIdle(); break; case chrome::NOTIFICATION_BROWSER_CLOSED: @@ -972,16 +946,14 @@ case chrome::NOTIFICATION_PROFILE_ADDED: { bool success = RegisterForProfileEvents(content::Source<Profile>(source).ptr()); + // On failure, set |notification_listeners_active_| to false which will + // disable UKM reporting via UpdateRunningServices(). if (!success && notification_listeners_active_) { notification_listeners_active_ = false; UpdateRunningServices(); } break; } - case chrome::NOTIFICATION_PROFILE_DESTROYED: - // May have closed last incognito window. - UpdateRunningServices(); - break; default: NOTREACHED();
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index 56b9eff..33bc20a1 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -18,6 +18,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "build/build_config.h" +#include "chrome/browser/metrics/incognito_observer.h" #include "chrome/browser/metrics/metrics_memory_details.h" #include "components/metrics/file_metrics_provider.h" #include "components/metrics/metrics_log_uploader.h" @@ -34,11 +35,6 @@ class Profile; class PrefRegistrySimple; -#if defined(OS_ANDROID) -class TabModelListObserver; -#endif // defined(OS_ANDROID) - - namespace metrics { class MetricsService; class MetricsStateManager; @@ -176,12 +172,8 @@ content::NotificationRegistrar registrar_; -#if defined(OS_ANDROID) // Listener for changes in incognito activity. - // Desktop platform use BrowserList, and can listen for - // chrome::NOTIFICATION_BROWSER_OPENED instead. - std::unique_ptr<TabModelListObserver> incognito_observer_; -#endif // defined(OS_ANDROID) + std::unique_ptr<IncognitoObserver> incognito_observer_; // Whether we registered all notification listeners successfully. bool notification_listeners_active_;
diff --git a/chrome/browser/metrics/incognito_observer.cc b/chrome/browser/metrics/incognito_observer.cc new file mode 100644 index 0000000..a00c2ce --- /dev/null +++ b/chrome/browser/metrics/incognito_observer.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/metrics/incognito_observer.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "content/public/browser/notification_service.h" + +IncognitoObserver::IncognitoObserver( + const base::RepeatingClosure& update_closure) + : update_closure_(update_closure) { +#if defined(OS_ANDROID) + TabModelList::AddObserver(this); +#endif + + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, + content::NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::NotificationService::AllBrowserContextsAndSources()); +} + +IncognitoObserver::~IncognitoObserver() { +#if defined(OS_ANDROID) + TabModelList::RemoveObserver(this); +#endif +} + +#if defined(OS_ANDROID) +void IncognitoObserver::OnTabModelAdded() { + update_closure_.Run(); +} + +void IncognitoObserver::OnTabModelRemoved() { + update_closure_.Run(); +} +#endif + +void IncognitoObserver::Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case chrome::NOTIFICATION_BROWSER_OPENED: + case chrome::NOTIFICATION_PROFILE_DESTROYED: + update_closure_.Run(); + break; + + default: + NOTREACHED(); + } +}
diff --git a/chrome/browser/metrics/incognito_observer.h b/chrome/browser/metrics/incognito_observer.h new file mode 100644 index 0000000..d7f9745 --- /dev/null +++ b/chrome/browser/metrics/incognito_observer.h
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_METRICS_INCOGNITO_OBSERVER_H_ +#define CHROME_BROWSER_METRICS_INCOGNITO_OBSERVER_H_ + +#include "base/callback.h" +#include "build/build_config.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +#if defined(OS_ANDROID) +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list_observer.h" +#endif + +// Encapsulates platform-specific functionality for observing events that may +// cause "is incognito active?" state to change. The class takes a closure that +// will be called when an event happens that could result in a state change. +// The incognito state should then be checked by the callback. +// TODO(asvitkine): Considering moving the check for incognito to this class +// too; see ChromeMetricsServicesManagerClient::IsIncognitoSessionActive(). +class IncognitoObserver : +#if defined(OS_ANDROID) + public TabModelListObserver, +#endif + content::NotificationObserver { + public: + explicit IncognitoObserver(const base::RepeatingClosure& update_closure); + ~IncognitoObserver() override; + + private: +#if defined(OS_ANDROID) + // TabModelListObserver: + void OnTabModelAdded() override; + void OnTabModelRemoved() override; +#endif + + // content::NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + const base::RepeatingClosure update_closure_; + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(IncognitoObserver); +}; + +#endif // CHROME_BROWSER_METRICS_INCOGNITO_OBSERVER_H_
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc index b374f19..32fd511 100644 --- a/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc +++ b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc
@@ -53,14 +53,16 @@ auto* display_service = NotificationDisplayService::GetForProfile(browser()->profile()); - display_service->Display(NotificationHandler::Type::TRANSIENT, notification); + display_service->Display(NotificationHandler::Type::TRANSIENT, notification, + /*metadata=*/nullptr); display_service->Close(NotificationHandler::Type::TRANSIENT, notification.id()); // The Close callback should be fired asynchronously, so there is no close // yet. EXPECT_EQ(0, delegate->close_count()); - display_service->Display(NotificationHandler::Type::TRANSIENT, notification); + display_service->Display(NotificationHandler::Type::TRANSIENT, notification, + /*metadata=*/nullptr); display_service->Close(NotificationHandler::Type::TRANSIENT, notification.id()); ChromeAshMessageCenterClient::FlushForTesting();
diff --git a/chrome/browser/notifications/notification_display_service.h b/chrome/browser/notifications/notification_display_service.h index 9c3b0a6..a9ee846 100644 --- a/chrome/browser/notifications/notification_display_service.h +++ b/chrome/browser/notifications/notification_display_service.h
@@ -48,7 +48,7 @@ virtual void Display( NotificationHandler::Type notification_type, const message_center::Notification& notification, - std::unique_ptr<NotificationCommon::Metadata> metadata = nullptr) = 0; + std::unique_ptr<NotificationCommon::Metadata> metadata) = 0; // Closes the notification having |notification_id| of |notification_type|. virtual void Close(NotificationHandler::Type notification_type,
diff --git a/chrome/browser/notifications/notification_display_service_impl.h b/chrome/browser/notifications/notification_display_service_impl.h index 4504b67..d8d5b7e6 100644 --- a/chrome/browser/notifications/notification_display_service_impl.h +++ b/chrome/browser/notifications/notification_display_service_impl.h
@@ -66,8 +66,7 @@ void Shutdown() override; void Display(NotificationHandler::Type notification_type, const message_center::Notification& notification, - std::unique_ptr<NotificationCommon::Metadata> metadata = - nullptr) override; + std::unique_ptr<NotificationCommon::Metadata> metadata) override; void Close(NotificationHandler::Type notification_type, const std::string& notification_id) override; void GetDisplayed(DisplayedNotificationsCallback callback) override;
diff --git a/chrome/browser/notifications/notification_platform_bridge_chromeos_browsertest.cc b/chrome/browser/notifications/notification_platform_bridge_chromeos_browsertest.cc index bc47d75..0aaf1d2 100644 --- a/chrome/browser/notifications/notification_platform_bridge_chromeos_browsertest.cc +++ b/chrome/browser/notifications/notification_platform_bridge_chromeos_browsertest.cc
@@ -48,6 +48,7 @@ weak_ptr_factory_.GetWeakPtr())); NotificationDisplayService::GetForProfile(browser()->profile()) - ->Display(NotificationHandler::Type::TRANSIENT, notification); + ->Display(NotificationHandler::Type::TRANSIENT, notification, + /*metadata=*/nullptr); expected_close_count_ = 1; }
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 06949640..3468a6a3 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -155,7 +155,8 @@ notification_data, notification_resources); NotificationDisplayServiceFactory::GetForProfile(profile)->Display( - NotificationHandler::Type::WEB_NON_PERSISTENT, notification); + NotificationHandler::Type::WEB_NON_PERSISTENT, notification, + /*metadata=*/nullptr); } void PlatformNotificationServiceImpl::DisplayPersistentNotification(
diff --git a/chrome/browser/notifications/system_notification_helper.cc b/chrome/browser/notifications/system_notification_helper.cc index 38cb177..96e8e56 100644 --- a/chrome/browser/notifications/system_notification_helper.cc +++ b/chrome/browser/notifications/system_notification_helper.cc
@@ -33,7 +33,7 @@ void SystemNotificationHelper::Display( const message_center::Notification& notification) { GetSystemService()->Display(NotificationHandler::Type::TRANSIENT, - notification); + notification, /*metadata=*/nullptr); } void SystemNotificationHelper::Close(const std::string& notification_id) {
diff --git a/chrome/browser/offline_pages/offline_page_utils.cc b/chrome/browser/offline_pages/offline_page_utils.cc index e4d0eb5d..8f229a7 100644 --- a/chrome/browser/offline_pages/offline_page_utils.cc +++ b/chrome/browser/offline_pages/offline_page_utils.cc
@@ -328,7 +328,8 @@ const GURL& url, DownloadUIActionFlags ui_action, const std::string& request_origin) { - DCHECK(web_contents); + if (!web_contents) + return; // Ensure that the storage permission is granted since the archive file is // going to be placed in the public directory.
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc index f7d9906c..ab2afa0 100644 --- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" @@ -51,15 +50,6 @@ class DataSaverSiteBreakdownMetricsObserverBrowserTest : public InProcessBrowserTest { protected: - void EnableDataSaver() { - PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDataSaverEnabled, true); - prefs->SetBoolean(data_reduction_proxy::prefs::kDataUsageReportingEnabled, - true); - // Give the setting notification a chance to propagate. - base::RunLoop().RunUntilIdle(); - } - void SetUp() override { scoped_feature_list_.InitAndEnableFeature( data_reduction_proxy::features:: @@ -67,6 +57,14 @@ InProcessBrowserTest::SetUp(); } + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + PrefService* prefs = browser()->profile()->GetPrefs(); + prefs->SetBoolean(data_reduction_proxy::prefs::kDataUsageReportingEnabled, + true); + } + void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch( data_reduction_proxy::switches::kEnableDataReductionProxy); @@ -105,7 +103,6 @@ }; ASSERT_TRUE(embedded_test_server()->Start()); - EnableDataSaver(); for (const auto& test : tests) { GURL test_url(embedded_test_server()->GetURL(test.url)); uint64_t data_usage_before_navigation = @@ -135,8 +132,6 @@ base::BindRepeating(&HandleResourceRequestWithPlaintextMimeType)); ASSERT_TRUE(plaintext_server->Start()); - EnableDataSaver(); - GURL test_url(plaintext_server->GetURL("/page")); uint64_t data_usage_before_navigation =
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 1ce29dc..6b8c6df00 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -106,12 +106,13 @@ #include "extensions/common/constants.h" #endif -using password_manager::metrics_util::PasswordType; +using autofill::PasswordForm; using password_manager::BadMessageReason; using password_manager::ContentPasswordManagerDriverFactory; using password_manager::PasswordManagerClientHelper; using password_manager::PasswordManagerInternalsService; using password_manager::PasswordManagerMetricsRecorder; +using password_manager::metrics_util::PasswordType; using sessions::SerializedNavigationEntry; // Shorten the name to spare line breaks. The code provides enough context @@ -414,9 +415,9 @@ } void ChromePasswordManagerClient::PasswordWasAutofilled( - const std::map<base::string16, const autofill::PasswordForm*>& best_matches, + const std::map<base::string16, const PasswordForm*>& best_matches, const GURL& origin, - const std::vector<const autofill::PasswordForm*>* federated_matches) const { + const std::vector<const PasswordForm*>* federated_matches) const { #if defined(OS_ANDROID) // Either #passwords-keyboards-accessory or #experimental-ui must be enabled. if (!PasswordAccessoryController::AllowedForWebContents(web_contents())) { @@ -433,6 +434,12 @@ #endif } +void ChromePasswordManagerClient::AutofillHttpAuth( + const std::map<base::string16, const PasswordForm*>& best_matches, + const PasswordForm& preferred_match) const { + password_manager_.AutofillHttpAuth(best_matches, preferred_match); +} + void ChromePasswordManagerClient::CheckSafeBrowsingReputation( const GURL& form_action, const GURL& frame_url) {
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index 1c806447..ce8575a 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_PASSWORD_MANAGER_CHROME_PASSWORD_MANAGER_CLIENT_H_ #define CHROME_BROWSER_PASSWORD_MANAGER_CHROME_PASSWORD_MANAGER_CLIENT_H_ +#include <map> #include <memory> #include <vector> @@ -93,6 +94,11 @@ const GURL& origin, const std::vector<const autofill::PasswordForm*>* federated_matches) const override; + void AutofillHttpAuth( + const std::map<base::string16, const autofill::PasswordForm*>& + best_matches, + const autofill::PasswordForm& preferred_match) const override; + PrefService* GetPrefs() const override; password_manager::PasswordStore* GetPasswordStore() const override; password_manager::SyncState GetPasswordSyncState() const override;
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index a75ef18..480d404 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -83,7 +83,8 @@ void SetNewParsingForSaving(base::test::ScopedFeatureList* scoped_feature_list, bool enabled) { std::vector<Feature> features = {features::kNewPasswordFormParsing, - features::kNewPasswordFormParsingForSaving}; + features::kNewPasswordFormParsingForSaving, + features::kOnlyNewParser}; std::vector<Feature> enabled_features; std::vector<Feature> disabled_features; @@ -3649,14 +3650,10 @@ // page. IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, CorrectEntryForHttpAuth) { for (bool new_parser_enabled : {false, true}) { + SCOPED_TRACE(testing::Message("new_parser_enabled=") << new_parser_enabled); base::test::ScopedFeatureList scoped_feature_list; - if (new_parser_enabled) { - scoped_feature_list.InitAndEnableFeature( - features::kNewPasswordFormParsing); - } else { - scoped_feature_list.InitAndDisableFeature( - features::kNewPasswordFormParsing); - } + SetNewParsingForSaving(&scoped_feature_list, new_parser_enabled); + // The embedded_test_server() is already started at this point and adding // the request handler to it would not be thread safe. Therefore, use a new // server.
diff --git a/chrome/browser/platform_util_chromeos.cc b/chrome/browser/platform_util_chromeos.cc index 73b22b2b..ddf18cb 100644 --- a/chrome/browser/platform_util_chromeos.cc +++ b/chrome/browser/platform_util_chromeos.cc
@@ -4,7 +4,8 @@ #include "chrome/browser/platform_util.h" -#include "ash/public/cpp/window_pin_type.h" +#include "ash/public/cpp/window_properties.h" +#include "ash/public/interfaces/window_pin_type.mojom.h" #include "base/bind.h" #include "base/files/file_path.h" #include "chrome/browser/chromeos/file_manager/open_util.h" @@ -124,16 +125,14 @@ } bool IsBrowserLockedFullscreen(const Browser* browser) { - // TODO(isandrk): Roll the IsUsingWindowService logic into - // ash::IsWindowTrustedPinned, get rid of the IsWindowTrustedPinned override, - // and refactor callsites of the IsWindowTrustedPinned override to use this - // function instead. aura::Window* window = browser->window()->GetNativeWindow(); // |window| can be nullptr inside of unit tests. if (!window) return false; - return ash::IsWindowTrustedPinned( - features::IsUsingWindowService() ? window->GetRootWindow() : window); + if (features::IsUsingWindowService()) + window = window->GetRootWindow(); + return window->GetProperty(ash::kWindowPinTypeKey) == + ash::mojom::WindowPinType::TRUSTED_PINNED; } } // namespace platform_util
diff --git a/chrome/browser/policy/chrome_extension_policy_migrator.cc b/chrome/browser/policy/chrome_extension_policy_migrator.cc index 4f36933..4ad3217 100644 --- a/chrome/browser/policy/chrome_extension_policy_migrator.cc +++ b/chrome/browser/policy/chrome_extension_policy_migrator.cc
@@ -3,7 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/policy/chrome_extension_policy_migrator.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/strings/grit/components_strings.h" #include "extensions/common/hashed_extension_id.h" +#include "ui/base/l10n/l10n_util.h" namespace policy { @@ -43,10 +47,14 @@ if (!chrome_map.Get(migration.new_name)) { auto new_entry = entry->DeepCopy(); migration.transform.Run(new_entry.value.get()); + new_entry.AddError( + l10n_util::GetStringFUTF8(IDS_POLICY_MIGRATED_NEW_POLICY, + base::UTF8ToUTF16(migration.old_name))); chrome_map.Set(migration.new_name, std::move(new_entry)); } - // TODO(crbug/869958): Mark the old policy as deprecated for - // chrome://policy. + entry->AddError( + l10n_util::GetStringFUTF8(IDS_POLICY_MIGRATED_OLD_POLICY, + base::UTF8ToUTF16(migration.new_name))); } } }
diff --git a/chrome/browser/policy/chrome_extension_policy_migrator_unittest.cc b/chrome/browser/policy/chrome_extension_policy_migrator_unittest.cc index 1e4bfde6..f475203f 100644 --- a/chrome/browser/policy/chrome_extension_policy_migrator_unittest.cc +++ b/chrome/browser/policy/chrome_extension_policy_migrator_unittest.cc
@@ -6,10 +6,12 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "extensions/common/hashed_extension_id.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" namespace policy { @@ -102,4 +104,26 @@ EXPECT_EQ(base::Value(kNewValue4), *chrome_map.GetValue(kNewPolicy4)); } +TEST(ChromeExtensionPolicyMigratorTest, DeprecatedWarnings) { + PolicyBundle bundle; + + PolicyMap& chrome_map = bundle.Get( + PolicyNamespace(POLICY_DOMAIN_CHROME, /* component_id */ std::string())); + + PolicyMap& extension_map = + bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtensionId)); + SetPolicy(&extension_map, kOldPolicy1, + std::make_unique<base::Value>(kOldValue1)); + + TestingPolicyMigrator().Migrate(&bundle); + + // Policies in kMigrations should be renamed + copied into the Chrome domain. + EXPECT_EQ(1u, chrome_map.size()); + ASSERT_TRUE(chrome_map.GetValue(kNewPolicy1)); + base::RepeatingCallback<base::string16(int)> l10nlookup = + base::BindRepeating(&l10n_util::GetStringUTF16); + EXPECT_FALSE( + chrome_map.Get(kNewPolicy1)->GetLocalizedErrors(l10nlookup).empty()); +} + } // namespace policy
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc index 517b8ee..8df721e7 100644 --- a/chrome/browser/predictors/preconnect_manager.cc +++ b/chrome/browser/predictors/preconnect_manager.cc
@@ -174,8 +174,10 @@ if (!network_context) { // Cannot invoke the callback right away because it would cause the // use-after-free after returning from this function. - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(callback), false)); + base::PostTaskWithTraits( + FROM_HERE, + {content::BrowserThread::UI, content::BrowserTaskType::kPreconnect}, + base::BindOnce(std::move(callback), false)); return nullptr; }
diff --git a/chrome/browser/predictors/proxy_lookup_client_impl.cc b/chrome/browser/predictors/proxy_lookup_client_impl.cc index 6da4903..d7dc77e 100644 --- a/chrome/browser/predictors/proxy_lookup_client_impl.cc +++ b/chrome/browser/predictors/proxy_lookup_client_impl.cc
@@ -7,6 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "net/proxy_resolution/proxy_info.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -19,8 +22,12 @@ ProxyLookupCallback callback, network::mojom::NetworkContext* network_context) : binding_(this), callback_(std::move(callback)) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); network::mojom::ProxyLookupClientPtr proxy_lookup_client_ptr; - binding_.Bind(mojo::MakeRequest(&proxy_lookup_client_ptr)); + binding_.Bind( + mojo::MakeRequest(&proxy_lookup_client_ptr), + base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI, content::BrowserTaskType::kPreconnect})); network_context->LookUpProxyForURL(url, std::move(proxy_lookup_client_ptr)); binding_.set_connection_error_handler( base::BindOnce(&ProxyLookupClientImpl::OnProxyLookupComplete,
diff --git a/chrome/browser/predictors/resolve_host_client_impl.cc b/chrome/browser/predictors/resolve_host_client_impl.cc index 381e51c9..cfcbc25f 100644 --- a/chrome/browser/predictors/resolve_host_client_impl.cc +++ b/chrome/browser/predictors/resolve_host_client_impl.cc
@@ -7,6 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" @@ -21,8 +24,12 @@ ResolveHostCallback callback, network::mojom::NetworkContext* network_context) : binding_(this), callback_(std::move(callback)) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); network::mojom::ResolveHostClientPtr resolve_host_client_ptr; - binding_.Bind(mojo::MakeRequest(&resolve_host_client_ptr)); + binding_.Bind( + mojo::MakeRequest(&resolve_host_client_ptr), + base::CreateSingleThreadTaskRunnerWithTraits( + {content::BrowserThread::UI, content::BrowserTaskType::kPreconnect})); network::mojom::ResolveHostParametersPtr parameters = network::mojom::ResolveHostParameters::New(); parameters->initial_priority = net::RequestPriority::IDLE;
diff --git a/chrome/browser/previews/previews_oneplatform_hints_browsertest.cc b/chrome/browser/previews/hints_fetcher_browsertest.cc similarity index 73% rename from chrome/browser/previews/previews_oneplatform_hints_browsertest.cc rename to chrome/browser/previews/hints_fetcher_browsertest.cc index 000c27d..93984e3 100644 --- a/chrome/browser/previews/previews_oneplatform_hints_browsertest.cc +++ b/chrome/browser/previews/hints_fetcher_browsertest.cc
@@ -76,18 +76,23 @@ } // namespace // This test class sets up everything but does not enable any features. -class PreviewsOnePlatformNoFeaturesBrowserTest : public InProcessBrowserTest { +class OptimizationGuideServiceNoHintsFetcherBrowserTest + : public InProcessBrowserTest { public: - PreviewsOnePlatformNoFeaturesBrowserTest() = default; - ~PreviewsOnePlatformNoFeaturesBrowserTest() override = default; + OptimizationGuideServiceNoHintsFetcherBrowserTest() = default; + ~OptimizationGuideServiceNoHintsFetcherBrowserTest() override = default; - void SetUpOnMainThread() override { + void SetUp() override { https_server_.reset( new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); https_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews"); + https_server_->RegisterRequestMonitor( + base::BindRepeating(&OptimizationGuideServiceNoHintsFetcherBrowserTest:: + MonitorResourceRequest, + base::Unretained(this))); ASSERT_TRUE(https_server_->Start()); - InProcessBrowserTest::SetUpOnMainThread(); + InProcessBrowserTest::SetUp(); } void SetUpCommandLine(base::CommandLine* cmd) override { @@ -97,6 +102,11 @@ // at the time of first navigation. That may prevent Preview from // triggering, and causing the test to flake. cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist); + + // Set up OptimizationGuideServiceURL, this does not enable HintsFetching, + // only provides the URL. + cmd->AppendSwitchASCII(previews::switches::kOptimizationGuideServiceURL, + https_server_->base_url().spec()); } const GURL& https_url() const { return https_url_; } @@ -106,52 +116,60 @@ protected: base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<net::EmbeddedTestServer> https_server_; private: + // Called by |https_server_|. + void MonitorResourceRequest(const net::test_server::HttpRequest& request) { + // The request by HintsFetcher request should happen and be a POST request. + EXPECT_EQ(request.method, net::test_server::METHOD_POST); + // TODO(mcrouse): Test server returns 404 for now as HintsFetcher does not + // currently handle responses. + } + void TearDownOnMainThread() override { EXPECT_TRUE(https_server_->ShutdownAndWaitUntilComplete()); InProcessBrowserTest::TearDownOnMainThread(); } - std::unique_ptr<net::EmbeddedTestServer> https_server_; GURL https_url_; base::HistogramTester histogram_tester_; - DISALLOW_COPY_AND_ASSIGN(PreviewsOnePlatformNoFeaturesBrowserTest); + DISALLOW_COPY_AND_ASSIGN(OptimizationGuideServiceNoHintsFetcherBrowserTest); }; // This test class enables OnePlatform Hints. -class PreviewsOnePlatformHintsBrowserTest - : public PreviewsOnePlatformNoFeaturesBrowserTest { +class OptimizationGuideServiceHintsFetcherBrowserTest + : public OptimizationGuideServiceNoHintsFetcherBrowserTest { public: - PreviewsOnePlatformHintsBrowserTest() = default; + OptimizationGuideServiceHintsFetcherBrowserTest() = default; - ~PreviewsOnePlatformHintsBrowserTest() override = default; + ~OptimizationGuideServiceHintsFetcherBrowserTest() override = default; void SetUp() override { - // Enabled OnePlatformHints with |kPreviewsOnePlatformHints|. + // Enable OptimizationHintsFetching with |kOptimizationHintsFetching|. scoped_feature_list_.InitWithFeatures( {previews::features::kPreviews, previews::features::kOptimizationHints, - previews::features::kPreviewsOnePlatformHints}, + previews::features::kOptimizationHintsFetching}, {}); + // Call to inherited class to match same set up with feature flags added. - PreviewsOnePlatformNoFeaturesBrowserTest::SetUp(); + OptimizationGuideServiceNoHintsFetcherBrowserTest::SetUp(); } private: - DISALLOW_COPY_AND_ASSIGN(PreviewsOnePlatformHintsBrowserTest); + DISALLOW_COPY_AND_ASSIGN(OptimizationGuideServiceHintsFetcherBrowserTest); }; - // This test creates new browser with no profile and loads a random page with // the feature flags enables the PreviewsOnePlatformHints. We confirm that the // top_host_provider_impl executes and does not crash by checking UMA // histograms for the total number of TopEngagementSites and // the total number of sites returned controlled by the experiments flag // |max_oneplatform_update_hosts|. -IN_PROC_BROWSER_TEST_F(PreviewsOnePlatformHintsBrowserTest, - OnePlatformHintsEnabled) { +IN_PROC_BROWSER_TEST_F(OptimizationGuideServiceHintsFetcherBrowserTest, + OptimizationGuideServiceHintsFetcher) { const base::HistogramTester* histogram_tester = GetHistogramTester(); // Expect that the browser initialization will record at least one sample @@ -162,8 +180,8 @@ 1); } -IN_PROC_BROWSER_TEST_F(PreviewsOnePlatformNoFeaturesBrowserTest, - OnePlatformNoFeatures) { +IN_PROC_BROWSER_TEST_F(OptimizationGuideServiceNoHintsFetcherBrowserTest, + OptimizationGuideServiceNoHintsFetcher) { const base::HistogramTester* histogram_tester = GetHistogramTester(); // Expect that the histogram for HintsFetcher to be 0 because the OnePlatform
diff --git a/chrome/browser/previews/previews_service.cc b/chrome/browser/previews/previews_service.cc index d917986..ef10bf2 100644 --- a/chrome/browser/previews/previews_service.cc +++ b/chrome/browser/previews/previews_service.cc
@@ -11,6 +11,7 @@ #include "base/time/default_clock.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/previews/previews_lite_page_decider.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" #include "components/blacklist/opt_out_blacklist/opt_out_store.h" #include "components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.h" @@ -23,6 +24,7 @@ #include "components/previews/core/previews_experiments.h" #include "components/previews/core/previews_logger.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/storage_partition.h" namespace { @@ -106,7 +108,11 @@ std::make_unique<previews::PreviewsTopHostProviderImpl>( browser_context)), previews_lite_page_decider_( - std::make_unique<PreviewsLitePageDecider>(browser_context)) { + std::make_unique<PreviewsLitePageDecider>(browser_context)), + previews_url_loader_factory_( + content::BrowserContext::GetDefaultStoragePartition( + Profile::FromBrowserContext(browser_context)) + ->GetURLLoaderFactoryForBrowserProcess()) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } @@ -137,7 +143,7 @@ optimization_guide_service ? std::make_unique<previews::PreviewsOptimizationGuide>( optimization_guide_service, ui_task_runner, profile_path, - previews_top_host_provider_.get()) + previews_top_host_provider_.get(), previews_url_loader_factory_) : nullptr, base::Bind(&IsPreviewsTypeEnabled), std::make_unique<previews::PreviewsLogger>(), GetAllowedPreviews(),
diff --git a/chrome/browser/previews/previews_service.h b/chrome/browser/previews/previews_service.h index 376d093..11e25fa 100644 --- a/chrome/browser/previews/previews_service.h +++ b/chrome/browser/previews/previews_service.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/single_thread_task_runner.h" #include "chrome/browser/previews/previews_lite_page_decider.h" #include "chrome/browser/previews/previews_top_host_provider_impl.h" @@ -25,6 +26,10 @@ class BrowserContext; } +namespace network { +class SharedURLLoaderFactory; +} // namespace network + namespace optimization_guide { class OptimizationGuideService; } @@ -88,6 +93,9 @@ // The server lite page preview decider. std::unique_ptr<PreviewsLitePageDecider> previews_lite_page_decider_; + // URL Factory for the Previews Optimization Guide's Hints Fetcher. + scoped_refptr<network::SharedURLLoaderFactory> previews_url_loader_factory_; + DISALLOW_COPY_AND_ASSIGN(PreviewsService); };
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.cc b/chrome/browser/printing/cloud_print/privet_notifications.cc index 39b3868..8087b4f7e 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.cc +++ b/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -295,7 +295,8 @@ NotificationDisplayService::GetForProfile( Profile::FromBrowserContext(profile_)) - ->Display(NotificationHandler::Type::TRANSIENT, notification); + ->Display(NotificationHandler::Type::TRANSIENT, notification, + /*metadata=*/nullptr); } void PrivetNotificationService::PrivetRemoveNotification() {
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 343eadc6..55c6f511 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -152,6 +152,8 @@ #include "chrome/browser/chromeos/android_sms/android_sms_service_factory.h" #include "chrome/browser/chromeos/arc/arc_service_launcher.h" #include "chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h" +#include "chrome/browser/chromeos/cryptauth/client_app_metadata_provider_service.h" +#include "chrome/browser/chromeos/cryptauth/client_app_metadata_provider_service_factory.h" #include "chrome/browser/chromeos/cryptauth/gcm_device_info_provider_impl.h" #include "chrome/browser/chromeos/device_sync/device_sync_client_factory.h" #include "chrome/browser/chromeos/locale_change_guard.h" @@ -1271,6 +1273,7 @@ IdentityManagerFactory::GetForProfile(this), gcm::GCMProfileServiceFactory::GetForProfile(this)->driver(), chromeos::GcmDeviceInfoProviderImpl::GetInstance(), + chromeos::ClientAppMetadataProviderServiceFactory::GetForProfile(this), GetURLLoaderFactory(), std::move(request)); } @@ -1485,10 +1488,8 @@ ProfileAttributesEntry* entry; bool has_entry = profile_manager->GetProfileAttributesStorage() .GetProfileAttributesWithPath(GetPath(), &entry); - if (has_entry) { + if (has_entry) entry->SetSupervisedUserId(GetPrefs()->GetString(prefs::kSupervisedUserId)); - ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager); - } } void ProfileImpl::UpdateNameInStorage() {
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 07f7eb6..4a86203 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -591,8 +591,6 @@ profile_path, name, std::string(), base::string16(), icon_index, /*supervised_user_id=*/std::string(), EmptyAccountId()); } - - ProfileMetrics::UpdateReportedProfilesStatistics(this); } // Call or enqueue the callback. @@ -1089,7 +1087,7 @@ // Enterprise users should not be included in any NUX/Navi flow. if (!base::IsMachineExternallyManaged()) { profile->GetPrefs()->SetString(prefs::kNaviOnboardGroup, - nux::GetOnboardingGroup()); + nux::GetOnboardingGroup(profile)); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) } @@ -1617,7 +1615,6 @@ } storage.RemoveProfile(profile_dir); - ProfileMetrics::UpdateReportedProfilesStatistics(this); } void ProfileManager::FinishDeletingProfile(
diff --git a/chrome/browser/profiles/profile_metrics.cc b/chrome/browser/profiles/profile_metrics.cc index be4b91c0..7b7b9b3b 100644 --- a/chrome/browser/profiles/profile_metrics.cc +++ b/chrome/browser/profiles/profile_metrics.cc
@@ -26,10 +26,6 @@ namespace { -#if defined(OS_WIN) || defined(OS_MACOSX) -const int kMaximumReportedProfileCount = 5; -#endif - const int kMaximumDaysOfDisuse = 4 * 7; // Should be integral number of weeks. #if !defined(OS_ANDROID) @@ -180,23 +176,6 @@ return true; } -void ProfileMetrics::UpdateReportedProfilesStatistics(ProfileManager* manager) { -#if defined(OS_WIN) || defined(OS_MACOSX) - profile_metrics::Counts counts; - if (CountProfileInformation(manager, &counts)) { - size_t limited_total = counts.total; - size_t limited_signedin = counts.signedin; - if (limited_total > kMaximumReportedProfileCount) { - limited_total = kMaximumReportedProfileCount + 1; - limited_signedin = - (int)((float)(counts.signedin * limited_total) - / counts.total + 0.5); - } - UpdateReportedOSProfileStatistics(limited_total, limited_signedin); - } -#endif -} - #if !defined(OS_ANDROID) void ProfileMetrics::LogNumberOfProfileSwitches() { UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfSwitches", @@ -204,14 +183,6 @@ } #endif -// The OS_MACOSX implementation of this function is in profile_metrics_mac.mm. -#if defined(OS_WIN) -void ProfileMetrics::UpdateReportedOSProfileStatistics( - size_t active, size_t signedin) { - GoogleUpdateSettings::UpdateProfileCounts(active, signedin); -} -#endif - void ProfileMetrics::LogNumberOfProfiles(ProfileManager* manager) { profile_metrics::Counts counts; bool success = CountProfileInformation(manager, &counts); @@ -219,13 +190,8 @@ profile_metrics::LogProfileMetricsCounts(counts); // Ignore other metrics if we have no profiles. - if (success) { + if (success) LogLockedProfileInformation(manager); - -#if defined(OS_WIN) || defined(OS_MACOSX) - UpdateReportedOSProfileStatistics(counts.total, counts.signedin); -#endif - } } void ProfileMetrics::LogProfileAddNewUser(ProfileAdd metric) {
diff --git a/chrome/browser/profiles/profile_metrics.h b/chrome/browser/profiles/profile_metrics.h index dd42718..482bd51 100644 --- a/chrome/browser/profiles/profile_metrics.h +++ b/chrome/browser/profiles/profile_metrics.h
@@ -166,7 +166,6 @@ }; #endif // defined(OS_ANDROID) - static void UpdateReportedProfilesStatistics(ProfileManager* manager); // Count and return summary information about the profiles currently in the // |manager|. This information is returned in the output variable |counts|. static bool CountProfileInformation(ProfileManager* manager, @@ -176,11 +175,6 @@ static void LogNumberOfProfileSwitches(); #endif -#if defined(OS_WIN) || defined(OS_MACOSX) - // Update OS level tracking of profile counts. - static void UpdateReportedOSProfileStatistics(size_t active, size_t signedin); -#endif - static void LogNumberOfProfiles(ProfileManager* manager); static void LogProfileAddNewUser(ProfileAdd metric); static void LogProfileAvatarSelection(size_t icon_index);
diff --git a/chrome/browser/profiles/profile_metrics_mac.mm b/chrome/browser/profiles/profile_metrics_mac.mm deleted file mode 100644 index dd931b1..0000000 --- a/chrome/browser/profiles/profile_metrics_mac.mm +++ /dev/null
@@ -1,21 +0,0 @@ -// 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. - -#include "chrome/browser/profiles/profile_metrics.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/numerics/safe_conversions.h" -#include "chrome/browser/mac/keystone_glue.h" - -void ProfileMetrics::UpdateReportedOSProfileStatistics( - size_t active, size_t signedin) { - if (base::IsValueInRangeForNumericType<uint32_t>(active) && - base::IsValueInRangeForNumericType<uint32_t>(signedin)) { - [[KeystoneGlue defaultKeystoneGlue] - updateProfileCountsWithNumProfiles:active - numSignedInProfiles:signedin]; - } -}
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 210e927..cb39e0b4 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/media/router/media_router_metrics.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -177,7 +178,6 @@ #endif #if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/intent_helper/open_with_menu.h" #include "chrome/browser/chromeos/arc/intent_helper/start_smart_selection_action_menu.h" @@ -355,7 +355,7 @@ {99, -1, IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE}, {100, -1, IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE}, {101, -1, IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS}, - {102, -1, IDC_SEND_TO_MY_DEVICES}, + {102, -1, IDC_SEND_TAB_TO_SELF}, // Add new items here and use |enum_id| from the next line. // Also, add new items to RenderViewContextMenuItem enum in // tools/metrics/histograms/enums.xml. @@ -1353,8 +1353,8 @@ AppendMediaRouterItem(); if (send_tab_to_self::ShouldOfferFeature(GetBrowser())) { - menu_model_.AddItemWithStringId(IDC_SEND_TO_MY_DEVICES, - IDS_CONTENT_CONTEXT_SEND_TO_MY_DEVICES); + menu_model_.AddItemWithStringId(IDC_SEND_TAB_TO_SELF, + IDS_CONTEXT_MENU_SEND_TAB_TO_SELF); } if (TranslateService::IsTranslatableURL(params_.page_url)) { std::unique_ptr<translate::TranslatePrefs> prefs( @@ -1633,13 +1633,11 @@ // Menu delegate functions ----------------------------------------------------- bool RenderViewContextMenu::IsCommandIdEnabled(int id) const { -#if defined(OS_CHROMEOS) // Disable context menu in locked fullscreen mode (the menu is not really // disabled as the user can still open it, but all the individual context menu // entries are disabled / greyed out). - if (GetBrowser() && ash::IsWindowTrustedPinned(GetBrowser()->window())) + if (GetBrowser() && platform_util::IsBrowserLockedFullscreen(GetBrowser())) return false; -#endif { bool enabled = false; @@ -1812,7 +1810,7 @@ case IDC_CONTENT_CONTEXT_GOTOURL: case IDC_SPELLPANEL_TOGGLE: case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: - case IDC_SEND_TO_MY_DEVICES: + case IDC_SEND_TAB_TO_SELF: return true; case IDC_CHECK_SPELLING_WHILE_TYPING: return prefs->GetBoolean(spellcheck::prefs::kSpellCheckEnable); @@ -2026,7 +2024,7 @@ embedder_web_contents_->OnSavePage(); break; - case IDC_SEND_TO_MY_DEVICES: + case IDC_SEND_TAB_TO_SELF: base::RecordAction(UserMetricsAction("ViewContextMenu_SendToMyDevices")); send_tab_to_self::CreateNewEntry(embedder_web_contents_, GetProfile()); break;
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.h b/chrome/browser/resource_coordinator/lifecycle_unit.h index b3b874c8..8ed3034 100644 --- a/chrome/browser/resource_coordinator/lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/lifecycle_unit.h
@@ -140,12 +140,6 @@ // than for individual LifecycleUnits. https://crbug.com/775644 virtual int GetEstimatedMemoryFreedOnDiscardKB() const = 0; - // Whether memory can be purged in the process hosting this LifecycleUnit. - // - // TODO(fdoray): This method should be on a class that represents a process, - // not on a LifecycleUnit. https://crbug.com/775644 - virtual bool CanPurge() const = 0; - // Returns true if this LifecycleUnit can be frozen. Full details regarding // the policy decision are recorded in |decision_details|, for logging. // Returning false but with an empty |decision_details| means the transition
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc index e7bf787..fe42caf 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -498,11 +498,6 @@ return GetPrivateMemoryKB(GetProcessHandle()); } -bool TabLifecycleUnitSource::TabLifecycleUnit::CanPurge() const { - // A renderer can be purged if it's not playing media. - return !IsMediaTabImpl(nullptr); -} - bool TabLifecycleUnitSource::TabLifecycleUnit::CanFreeze( DecisionDetails* decision_details) const { DCHECK(decision_details->reasons().empty());
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h index 887fb0f..81fe1eb 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
@@ -99,7 +99,6 @@ LifecycleUnitLoadingState GetLoadingState() const override; bool Load() override; int GetEstimatedMemoryFreedOnDiscardKB() const override; - bool CanPurge() const override; bool CanFreeze(DecisionDetails* decision_details) const override; bool CanDiscard(LifecycleUnitDiscardReason reason, DecisionDetails* decision_details) const override;
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index 023afc5a..bd1a204 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -94,9 +94,11 @@ // load the next background tab when the loading slots free up. constexpr size_t kNumOfLoadingSlots = 1; +#if defined(OS_CHROMEOS) // The default interval in seconds after which to adjust the oom_score_adj // value. constexpr int kAdjustmentIntervalSeconds = 10; +#endif struct LifecycleUnitAndSortKey { explicit LifecycleUnitAndSortKey(LifecycleUnit* lifecycle_unit) @@ -170,8 +172,6 @@ TabManager* tab_manager_; }; -constexpr base::TimeDelta TabManager::kDefaultMinTimeToPurge; - TabManager::TabManager(PageSignalReceiver* page_signal_receiver, TabLoadTracker* tab_load_tracker) : state_transitions_callback_( @@ -223,11 +223,14 @@ return; #endif +// TODO(adityakeerthi): Move this logic into TabManagerDelegate. +#if defined(OS_CHROMEOS) if (!update_timer_.IsRunning()) { update_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(kAdjustmentIntervalSeconds), this, &TabManager::UpdateTimerCallback); } +#endif // MemoryPressureMonitor is not implemented on Linux so far and tabs are never // discarded. @@ -245,31 +248,6 @@ } } #endif - // purge-and-suspend param is used for Purge+Suspend finch experiment - // in the following way: - // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7PPbk/edit?usp=sharing - std::string purge_and_suspend_time = variations::GetVariationParamValue( - "PurgeAndSuspendAggressive", "purge-and-suspend-time"); - unsigned int min_time_to_purge_sec = 0; - if (purge_and_suspend_time.empty() || - !base::StringToUint(purge_and_suspend_time, &min_time_to_purge_sec)) - min_time_to_purge_ = kDefaultMinTimeToPurge; - else - min_time_to_purge_ = base::TimeDelta::FromSeconds(min_time_to_purge_sec); - - std::string max_purge_and_suspend_time = variations::GetVariationParamValue( - "PurgeAndSuspendAggressive", "max-purge-and-suspend-time"); - unsigned int max_time_to_purge_sec = 0; - // If max-purge-and-suspend-time is not specified or - // max-purge-and-suspend-time is not valid (not number or smaller than - // min-purge-and-suspend-time), use default max-time-to-purge, i.e. - // min-time-to-purge times kDefaultMinMaxTimeToPurgeRatio. - if (max_purge_and_suspend_time.empty() || - !base::StringToUint(max_purge_and_suspend_time, &max_time_to_purge_sec) || - max_time_to_purge_sec < min_time_to_purge_.InSeconds()) - max_time_to_purge_ = min_time_to_purge_ * kDefaultMinMaxTimeToPurgeRatio; - else - max_time_to_purge_ = base::TimeDelta::FromSeconds(max_time_to_purge_sec); } LifecycleUnitVector TabManager::GetSortedLifecycleUnits() { @@ -348,26 +326,6 @@ TabLifecycleUnitExternal::RemoveTabLifecycleObserver(observer); } -bool TabManager::CanPurgeBackgroundedRenderer(int render_process_id) const { - for (LifecycleUnit* lifecycle_unit : lifecycle_units_) { - TabLifecycleUnitExternal* tab_lifecycle_unit_external = - lifecycle_unit->AsTabLifecycleUnitExternal(); - // For now, all LifecycleUnits are TabLifecycleUnitExternals. - DCHECK(tab_lifecycle_unit_external); - content::WebContents* content = - tab_lifecycle_unit_external->GetWebContents(); - DCHECK(content); - - if (content->IsCrashed()) - continue; - if (content->GetMainFrame()->GetProcess()->GetID() != render_process_id) - continue; - if (!lifecycle_unit->CanPurge()) - return false; - } - return true; -} - size_t TabManager::GetBackgroundTabLoadingCount() const { if (!IsInBackgroundTabOpeningSession()) return 0; @@ -421,8 +379,7 @@ // This function is called when |update_timer_| fires. It will adjust the clock // if needed (if it detects that the machine was asleep) and will fire the stats -// updating on ChromeOS via the delegate. This function also tries to purge -// cache memory. +// updating on ChromeOS via the delegate. void TabManager::UpdateTimerCallback() { // If Chrome is shutting down, do not do anything. if (g_browser_process->IsShuttingDown()) @@ -435,61 +392,6 @@ // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. delegate_->AdjustOomPriorities(); #endif - - PurgeBackgroundedTabsIfNeeded(); -} - -base::TimeDelta TabManager::GetTimeToPurge( - base::TimeDelta min_time_to_purge, - base::TimeDelta max_time_to_purge) const { - return base::TimeDelta::FromSeconds(base::RandInt( - min_time_to_purge.InSeconds(), max_time_to_purge.InSeconds())); -} - -bool TabManager::ShouldPurgeNow(content::WebContents* content) const { - if (GetWebContentsData(content)->is_purged()) - return false; - if (TabLifecycleUnitExternal::FromWebContents(content)->IsDiscarded()) - return false; - - base::TimeDelta time_passed = - NowTicks() - GetWebContentsData(content)->LastInactiveTime(); - return time_passed > GetWebContentsData(content)->time_to_purge(); -} - -void TabManager::PurgeBackgroundedTabsIfNeeded() { - for (LifecycleUnit* lifecycle_unit : lifecycle_units_) { - TabLifecycleUnitExternal* tab_lifecycle_unit_external = - lifecycle_unit->AsTabLifecycleUnitExternal(); - // For now, all LifecycleUnits are TabLifecycleUnitExternals. - DCHECK(tab_lifecycle_unit_external); - content::WebContents* content = - tab_lifecycle_unit_external->GetWebContents(); - DCHECK(content); - - if (content->IsCrashed()) - continue; - - content::RenderProcessHost* render_process_host = - content->GetMainFrame()->GetProcess(); - int render_process_id = render_process_host->GetID(); - - if (!render_process_host->IsProcessBackgrounded()) - continue; - if (!CanPurgeBackgroundedRenderer(render_process_id)) - continue; - - bool purge_now = ShouldPurgeNow(content); - if (!purge_now) - continue; - - // Since |content|'s tab is kept inactive and background for more than - // time-to-purge time, its purged state changes: false => true. - GetWebContentsData(content)->set_is_purged(true); - // TODO(tasak): rename PurgeAndSuspend with a better name, e.g. - // RequestPurgeCache, because we don't suspend any renderers. - render_process_host->PurgeAndSuspend(); - } } void TabManager::PauseBackgroundTabOpeningIfNeeded() { @@ -561,19 +463,9 @@ void TabManager::OnActiveTabChanged(content::WebContents* old_contents, content::WebContents* new_contents) { - // An active tab is not purged. - // Calling GetWebContentsData() early ensures that the WebContentsData is - // created for |new_contents|, which |stats_collector_| expects. - GetWebContentsData(new_contents)->set_is_purged(false); - // If |old_contents| is set, that tab has switched from being active to // inactive, so record the time of that transition. if (old_contents) { - GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); - // Re-setting time-to-purge every time a tab becomes inactive. - GetWebContentsData(old_contents) - ->set_time_to_purge( - GetTimeToPurge(min_time_to_purge_, max_time_to_purge_)); // Only record switch-to-tab metrics when a switch happens, i.e. // |old_contents| is set. stats_collector_->RecordSwitchToTab(old_contents, new_contents); @@ -582,31 +474,11 @@ ResumeTabNavigationIfNeeded(new_contents); } -void TabManager::OnTabInserted(content::WebContents* contents, - bool foreground) { - // Only interested in background tabs, as foreground tabs get taken care of by - // OnActiveTabChanged. - if (foreground) - return; - - // A new background tab is similar to having a tab switch from being active to - // inactive. - GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); - // Re-setting time-to-purge every time a tab becomes inactive. - GetWebContentsData(contents)->set_time_to_purge( - GetTimeToPurge(min_time_to_purge_, max_time_to_purge_)); -} - void TabManager::OnTabStripModelChanged( TabStripModel* tab_strip_model, const TabStripModelChange& change, const TabStripSelectionChange& selection) { - if (change.type() == TabStripModelChange::kInserted) { - for (const auto& delta : change.deltas()) { - OnTabInserted(delta.insert.contents, - delta.insert.contents == selection.new_contents); - } - } else if (change.type() == TabStripModelChange::kReplaced) { + if (change.type() == TabStripModelChange::kReplaced) { for (const auto& delta : change.deltas()) { WebContentsData::CopyState(delta.replace.old_contents, delta.replace.new_contents);
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index 59a2d02..2628c31c 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -134,10 +134,6 @@ void AddObserver(TabLifecycleObserver* observer); void RemoveObserver(TabLifecycleObserver* observer); - // Returns true when a given renderer can be purged if the specified - // renderer is eligible for purging. - bool CanPurgeBackgroundedRenderer(int render_process_id) const; - // Indicates how TabManager should load pending background tabs. The mode is // recorded in tracing for easier debugging. The existing explicit numbering // should be kept as is when new modes are added. @@ -197,14 +193,12 @@ friend class TabManagerStatsCollectorTest; friend class TabManagerWithProactiveDiscardExperimentEnabledTest; - FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingMode); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabLoadingSlots); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, BackgroundTabsLoadingOrdering); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); - FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, EnablePageAlmostIdleSignal); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, FreezeTab); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL); @@ -232,12 +226,10 @@ FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabsFromUrgentDiscarding); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs); - FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, SessionRestoreAfterBackgroundTabOpeningSession); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, SessionRestoreBeforeBackgroundTabOpeningSession); - FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerWasDiscarded); FRIEND_TEST_ALL_PREFIXES(TabManagerTest, @@ -263,16 +255,6 @@ FRIEND_TEST_ALL_PREFIXES(TabManagerWithProactiveDiscardExperimentEnabledTest, NoUnfreezeWhenUnfreezingVariationParamDisabled); - // The time of the first purging after a renderer is backgrounded. - // The initial value was chosen because most of users activate backgrounded - // tabs within 30 minutes. (c.f. Tabs.StateTransfer.Time_Inactive_Active) - static constexpr base::TimeDelta kDefaultMinTimeToPurge = - base::TimeDelta::FromMinutes(1); - - // The min/max time to purge ratio. The max time to purge is set to be - // min time to purge times this value. - const int kDefaultMinMaxTimeToPurgeRatio = 4; - // Returns true if the |url| represents an internal Chrome web UI page that // can be easily reloaded and hence makes a good choice to discard. static bool IsInternalPage(const GURL& url); @@ -281,26 +263,6 @@ // that need to be run periodically (see comment in implementation). void UpdateTimerCallback(); - // Returns a random time-to-purge whose min value is min_time_to_purge and max - // value is max_time_to_purge. - base::TimeDelta GetTimeToPurge(base::TimeDelta min_time_to_purge, - base::TimeDelta max_time_to_purge) const; - - // Returns true if the tab specified by |content| is now eligible to have - // its memory purged. - bool ShouldPurgeNow(content::WebContents* content) const; - - // Purges renderers in backgrounded tabs if the following conditions are - // satisfied: - // - the renderers are not purged yet, - // - the renderers are not playing media, - // (CanPurgeBackgroundedRenderer returns true) - // - the renderers are left inactive and background for time-to-purge. - // If renderers are purged, their internal states become 'purged'. - // The state is reset to be 'not purged' only when they are activated - // (=ActiveTabChanged is invoked). - void PurgeBackgroundedTabsIfNeeded(); - // Makes a request to the WebContents at the specified index to freeze its // page. void FreezeWebContentsAt(int index, TabStripModel* model); @@ -325,10 +287,9 @@ // beginning of tab discards. void UnregisterMemoryPressureListener(); - // Methods called by OnTabStripModelChanged() + // Called by OnTabStripModelChanged() void OnActiveTabChanged(content::WebContents* old_contents, content::WebContents* new_contents); - void OnTabInserted(content::WebContents* contents, bool foreground); // TabStripModelObserver: void OnTabStripModelChanged( @@ -493,9 +454,6 @@ // Parameters for proactive freezing and discarding. ProactiveTabFreezeAndDiscardParams proactive_freeze_discard_params_; - // Timer to periodically update the stats of the renderers. - base::RepeatingTimer update_timer_; - // Timer to update the state of LifecycleUnits. This is an std::unique_ptr to // allow initialization after mock time is setup in unit tests. std::unique_ptr<base::OneShotTimer> state_transitions_timer_; @@ -507,12 +465,10 @@ // A listener to global memory pressure events. std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - // A backgrounded renderer will be purged between min_time_to_purge_ and - // max_time_to_purge_. - base::TimeDelta min_time_to_purge_; - base::TimeDelta max_time_to_purge_; - #if defined(OS_CHROMEOS) + // Timer to periodically make OOM adjustments on ChromeOS. + base::RepeatingTimer update_timer_; + std::unique_ptr<TabManagerDelegate> delegate_; #endif
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc index d6675428..180b10b0 100644 --- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -854,39 +854,6 @@ tab_manager()->DiscardTabImpl(LifecycleUnitDiscardReason::PROACTIVE)); } -IN_PROC_BROWSER_TEST_F(TabManagerTest, CanPurgeBackgroundedRenderer) { - // Open 2 tabs, the second one being in the background. - ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL)); - ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(chrome::kChromeUIAboutURL), - WindowOpenDisposition::NEW_BACKGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - auto* tab = GetWebContentsAt(1); - // Simulate that a video stream is now being captured. - blink::MediaStreamDevices video_devices(1); - video_devices[0] = - blink::MediaStreamDevice(blink::MEDIA_DEVICE_VIDEO_CAPTURE, - "fake_media_device", "fake_media_device"); - MediaCaptureDevicesDispatcher* dispatcher = - MediaCaptureDevicesDispatcher::GetInstance(); - dispatcher->SetTestVideoCaptureDevices(video_devices); - std::unique_ptr<content::MediaStreamUI> video_stream_ui = - dispatcher->GetMediaStreamCaptureIndicator()->RegisterMediaStream( - tab, video_devices); - video_stream_ui->OnStarted(base::OnceClosure(), base::RepeatingClosure()); - - // Should not be able to suspend a tab which plays a video. - int render_process_id = tab->GetMainFrame()->GetProcess()->GetID(); - ASSERT_FALSE(tab_manager()->CanPurgeBackgroundedRenderer(render_process_id)); - - // Remove the video stream. - video_stream_ui.reset(); - - // Should be able to suspend the background tab now. - EXPECT_TRUE(tab_manager()->CanPurgeBackgroundedRenderer(render_process_id)); -} - IN_PROC_BROWSER_TEST_F(TabManagerTest, AutoDiscardable) { using content::WindowedNotificationObserver; @@ -928,102 +895,6 @@ EXPECT_TRUE(IsTabDiscarded(GetWebContentsAt(0))); } -IN_PROC_BROWSER_TEST_F(TabManagerTest, PurgeBackgroundRenderer) { - // Get three tabs open. - content::WindowedNotificationObserver load1( - content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::NotificationService::AllSources()); - OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(), - WindowOpenDisposition::CURRENT_TAB, - ui::PAGE_TRANSITION_TYPED, false); - browser()->OpenURL(open1); - load1.Wait(); - - content::WindowedNotificationObserver load2( - content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::NotificationService::AllSources()); - OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui::PAGE_TRANSITION_TYPED, false); - browser()->OpenURL(open2); - load2.Wait(); - - content::WindowedNotificationObserver load3( - content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::NotificationService::AllSources()); - OpenURLParams open3(GURL(chrome::kChromeUITermsURL), content::Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, - ui::PAGE_TRANSITION_TYPED, false); - browser()->OpenURL(open3); - load3.Wait(); - - TabManager::WebContentsData* tab1_contents_data = - tab_manager()->GetWebContentsData(GetWebContentsAt(0)); - TabManager::WebContentsData* tab2_contents_data = - tab_manager()->GetWebContentsData(GetWebContentsAt(1)); - TabManager::WebContentsData* tab3_contents_data = - tab_manager()->GetWebContentsData(GetWebContentsAt(2)); - - // The time-to-purge initialized at ActiveTabChanged should be in the - // right default range. - EXPECT_GE(tab1_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(1)); - EXPECT_LE(tab1_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(4)); - EXPECT_GE(tab2_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(1)); - EXPECT_LE(tab2_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(4)); - - EXPECT_GE(tab3_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(30)); - EXPECT_LE(tab3_contents_data->time_to_purge(), - base::TimeDelta::FromMinutes(60)); - - // To make it easy to test, configure time-to-purge here. - base::TimeDelta time_to_purge1 = base::TimeDelta::FromMinutes(30); - base::TimeDelta time_to_purge2 = base::TimeDelta::FromMinutes(40); - tab1_contents_data->set_time_to_purge(time_to_purge1); - tab2_contents_data->set_time_to_purge(time_to_purge2); - tab3_contents_data->set_time_to_purge(time_to_purge1); - - // No tabs are not purged yet. - ASSERT_FALSE(tab1_contents_data->is_purged()); - ASSERT_FALSE(tab2_contents_data->is_purged()); - ASSERT_FALSE(tab3_contents_data->is_purged()); - - // Advance the clock for time_to_purge1. - test_clock_.Advance(time_to_purge1); - tab_manager()->PurgeBackgroundedTabsIfNeeded(); - - ASSERT_FALSE(tab1_contents_data->is_purged()); - ASSERT_FALSE(tab2_contents_data->is_purged()); - ASSERT_FALSE(tab3_contents_data->is_purged()); - - // Advance the clock for 1 minutes. - test_clock_.Advance(base::TimeDelta::FromMinutes(1)); - tab_manager()->PurgeBackgroundedTabsIfNeeded(); - - // Since tab1 is kept inactive and background for more than - // time_to_purge1, tab1 should be purged. - ASSERT_TRUE(tab1_contents_data->is_purged()); - ASSERT_FALSE(tab2_contents_data->is_purged()); - ASSERT_FALSE(tab3_contents_data->is_purged()); - - // Advance the clock. - test_clock_.Advance(time_to_purge2 - time_to_purge1); - tab_manager()->PurgeBackgroundedTabsIfNeeded(); - - // Since tab2 is kept inactive and background for more than - // time_to_purge2, tab1 should be purged. - // Since tab3 is active, tab3 should not be purged. - ASSERT_TRUE(tab1_contents_data->is_purged()); - ASSERT_TRUE(tab2_contents_data->is_purged()); - ASSERT_FALSE(tab3_contents_data->is_purged()); - - tsm()->CloseAllTabs(); -} - IN_PROC_BROWSER_TEST_F(TabManagerTestWithTwoTabs, ProactiveFastShutdownSingleTabProcess) { // The Tab Manager should be able to fast-kill a process for the discarded tab
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index dd18c4b..809fbe79 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -425,90 +425,6 @@ TabManager::IsInternalPage(GURL("chrome://settings/fakeSetting"))); } -TEST_F(TabManagerTest, DefaultTimeToPurgeInCorrectRange) { - base::TimeDelta time_to_purge = - tab_manager_->GetTimeToPurge(TabManager::kDefaultMinTimeToPurge, - TabManager::kDefaultMinTimeToPurge * 4); - EXPECT_GE(time_to_purge, base::TimeDelta::FromMinutes(1)); - EXPECT_LE(time_to_purge, base::TimeDelta::FromMinutes(4)); -} - -TEST_F(TabManagerTest, ShouldPurgeAtDefaultTime) { - auto window = std::make_unique<TestBrowserWindow>(); - Browser::CreateParams params(profile(), true); - params.type = Browser::TYPE_TABBED; - params.window = window.get(); - auto browser = std::make_unique<Browser>(params); - TabStripModel* tab_strip = browser->tab_strip_model(); - - std::unique_ptr<WebContents> test_contents = CreateWebContents(); - WebContents* raw_test_contents = test_contents.get(); - tab_strip->AppendWebContents(std::move(test_contents), /*foreground=*/true); - - tab_manager_->GetWebContentsData(raw_test_contents)->set_is_purged(false); - tab_manager_->GetWebContentsData(raw_test_contents) - ->SetLastInactiveTime(NowTicks()); - tab_manager_->GetWebContentsData(raw_test_contents) - ->set_time_to_purge(base::TimeDelta::FromMinutes(1)); - - // Wait 1 minute and verify that the tab is still not to be purged. - task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(1)); - EXPECT_FALSE(tab_manager_->ShouldPurgeNow(raw_test_contents)); - - // Wait another 1 second and verify that it should be purged now . - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1)); - EXPECT_TRUE(tab_manager_->ShouldPurgeNow(raw_test_contents)); - - tab_manager_->GetWebContentsData(raw_test_contents)->set_is_purged(true); - tab_manager_->GetWebContentsData(raw_test_contents) - ->SetLastInactiveTime(NowTicks()); - - // Wait 1 day and verify that the tab is still be purged. - task_runner_->FastForwardBy(base::TimeDelta::FromHours(24)); - EXPECT_FALSE(tab_manager_->ShouldPurgeNow(raw_test_contents)); - - // Tabs with a committed URL must be closed explicitly to avoid DCHECK errors. - tab_strip->CloseAllTabs(); -} - -TEST_F(TabManagerTest, ActivateTabResetPurgeState) { - auto window = std::make_unique<TestBrowserWindow>(); - Browser::CreateParams params(profile(), true); - params.type = Browser::TYPE_TABBED; - params.window = window.get(); - auto browser = std::make_unique<Browser>(params); - TabStripModel* tabstrip = browser->tab_strip_model(); - - std::unique_ptr<WebContents> tab1 = CreateWebContents(); - std::unique_ptr<WebContents> tab2 = CreateWebContents(); - WebContents* raw_tab2 = tab2.get(); - tabstrip->AppendWebContents(std::move(tab1), true); - tabstrip->AppendWebContents(std::move(tab2), false); - - tab_manager_->GetWebContentsData(raw_tab2)->SetLastInactiveTime(NowTicks()); - static_cast<content::MockRenderProcessHost*>( - raw_tab2->GetMainFrame()->GetProcess()) - ->set_is_process_backgrounded(true); - EXPECT_TRUE(raw_tab2->GetMainFrame()->GetProcess()->IsProcessBackgrounded()); - - // Initially PurgeAndSuspend state should be NOT_PURGED. - EXPECT_FALSE(tab_manager_->GetWebContentsData(raw_tab2)->is_purged()); - tab_manager_->GetWebContentsData(raw_tab2)->set_time_to_purge( - base::TimeDelta::FromMinutes(1)); - task_runner_->FastForwardBy(base::TimeDelta::FromMinutes(2)); - tab_manager_->PurgeBackgroundedTabsIfNeeded(); - // Since tab2 is kept inactive and background for more than time-to-purge, - // tab2 should be purged. - EXPECT_TRUE(tab_manager_->GetWebContentsData(raw_tab2)->is_purged()); - - // Activate tab2. Tab2's PurgeAndSuspend state should be NOT_PURGED. - tabstrip->ActivateTabAt(1, {TabStripModel::GestureType::kOther}); - EXPECT_FALSE(tab_manager_->GetWebContentsData(raw_tab2)->is_purged()); - - // Tabs with a committed URL must be closed explicitly to avoid DCHECK errors. - tabstrip->CloseAllTabs(); -} - // Data race on Linux. http://crbug.com/787842 #if defined(OS_LINUX) #define MAYBE_DiscardTabWithNonVisibleTabs DISABLED_DiscardTabWithNonVisibleTabs
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc index 49ce7ad..9cd303c 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.cc
@@ -20,9 +20,7 @@ namespace resource_coordinator { TabManager::WebContentsData::WebContentsData(content::WebContents* web_contents) - : WebContentsObserver(web_contents), - time_to_purge_(base::TimeDelta::FromMinutes(30)), - is_purged_(false) {} + : WebContentsObserver(web_contents) {} TabManager::WebContentsData::~WebContentsData() {} @@ -55,14 +53,6 @@ g_browser_process->GetTabManager()->OnWebContentsDestroyed(web_contents()); } -TimeTicks TabManager::WebContentsData::LastInactiveTime() { - return tab_data_.last_inactive_time; -} - -void TabManager::WebContentsData::SetLastInactiveTime(TimeTicks timestamp) { - tab_data_.last_inactive_time = timestamp; -} - // static void TabManager::WebContentsData::CopyState( content::WebContents* old_contents, @@ -81,8 +71,7 @@ is_restored_in_foreground(false) {} bool TabManager::WebContentsData::Data::operator==(const Data& right) const { - return last_inactive_time == right.last_inactive_time && - tab_loading_state == right.tab_loading_state && + return tab_loading_state == right.tab_loading_state && is_in_session_restore == right.is_in_session_restore && is_restored_in_foreground == right.is_restored_in_foreground; }
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h index f5e4f7f9..4978a854 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data.h
@@ -39,30 +39,10 @@ content::NavigationHandle* navigation_handle) override; void WebContentsDestroyed() override; - // Returns the timestamp of the last time the tab changed became inactive. - base::TimeTicks LastInactiveTime(); - - // Sets the timestamp of the last time the tab became inactive. - void SetLastInactiveTime(base::TimeTicks timestamp); - // Copies the discard state from |old_contents| to |new_contents|. static void CopyState(content::WebContents* old_contents, content::WebContents* new_contents); - // Sets the current purge state. - void set_is_purged(bool state) { is_purged_ = state; } - - // Returns the current state of purge. - bool is_purged() const { return is_purged_; } - - // Sets the time to purge after the tab is backgrounded. - void set_time_to_purge(const base::TimeDelta& time_to_purge) { - time_to_purge_ = time_to_purge; - } - - // Returns the time to first purge after the tab is backgrounded. - base::TimeDelta time_to_purge() const { return time_to_purge_; } - // Sets the tab loading state. void SetTabLoadingState(LoadingState state) { tab_data_.tab_loading_state = state; @@ -96,8 +76,6 @@ bool operator==(const Data& right) const; bool operator!=(const Data& right) const; - // The last time the tab switched from being active to inactive. - base::TimeTicks last_inactive_time; // Current loading state of this tab. LoadingState tab_loading_state; // True if the tab was created by session restore. Remains true until the @@ -110,12 +88,6 @@ // Contains all the needed data for the tab. Data tab_data_; - // The time to purge after the tab is backgrounded. - base::TimeDelta time_to_purge_; - - // True if the tab has been purged. - bool is_purged_; - DISALLOW_COPY_AND_ASSIGN(WebContentsData); WEB_CONTENTS_USER_DATA_KEY_DECL(); };
diff --git a/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc index 5c6840cb8..527b600e 100644 --- a/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc
@@ -69,13 +69,6 @@ } // namespace -TEST_F(TabManagerWebContentsDataTest, LastInactiveTime) { - EXPECT_TRUE(tab_data()->LastInactiveTime().is_null()); - auto now = NowTicks(); - tab_data()->SetLastInactiveTime(now); - EXPECT_EQ(now, tab_data()->LastInactiveTime()); -} - TEST_F(TabManagerWebContentsDataTest, TabLoadingState) { EXPECT_EQ(UNLOADED, tab_data()->tab_loading_state()); tab_data()->SetTabLoadingState(LOADING); @@ -85,8 +78,6 @@ } TEST_F(TabManagerWebContentsDataTest, CopyState) { - tab_data()->SetLastInactiveTime(base::TimeTicks() + - base::TimeDelta::FromSeconds(42)); tab_data()->SetTabLoadingState(LOADED); tab_data()->SetIsInSessionRestore(true); tab_data()->SetIsRestoredInForeground(true);
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc index 7a4ae7c..22885b7 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.cc
@@ -64,10 +64,6 @@ return 0; } -bool TestLifecycleUnit::CanPurge() const { - return false; -} - bool TestLifecycleUnit::CanFreeze(DecisionDetails* decision_details) const { return false; }
diff --git a/chrome/browser/resource_coordinator/test_lifecycle_unit.h b/chrome/browser/resource_coordinator/test_lifecycle_unit.h index 876192e3..cde4b206 100644 --- a/chrome/browser/resource_coordinator/test_lifecycle_unit.h +++ b/chrome/browser/resource_coordinator/test_lifecycle_unit.h
@@ -41,7 +41,6 @@ LifecycleUnitLoadingState GetLoadingState() const override; bool Load() override; int GetEstimatedMemoryFreedOnDiscardKB() const override; - bool CanPurge() const override; bool CanFreeze(DecisionDetails* decision_details) const override; bool CanDiscard(LifecycleUnitDiscardReason reason, DecisionDetails* decision_details) const override;
diff --git a/chrome/browser/resources/bookmarks/command_manager.js b/chrome/browser/resources/bookmarks/command_manager.js index 95c1175d..8f153dd 100644 --- a/chrome/browser/resources/bookmarks/command_manager.js +++ b/chrome/browser/resources/bookmarks/command_manager.js
@@ -789,10 +789,14 @@ * @private */ onKeydown_: function(e) { - const selection = this.getState().selection.items; - if (e.target == document.body && + const path = e.composedPath(); + if (path[0].tagName == 'INPUT') { + return; + } + if ((e.target == document.body || + path.some(el => el.tagName == 'BOOKMARKS-TOOLBAR')) && !bookmarks.DialogFocusManager.getInstance().hasOpenDialog()) { - this.handleKeyEvent(e, selection); + this.handleKeyEvent(e, this.getState().selection.items); } },
diff --git a/chrome/browser/resources/browser_switcher/app.js b/chrome/browser/resources/browser_switcher/app.js index 4f2d80b..66138475 100644 --- a/chrome/browser/resources/browser_switcher/app.js +++ b/chrome/browser/resources/browser_switcher/app.js
@@ -107,12 +107,12 @@ */ computeTitle_: function() { if (this.error_) { - return this.i18n('errorTitle'); + return this.i18n('errorTitle', getBrowserName()); } if (this.secondCounter_ > 0) { - return this.i18n('countdownTitle', this.secondCounter_); + return this.i18n('countdownTitle', this.secondCounter_, getBrowserName()); } - return this.i18n('openingTitle'); + return this.i18n('openingTitle', getBrowserName()); }, /** @@ -121,12 +121,18 @@ */ computeDescription_: function() { if (this.error_) { - return this.i18n(this.error_, getUrlHostname(this.url_)); + return this.i18n( + this.error_, getUrlHostname(this.url_), getBrowserName()); } - return this.i18n('description', getUrlHostname(this.url_)); + return this.i18n( + 'description', getUrlHostname(this.url_), getBrowserName()); }, }); +function getBrowserName() { + return loadTimeData.getString('browserName'); +} + function getUrlHostname(url) { const anchor = document.createElement('a'); anchor.href = url;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/imagecapture.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/imagecapture.js index 712c8c82..9f588ee 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/mojo/imagecapture.js +++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/imagecapture.js
@@ -25,9 +25,15 @@ * Creates the wrapper of JS image-capture and Mojo image-capture. * @param {MediaStreamTrack} videoTrack A video track whose still images will be * taken. + * @param {string} deviceId The id of target media device. * @constructor */ -cca.mojo.ImageCapture = function(videoTrack) { +cca.mojo.ImageCapture = function(videoTrack, deviceId) { + /** + * @type {string} The id of target media device. + */ + this.deviceId_ = deviceId; + /** * @type {ImageCapture} * @private @@ -52,7 +58,7 @@ return Promise .all([ this.capture_.getPhotoCapabilities(), - this.mojoCapture_.getSupportedEffects(), + this.mojoCapture_.getSupportedEffects(this.deviceId_), ]) .then(([capabilities, effects]) => { capabilities.supportedEffects = effects.supportedEffects; @@ -74,7 +80,7 @@ const takes = []; if (photoEffects) { photoEffects.forEach((effect) => { - takes.push((this.mojoCapture_.setReprocessOption(effect)) + takes.push((this.mojoCapture_.setReprocessOption(this.deviceId_, effect)) .then(({status, blob}) => { if (status != 0) { throw new Error('Mojo image capture error: ' + status);
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index b6707a26..be13c261 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -619,6 +619,7 @@ "braille/liblouis_test.extjs", "cvox2/background/automation_util_test.extjs", "cvox2/background/background_test.extjs", + "cvox2/background/braille_command_data_test.extjs", "cvox2/background/color_test.extjs", "cvox2/background/cursors_test.extjs", "cvox2/background/editing_test.extjs",
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data.js index 0f9b024..b8c90f78 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data.js
@@ -91,9 +91,14 @@ */ BrailleCommandData.init_ = function() { var map = function(dots, command) { - BrailleCommandData - .DOT_PATTERN_TO_COMMAND[BrailleCommandData.makeDotPattern(dots)] = - command; + var pattern = BrailleCommandData.makeDotPattern(dots); + var existingCommand = BrailleCommandData.DOT_PATTERN_TO_COMMAND[pattern]; + if (existingCommand) { + throw 'Braille command pattern already exists: ' + dots + ' ' + + existingCommand + '. Trying to map ' + command; + } + + BrailleCommandData.DOT_PATTERN_TO_COMMAND[pattern] = command; }; map([2, 3], 'previousGroup'); @@ -139,7 +144,7 @@ map([1, 2, 3, 4, 5, 6], 'undarkenScreen'); // s. - map([2, 3, 4], 'toggleSpeechOnOrOff'); + map([1, 2, 3, 4, 5], 'toggleSpeechOnOrOff'); // g. map([1, 2, 4, 5], 'toggleBrailleTable');
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data_test.extjs new file mode 100644 index 0000000..9c23cdfa --- /dev/null +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_data_test.extjs
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Include test fixture. +GEN_INCLUDE(['../../testing/chromevox_next_e2e_test_base.js']); + +GEN_INCLUDE(['../../testing/assert_additions.js']); + +/** + * Test fixture for braille_command_data.js. + * @constructor + * @extends {ChromeVoxE2ETestBase} + */ +function ChromeVoxBrailleCommandDataTest() { + ChromeVoxNextE2ETest.call(this); +} + +ChromeVoxBrailleCommandDataTest.prototype = { + __proto__: ChromeVoxNextE2ETest.prototype, +}; + +SYNC_TEST_F('ChromeVoxBrailleCommandDataTest', 'Duplicates', function() { + try { + BrailleCommandData.DOT_PATTERN_TO_COMMAND = []; + BrailleCommandData.init_(); + } catch(e) { + assertNotReached(e.toString()); + } +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index f7f79fa..5cbc184 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -493,7 +493,7 @@ $description $state $restriction` }, menuItem: { - speak: `$name $role $if($haspopup, @has_submenu) + speak: `$name $role $if($hasPopup, @has_submenu) @describe_index($if($posInSet, $posInSet, $indexInParent(menuItem, menuItemCheckBox, menuItemRadio)), $if($setSize, $setSize, $parentChildCount(menuItem, menuItemCheckBox, menuItemRadio))) $description $state $restriction` @@ -726,6 +726,8 @@ switch (attrib) { case 'checked': return node.checked && node.checked !== 'false'; + case 'hasPopup': + return node.hasPopup && node.hasPopup !== 'false'; // Chrome automatically calculates these attributes. case 'posInSet':
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs index 72e6398..502f7677 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/recovery_strategy_test.extjs
@@ -43,12 +43,18 @@ var pTreePathRecovery = new TreePathRecoveryStrategy(p); var sTreePathRecovery = new TreePathRecoveryStrategy(s); this.listenOnce(b, 'clicked', function() { - assertFalse(bAncestryRecovery.requiresRecovery()); - assertTrue(pAncestryRecovery.requiresRecovery()); - assertTrue(sAncestryRecovery.requiresRecovery()); - assertFalse(bTreePathRecovery.requiresRecovery()); - assertTrue(pTreePathRecovery.requiresRecovery()); - assertTrue(sTreePathRecovery.requiresRecovery()); + assertFalse(bAncestryRecovery.requiresRecovery(), + "bAncestryRecovery.requiresRecovery"); + assertTrue(pAncestryRecovery.requiresRecovery(), + "pAncestryRecovery.requiresRecovery()"); + assertTrue(sAncestryRecovery.requiresRecovery(), + "sAncestryRecovery.requiresRecovery()"); + assertFalse(bTreePathRecovery.requiresRecovery(), + "bTreePathRecovery.requiresRecovery()"); + assertTrue(pTreePathRecovery.requiresRecovery(), + "pTreePathRecovery.requiresRecovery()"); + assertTrue(sTreePathRecovery.requiresRecovery(), + "sTreePathRecovery.requiresRecovery()"); assertEquals(RoleType.BUTTON, bAncestryRecovery.node.role); assertEquals(root, pAncestryRecovery.node); @@ -58,12 +64,18 @@ assertEquals(b, pTreePathRecovery.node); assertEquals(b, sTreePathRecovery.node); - assertFalse(bAncestryRecovery.requiresRecovery()); - assertFalse(pAncestryRecovery.requiresRecovery()); - assertFalse(sAncestryRecovery.requiresRecovery()); - assertFalse(bTreePathRecovery.requiresRecovery()); - assertFalse(pTreePathRecovery.requiresRecovery()); - assertFalse(sTreePathRecovery.requiresRecovery()); + assertFalse(bAncestryRecovery.requiresRecovery(), + "bAncestryRecovery.requiresRecovery()"); + assertFalse(pAncestryRecovery.requiresRecovery(), + "pAncestryRecovery.requiresRecovery()"); + assertFalse(sAncestryRecovery.requiresRecovery(), + "sAncestryRecovery.requiresRecovery()"); + assertFalse(bTreePathRecovery.requiresRecovery(), + "bTreePathRecovery.requiresRecovery()"); + assertFalse(pTreePathRecovery.requiresRecovery(), + "pTreePathRecovery.requiresRecovery()"); + assertFalse(sTreePathRecovery.requiresRecovery(), + "sTreePathRecovery.requiresRecovery()"); }); // Trigger the change. b.doDefault();
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js b/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js index c5684735..939275e 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/assert_additions.js
@@ -105,9 +105,10 @@ /** * Asserts and fails immediately once called. + * @param {string=} opt_msg */ -function assertNotReached() { - assertFalse(true); +function assertNotReached(opt_msg) { + assertFalse(true, opt_msg); } /**
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/api.js b/chrome/browser/resources/chromeos/kiosk_next_home/api.js index 2c787f7a..c86648a 100644 --- a/chrome/browser/resources/chromeos/kiosk_next_home/api.js +++ b/chrome/browser/resources/chromeos/kiosk_next_home/api.js
@@ -25,6 +25,13 @@ addListener(listener) {} /** + * Gets the obfuscated account Gaia ID associated with the current user + * session. + * @return {!Promise<string>} Promise for the obfuscated account Gaia ID. + */ + getAccountId() {} + + /** * Returns an access token with the requested scopes. * @param {!Array<string>} scopes List of scopes to use when obtaining access * token. @@ -68,6 +75,12 @@ * failures. */ uninstallApp(appId) {} + + /** + * Returns current device network state. + * @return {kioskNextHome.NetworkState} + */ + getNetworkState() {} }; /** @@ -82,6 +95,20 @@ }; /** + * Readiness status for apps. + * These values loosely map to AppService's apps.mojom.Readiness enum. + * @enum {string} + */ +kioskNextHome.AppReadiness = { + /** Installed and launchable. */ + READY: 'ready', + /** App is disabled by policy. */ + DISABLED: 'disabled', + /** App was uninstalled by user. */ + UNINSTALLED: 'uninstalled', +}; + +/** * A record representing an installed app on the system. * @record */ @@ -99,12 +126,23 @@ this.displayName; /** @type {string | undefined} Base64-encoded thumbnail image, fallback. */ this.thumbnailImage; - /** @type {boolean} Whether the app is suspended by policy. */ - this.suspended; + /** + * @type {kioskNextHome.AppReadiness} Current readiness state for the app. + */ + this.readiness; } }; /** + * Current network state of the device. + * @enum {string} + */ +kioskNextHome.NetworkState = { + ONLINE: 'online', + OFFLINE: 'offline', +}; + +/** * Interface for a listener of system events, subscribed via * {!kioskNextHome.Bridge}. * @@ -119,10 +157,11 @@ onAppChanged(app) {} /** - * Called when the network state changes between online and offline. - * @param {boolean} isOnline Whether device has Internet access. + * Called when the network state changes. + * @param {kioskNextHome.NetworkState} networkState Current network state of + * the device. */ - onOnlineStateChanged(isOnline) {} + onNetworkStateChanged(networkState) {} }; /**
diff --git a/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js b/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js index 06ab734..86c2be4d 100644 --- a/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js +++ b/chrome/browser/resources/chromeos/kiosk_next_home/api_impl.js
@@ -18,7 +18,7 @@ type: kioskNextHome.AppType.ARC, displayName: packageName, packageName: packageName, - suspended: false, + readiness: kioskNextHome.AppReadiness.READY, thumbnailImage: '', }; } @@ -44,6 +44,14 @@ listener.onAppChanged(buildApp(installedApp.packageName)); } }); + + window.addEventListener( + 'online', + () => this.notifyNetworkStateChange(kioskNextHome.NetworkState.ONLINE)); + window.addEventListener( + 'offline', + () => + this.notifyNetworkStateChange(kioskNextHome.NetworkState.OFFLINE)); } /** @override */ @@ -52,6 +60,12 @@ } /** @override */ + getAccountId() { + return this.identityAccessorProxy_.getPrimaryAccountWhenAvailable().then( + account => account.accountInfo.gaia); + } + + /** @override */ getAccessToken(scopes) { return this.identityAccessorProxy_.getPrimaryAccountWhenAvailable() .then(account => { @@ -105,6 +119,23 @@ // TODO(brunoad): Implement this method. return Promise.reject('Not implemented.'); } + + /** @override */ + getNetworkState() { + return navigator.onLine ? kioskNextHome.NetworkState.ONLINE : + kioskNextHome.NetworkState.OFFLINE; + } + + /** + * Notifies listeners about changes in network connection state. + * @param {kioskNextHome.NetworkState} networkState Indicates current network + * state. + */ + notifyNetworkStateChange(networkState) { + for (const listener of this.listeners_) { + listener.onNetworkStateChanged(networkState); + } + } } /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_eula.js b/chrome/browser/resources/chromeos/login/oobe_screen_eula.js index ab7dca4..71d532a 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_eula.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_eula.js
@@ -7,7 +7,6 @@ */ login.createScreen('EulaScreen', 'eula', function() { - var CONTEXT_KEY_USAGE_STATS_ENABLED = 'usageStatsEnabled'; var CLEAR_ANCHORS_CONTENT_SCRIPT = { code: 'A=Array.from(document.getElementsByTagName("a"));' + 'for(var i = 0; i < A.length; ++i) {' + @@ -112,8 +111,7 @@ * @param {boolean} value $('usage-stats').checked value. */ onUsageStatsClicked_: function(value) { - this.context.set(CONTEXT_KEY_USAGE_STATS_ENABLED, value); - this.commitContextChanges(); + chrome.send('EulaScreen.usageStatsEnabled', [value]); }, /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js index 5ad495a7..9ac6048 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
@@ -7,41 +7,19 @@ */ login.createScreen('UserImageScreen', 'user-image', function() { - var CONTEXT_KEY_IS_CAMERA_PRESENT = 'isCameraPresent'; - var CONTEXT_KEY_SELECTED_IMAGE_INDEX = 'selectedImageIndex'; - var CONTEXT_KEY_SELECTED_IMAGE_URL = 'selectedImageURL'; - var CONTEXT_KEY_PROFILE_PICTURE_DATA_URL = 'profilePictureDataURL'; - var CONTEXT_KEY_IS_PROFILE_PICTURE_AVAILABLE = 'isProfilePictureAvailable'; - return { - EXTERNAL_API: ['setDefaultImages', 'hideCurtain'], + EXTERNAL_API: [ + 'setDefaultImages', + 'hideCurtain', + 'setIsCameraPresent', + 'setProfilePictureDataURL', + 'setIsProfilePictureAvailable', + 'setSelectedImageIndex', + 'setSelectedImageURL', + ], /** @override */ decorate: function(element) { - var self = this; - this.context.addObserver( - CONTEXT_KEY_IS_CAMERA_PRESENT, function(present) { - $('changePicture').cameraPresent = present; - }); - this.context.addObserver( - CONTEXT_KEY_SELECTED_IMAGE_INDEX, this.setSelectedImageIndex_); - this.context.addObserver( - CONTEXT_KEY_SELECTED_IMAGE_URL, this.setSelectedImageUrl_); - this.context.addObserver( - CONTEXT_KEY_PROFILE_PICTURE_DATA_URL, function(url) { - self.profileImageLoading = false; - if (url) - $('changePicture').setProfileImageUrl(url, false /* selected */); - }); - this.context.addObserver( - CONTEXT_KEY_IS_PROFILE_PICTURE_AVAILABLE, function(available) { - if (!available) { - self.profileImageLoading = false; - // Empty url hides profile image selection choice. - $('changePicture').setProfileImageUrl('', false /* selected */); - } - }); - this.profileImageLoading = true; chrome.send('getImages'); }, @@ -117,26 +95,6 @@ chrome.send('screenReady'); }, - /** - * Selects user image with the given index. - * @param {number} index Index of the image to select. - * @private - */ - setSelectedImageIndex_: function(index) { - $('changePicture').selectedImageIndex = index; - }, - - /** - * Selects user image with the given URL. - * @param {string} url URL of the image to select. - * @private - */ - setSelectedImageUrl_: function(url) { - if (!url) - return; - $('changePicture').selectedImageUrl = url; - }, - get loading() { return this.classList.contains('loading'); }, @@ -155,6 +113,45 @@ $('changePicture').focus(); }, + /** @param {boolean} present */ + setIsCameraPresent: function(present) { + $('changePicture').cameraPresent = present; + }, + + /** @param {string} url */ + setProfilePictureDataURL: function(url) { + this.profileImageLoading = false; + if (url) + $('changePicture').setProfileImageUrl(url, false /* selected */); + }, + + /** @param {boolean} available */ + setIsProfilePictureAvailable: function(available) { + if (!available) { + this.profileImageLoading = false; + // Empty url hides profile image selection choice. + $('changePicture').setProfileImageUrl('', false /* selected */); + } + }, + + /** + * Selects user image with the given index. + * @param {number} index Index of the image to select. + */ + setSelectedImageIndex: function(index) { + $('changePicture').selectedImageIndex = index; + }, + + /** + * Selects user image with the given URL. + * @param {string} url URL of the image to select. + */ + setSelectedImageURL: function(url) { + if (!url) + return; + $('changePicture').selectedImageUrl = url; + }, + /** * Updates localized content of the screen that is not updated via template. */
diff --git a/chrome/browser/resources/feed_internals/feed_internals.html b/chrome/browser/resources/feed_internals/feed_internals.html index d93e1fe..5d4c9c00 100644 --- a/chrome/browser/resources/feed_internals/feed_internals.html +++ b/chrome/browser/resources/feed_internals/feed_internals.html
@@ -67,7 +67,11 @@ <button id="clear-user-classification"> Clear User Classification </button> + <h2>Feed Library Actions</h2> + <button id="refresh-feed"> + Refresh Feed + </button> <button id="clear-cached-data"> Clear Cache & Refresh Feed </button>
diff --git a/chrome/browser/resources/feed_internals/feed_internals.js b/chrome/browser/resources/feed_internals/feed_internals.js index c1e48eec..224f5bd 100644 --- a/chrome/browser/resources/feed_internals/feed_internals.js +++ b/chrome/browser/resources/feed_internals/feed_internals.js
@@ -108,6 +108,16 @@ } /** + * Update last fetch properties and current content following a Feed refresh. + */ +function updateAfterRefresh() { + // TODO(crbug.com/939907): Listen for Feed update events rather than waiting + // an arbitrary period of time. + setTimeout(updatePageWithLastFetchProperties, 1000); + setTimeout(updatePageWithCurrentContent, 1000); +} + +/** * Hook up buttons to event listeners. */ function setupEventListeners() { @@ -118,14 +128,12 @@ $('clear-cached-data').addEventListener('click', function() { pageHandler.clearCachedDataAndRefreshFeed(); + updateAfterRefresh(); + }); - // TODO(chouinard): Investigate whether the Feed library's - // AppLifecycleListener.onClearAll methods could accept a callback to notify - // when cache clear and Feed refresh operations are complete. If not, - // consider adding backend->frontend mojo communication to listen for - // updates, rather than waiting an arbitrary period of time. - setTimeout(updatePageWithLastFetchProperties, 1000); - setTimeout(updatePageWithCurrentContent, 1000); + $('refresh-feed').addEventListener('click', function() { + pageHandler.refreshFeed(); + updateAfterRefresh(); }); $('dump-feed-process-scope').addEventListener('click', function() {
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js index f6d08a9..f593b982 100644 --- a/chrome/browser/resources/feedback/js/feedback.js +++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -225,8 +225,10 @@ feedbackInfo.email = $('user-email-drop-down').value; let useSystemInfo = false; + let useHistograms = false; if ($('sys-info-checkbox') != null && $('sys-info-checkbox').checked) { - useSystemInfo = true; + // Send histograms along with system info. + useSystemInfo = useHistograms = true; } // <if expr="chromeos"> @@ -251,6 +253,8 @@ } // </if> + feedbackInfo.sendHistograms = useHistograms; + // If the user doesn't want to send the screenshot. if (!$('screenshot-checkbox').checked) { feedbackInfo.screenshot = null; @@ -535,6 +539,14 @@ }; } + const histogramUrlElement = $('histograms-url'); + if (histogramUrlElement) { + // Opens a new window showing the histogram metrics. + setupLinkHandlers( + histogramUrlElement, 'chrome://histograms', + true /* useAppWindow */); + } + const legalHelpPageUrlElement = $('legal-help-page-url'); if (legalHelpPageUrlElement) { setupLinkHandlers(
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log.html b/chrome/browser/resources/md_extensions/activity_log/activity_log.html index b9bae98..2462b48 100644 --- a/chrome/browser/resources/md_extensions/activity_log/activity_log.html +++ b/chrome/browser/resources/md_extensions/activity_log/activity_log.html
@@ -22,8 +22,6 @@ <style include="cr-icons shared-style paper-tabs-style"> #activity-log-heading { @apply --cr-title-text; - display: flex; - flex-direction: row; flex-grow: 1; } @@ -46,6 +44,25 @@ font-size: inherit; height: 40px; } + + .page-content { + display: flex; + flex-direction: column; + padding-bottom: 0; + } + + iron-pages { + flex: 1; + position: relative; + } + + activity-log-history, + activity-log-stream { + bottom: 0; + position: absolute; + top: 0; + width: 100%; + } </style> <div class="page-container" id="container"> <div class="page-content">
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log_history.html b/chrome/browser/resources/md_extensions/activity_log/activity_log_history.html index 76ea48e..fa99c5e 100644 --- a/chrome/browser/resources/md_extensions/activity_log/activity_log_history.html +++ b/chrome/browser/resources/md_extensions/activity_log/activity_log_history.html
@@ -11,13 +11,20 @@ <template> <style include="paper-button-style shared-style"> :host { - --activity-log-call-and-count-width: 529px; + --activity-log-call-and-count-width: 514px; --activity-type-width: 85px; --activity-count-width: 100px; + + display: flex; + flex-direction: column; } .activity-table-headings { - max-width: var(--activity-log-call-and-count-width); + width: var(--activity-log-call-and-count-width); + } + + #activity-list { + overflow-y: auto; } #activity-type { @@ -50,13 +57,14 @@ pageState_, activityData_)]]"> <span>$i18n{noActivities}</span> </div> + <div class="activity-table-headings" + hidden$="[[!shouldShowActivities_(pageState_, activityData_)]]"> + <span id="activity-type">$i18n{activityLogTypeColumn}</span> + <span id="activity-key">$i18n{activityLogNameColumn}</span> + <span id="activity-count">$i18n{activityLogCountColumn}</span> + </div> <div id="activity-list" hidden$="[[!shouldShowActivities_(pageState_, activityData_)]]"> - <div class="activity-table-headings"> - <span id="activity-type">$i18n{activityLogTypeColumn}</span> - <span id="activity-key">$i18n{activityLogNameColumn}</span> - <span id="activity-count">$i18n{activityLogCountColumn}</span> - </div> <template is="dom-repeat" items="[[activityData_]]"> <activity-log-history-item data="[[item]]"> </activity-log-history-item>
diff --git a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html index 5ab89ab..314c9f06 100644 --- a/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html +++ b/chrome/browser/resources/md_extensions/activity_log/activity_log_stream.html
@@ -10,13 +10,20 @@ <template> <style include="shared-style paper-button-style"> :host { - --activity-log-call-and-time-width: 596px; + --activity-log-call-and-time-width: 575px; --activity-type-width: 85px; --activity-time-width: 100px; + + display: flex; + flex-direction: column; } .activity-table-headings { - max-width: var(--activity-log-call-and-time-width); + width: var(--activity-log-call-and-time-width); + } + + #activity-stream-list { + overflow-y: auto; } #activity-type { @@ -56,13 +63,14 @@ $i18n{emptyStreamStarted} </span> </div> + <div class="activity-table-headings" + hidden$="[[isStreamEmpty_(activityStream_.length)]]"> + <span id="activity-type">$i18n{activityLogTypeColumn}</span> + <span id="activity-key">$i18n{activityLogNameColumn}</span> + <span id="activity-time">$i18n{activityLogTimeColumn}</span> + </div> <div id="activity-stream-list" hidden$="[[isStreamEmpty_(activityStream_.length)]]"> - <div class="activity-table-headings"> - <span id="activity-type">$i18n{activityLogTypeColumn}</span> - <span id="activity-key">$i18n{activityLogNameColumn}</span> - <span id="activity-time">$i18n{activityLogTimeColumn}</span> - </div> <template is="dom-repeat" items="[[activityStream_]]"> <activity-log-stream-item data="[[item]]"></activity-log-stream-item> </template>
diff --git a/chrome/browser/resources/page_not_available_for_guest/app.html b/chrome/browser/resources/page_not_available_for_guest/app.html index 3313ee43..8e73d76 100644 --- a/chrome/browser/resources/page_not_available_for_guest/app.html +++ b/chrome/browser/resources/page_not_available_for_guest/app.html
@@ -1,12 +1,17 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{dark}> <head> <meta charset="utf-8"> <title>$i18n{pageTitle}</title> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> + <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <style> + html { + background: var(--md-background-color); + } + h1 { - color: #6e6e6e; + color: var(--md-loading-message-color); font-weight: 500; margin-top: 80px; text-align: center; @@ -15,5 +20,8 @@ </head> <body> <h1>$i18n{pageHeading}</h1> + <link rel="import" href="chrome://resources/html/load_time_data.html"> + <script src="strings.js"></script> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index b4aebff..0e4cc677 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -454,6 +454,11 @@ this.selectFinalFallbackDestination_(); } + /** Removes all events being tracked from the tracker. */ + resetTracker() { + this.tracker_.removeAll(); + } + /** * Attempts to fetch capabilities of the destination identified by * |serializedDestination|.
diff --git a/chrome/browser/resources/print_preview/data/invitation_store.js b/chrome/browser/resources/print_preview/data/invitation_store.js index eeb06ea..724a309 100644 --- a/chrome/browser/resources/print_preview/data/invitation_store.js +++ b/chrome/browser/resources/print_preview/data/invitation_store.js
@@ -94,6 +94,11 @@ this.onCloudPrintProcessInviteDone_.bind(this)); } + /** Removes all events being tracked from the tracker. */ + resetTracker() { + this.tracker_.removeAll(); + } + /** * Initiates loading of cloud printer sharing invitations for the user * account given by |user|.
diff --git a/chrome/browser/resources/print_preview/data/user_info.js b/chrome/browser/resources/print_preview/data/user_info.js index 9f454f53..1be3c44 100644 --- a/chrome/browser/resources/print_preview/data/user_info.js +++ b/chrome/browser/resources/print_preview/data/user_info.js
@@ -53,6 +53,11 @@ /** @private {!EventTracker} */ tracker_: new EventTracker(), + /** @override */ + detached: function() { + this.tracker_.removeAll(); + }, + /** @param {!cloudprint.CloudPrintInterface} cloudPrintInterface */ setCloudPrintInterface: function(cloudPrintInterface) { this.tracker_.add(
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.js b/chrome/browser/resources/print_preview/new/destination_dialog.js index db2ba5f..d703f13 100644 --- a/chrome/browser/resources/print_preview/new/destination_dialog.js +++ b/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -99,6 +99,11 @@ assert(this.$$('.sign-in')), 'click', this.onSignInClick_.bind(this)); }, + /** @override */ + detached: function() { + this.tracker_.removeAll(); + }, + /** * @param {!KeyboardEvent} e Event containing the key * @private
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.js b/chrome/browser/resources/print_preview/new/destination_settings.js index 4a415a68..d4d58e0 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.js +++ b/chrome/browser/resources/print_preview/new/destination_settings.js
@@ -111,6 +111,13 @@ this.updateDropdownDestinations_.bind(this)); }, + /** @override */ + detached: function() { + this.invitationStore_.resetTracker(); + this.destinationStore_.resetTracker(); + this.tracker_.removeAll(); + }, + /** @param {!cloudprint.CloudPrintInterface} cloudPrintInterface */ setCloudPrintInterface: function(cloudPrintInterface) { [cloudprint.CloudPrintInterfaceEventType.SEARCH_FAILED,
diff --git a/chrome/browser/resources/print_preview/new/pages_settings.js b/chrome/browser/resources/print_preview/new/pages_settings.js index c2d4bfd..84c3132 100644 --- a/chrome/browser/resources/print_preview/new/pages_settings.js +++ b/chrome/browser/resources/print_preview/new/pages_settings.js
@@ -374,14 +374,6 @@ }, /** - * @param {!Event} e Click event - * @private - */ - onCustomInputClick_: function(e) { - e.stopPropagation(); - }, - - /** * @return {string} Gets message to show as hint. * @private */
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html index 20f1283..eb0922a 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html +++ b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html
@@ -33,7 +33,8 @@ <div class="toggle-container settings-box"> <div class="label">[[item.label]]</div> <cr-toggle class="toggle" checked="[[item.shared]]" - on-change="onDeviceSharedChange_"></cr-toggle> + on-change="onDeviceSharedChange_" + aria-label$="[[item.label]]"></cr-toggle> </div> </div> </template>
diff --git a/chrome/browser/resources/settings/internet_page/OWNERS b/chrome/browser/resources/settings/internet_page/OWNERS new file mode 100644 index 0000000..137a112 --- /dev/null +++ b/chrome/browser/resources/settings/internet_page/OWNERS
@@ -0,0 +1 @@ +file://chromeos/network/OWNERS
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html index 907239d..d0636adb 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -175,7 +175,7 @@ managedNetworkAvailable)]]"> <div class="settings-box"> <div id="autoConnectToggleLabel" class="start settings-box-text"> - $i18n{networkAutoConnect} + [[getAutoConnectToggleLabel_(networkProperties_)]] </div> <template is="dom-if" if="[[isAutoConnectEnforcedByPolicy( networkProperties_, globalPolicy)]]">
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js index 5d6af27..1b748b27 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -478,6 +478,17 @@ /** * @param {!CrOnc.NetworkProperties} networkProperties + * @return {string} The text to display for auto-connect toggle label. + * @private + */ + getAutoConnectToggleLabel_: function(networkProperties) { + return this.isCellular_(networkProperties) ? + this.i18n('networkAutoConnectCellular') : + this.i18n('networkAutoConnect'); + }, + + /** + * @param {!CrOnc.NetworkProperties} networkProperties * @return {boolean} True if the network is connected. * @private */
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html index c7227b8..a4243c7a 100644 --- a/chrome/browser/resources/settings/people_page/sync_account_control.html +++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -112,6 +112,7 @@ } #sign-in { + margin: auto 8px; min-width: 100px; }
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers.js b/chrome/browser/resources/settings/printing_page/cups_printers.js index 8321fbfb..19a7fe7 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers.js
@@ -61,7 +61,8 @@ /** @override */ attached: function() { - this.addWebUIListener('on-add-cups-printer', this.onAddPrinter_.bind(this)); + this.addWebUIListener('on-add-or-edit-cups-printer', + this.onAddOrEditPrinter_.bind(this)); this.addWebUIListener( 'on-printers-changed', this.printersChanged_.bind(this)); this.networksChangedListener_ = this.refreshNetworks_.bind(this); @@ -106,53 +107,59 @@ * @param {string} printerName * @private */ - onAddPrinter_: function(result_code, printerName) { - if (result_code == PrinterSetupResult.SUCCESS) { - this.updateCupsPrintersList_(); - this.addPrinterResultText_ = - loadTimeData.getStringF('printerAddedSuccessfulMessage', printerName); - } else { - switch (result_code) { - case PrinterSetupResult.FATAL_ERROR: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedFatalErrorMessage'); - break; - case PrinterSetupResult.PRINTER_UNREACHABLE: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedUnreachableMessage'); - break; - case PrinterSetupResult.DBUS_ERROR: - // Simply display a generic error message as this error should only - // occur when a call to Dbus fails which isn't meaningful to the user. - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedFailedMessage'); - break; - case PrinterSetupResult.NATIVE_PRINTERS_NOT_ALLOWED: - this.addPrinterResultText_ = loadTimeData.getString( - 'printerAddedNativePrintersNotAllowedMessage'); - break; - case PrinterSetupResult.INVALID_PRINTER_UPDATE: - this.addPrinterResultText_ = - loadTimeData.getString('editPrinterInvalidPrinterUpdate'); - break; - case PrinterSetupResult.PPD_TOO_LARGE: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedPpdTooLargeMessage'); - break; - case PrinterSetupResult.INVALID_PPD: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedInvalidPpdMessage'); - break; - case PrinterSetupResult.PPD_NOT_FOUND: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedPpdNotFoundMessage'); - break; - case PrinterSetupResult.PPD_UNRETRIEVABLE: - this.addPrinterResultText_ = - loadTimeData.getString('printerAddedPpdUnretrievableMessage'); - break; + onAddOrEditPrinter_: function(result_code, printerName) { + switch (result_code) { + case PrinterSetupResult.SUCCESS: + this.updateCupsPrintersList_(); + this.addPrinterResultText_ = + loadTimeData.getStringF('printerAddedSuccessfulMessage', + printerName); + break; + case PrinterSetupResult.EDIT_SUCCESS: + this.updateCupsPrintersList_(); + this.addPrinterResultText_ = + loadTimeData.getStringF('printerEditedSuccessfulMessage', + printerName); + break; + case PrinterSetupResult.FATAL_ERROR: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedFatalErrorMessage'); + break; + case PrinterSetupResult.PRINTER_UNREACHABLE: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedUnreachableMessage'); + break; + case PrinterSetupResult.DBUS_ERROR: + // Simply display a generic error message as this error should only + // occur when a call to Dbus fails which isn't meaningful to the user. + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedFailedMessage'); + break; + case PrinterSetupResult.NATIVE_PRINTERS_NOT_ALLOWED: + this.addPrinterResultText_ = loadTimeData.getString( + 'printerAddedNativePrintersNotAllowedMessage'); + break; + case PrinterSetupResult.INVALID_PRINTER_UPDATE: + this.addPrinterResultText_ = + loadTimeData.getString('editPrinterInvalidPrinterUpdate'); + break; + case PrinterSetupResult.PPD_TOO_LARGE: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedPpdTooLargeMessage'); + break; + case PrinterSetupResult.INVALID_PPD: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedInvalidPpdMessage'); + break; + case PrinterSetupResult.PPD_NOT_FOUND: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedPpdNotFoundMessage'); + break; + case PrinterSetupResult.PPD_UNRETRIEVABLE: + this.addPrinterResultText_ = + loadTimeData.getString('printerAddedPpdUnretrievableMessage'); + break; } - } this.$.errorToast.show(); },
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js index 5963d59..61eaa1c7 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -92,6 +92,8 @@ DBUS_ERROR: 3, NATIVE_PRINTERS_NOT_ALLOWED: 4, INVALID_PRINTER_UPDATE: 5, + COMPONENT_UNAVAILAVLE: 6, + EDIT_SUCCESS: 7, PPD_TOO_LARGE: 10, INVALID_PPD: 11, PPD_NOT_FOUND: 12,
diff --git a/chrome/browser/resources/usb_internals/BUILD.gn b/chrome/browser/resources/usb_internals/BUILD.gn index 2d9afb3b..28ec89bb 100644 --- a/chrome/browser/resources/usb_internals/BUILD.gn +++ b/chrome/browser/resources/usb_internals/BUILD.gn
@@ -6,6 +6,7 @@ js_type_check("closure_compile") { deps = [ + ":descriptor_panel", ":device_page", ":usb_internals", ] @@ -13,7 +14,7 @@ js_library("usb_internals") { deps = [ - ":device_page" + ":device_page", "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js_library_for_compile", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:util", @@ -22,4 +23,10 @@ } js_library("devices_page") { + deps = [ + ":descriptor_panel", + ] +} + +js_library("descriptor_panel") { }
diff --git a/chrome/browser/resources/usb_internals/descriptor_panel.js b/chrome/browser/resources/usb_internals/descriptor_panel.js new file mode 100644 index 0000000..22cbcb2b --- /dev/null +++ b/chrome/browser/resources/usb_internals/descriptor_panel.js
@@ -0,0 +1,825 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Javascript for DescriptorPanel UI, served from + * chrome://usb-internals/. + */ + +cr.define('descriptor_panel', function() { + // Standard USB requests and descriptor types: + const GET_DESCRIPTOR_REQUEST = 0x06; + const DEVICE_DESCRIPTOR_TYPE = 0x01; + const CONFIGURATION_DESCRIPTOR_TYPE = 0x02; + const STRING_DESCRIPTOR_TYPE = 0x03; + const INTERFACE_DESCRIPTOR_TYPE = 0x04; + const ENDPOINT_DESCRIPTOR_TYPE = 0x05; + + const DEVICE_DESCRIPTOR_LENGTH = 18; + const CONFIGURATION_DESCRIPTOR_LENGTH = 9; + const INTERFACE_DESCRIPTOR_LENGTH = 9; + const ENDPOINT_DESCRIPTOR_LENGTH = 7; + + const CONTROL_TRANSFER_TIMEOUT_MS = 2000; // 2 seconds + + class DescriptorPanel { + /** + * @param {!device.mojom.UsbDeviceInterface} usbDeviceProxy + * @param {HTMLElement} rootElement + */ + constructor(usbDeviceProxy, rootElement) { + /** @private {!device.mojom.UsbDeviceInterface} */ + this.usbDeviceProxy_ = usbDeviceProxy; + + /** @private {!HTMLElement} */ + this.rootElement_ = rootElement; + + const descriptorPanelTemplate = + document.querySelector('#descriptor-panel-template'); + const descriptorPanelClone = + document.importNode(descriptorPanelTemplate.content, true); + + /** @private {!HTMLElement} */ + this.rawDataTreeRoot_ = + descriptorPanelClone.querySelector('#raw-data-tree-view'); + /** @private {!HTMLElement} */ + this.rawDataElement_ = descriptorPanelClone.querySelector('#raw-data'); + + this.clearView(); + + cr.ui.decorate(this.rawDataTreeRoot_, cr.ui.Tree); + this.rawDataTreeRoot_.detail = {payload: {}, children: {}}; + + this.rootElement_.appendChild(descriptorPanelClone); + } + + /** + * Clears the data first before populating it with the new content. + */ + clearView() { + this.rootElement_.querySelectorAll('error').forEach(el => el.remove()); + this.rawDataTreeRoot_.innerText = ''; + this.rawDataElement_.textContent = ''; + } + + /** + * Adds function for mapping between two views. + * @private + */ + addMappingAction_() { + // Highlights the byte(s) that hovered in the tree. + this.rawDataTreeRoot_.querySelectorAll('.tree-row').forEach((el) => { + const classList = el.classList; + // classList[0] is 'tree-row'. classList[1] of tree item for fields + // starts with 'field-offset-', and classList[1] of tree item for + // descriptors (ie. endpoint descriptor) is descriptor type and index. + const fieldOffsetOrDescriptorClass = classList[1]; + assert( + fieldOffsetOrDescriptorClass.startsWith('field-offset-') || + fieldOffsetOrDescriptorClass.startsWith('descriptor-')); + + el.addEventListener('pointerenter', (event) => { + this.rawDataElement_ + .querySelectorAll(`.${fieldOffsetOrDescriptorClass}`) + .forEach((el) => el.classList.add('hovered-field')); + event.stopPropagation(); + }); + + el.addEventListener('pointerleave', () => { + this.rawDataElement_ + .querySelectorAll(`.${fieldOffsetOrDescriptorClass}`) + .forEach((el) => el.classList.remove('hovered-field')); + }); + + el.addEventListener('click', (event) => { + if (event.target.className != 'expand-icon') { + // Clears all the selected elements before select another. + this.rawDataElement_.querySelectorAll('#raw-data span') + .forEach((el) => el.classList.remove('selected-field')); + + this.rawDataElement_ + .querySelectorAll(`.${fieldOffsetOrDescriptorClass}`) + .forEach((el) => el.classList.add('selected-field')); + } + }); + }); + + // Selects the tree item that displays the byte hovered in the raw view. + const rawDataByteElements = this.rawDataElement_.querySelectorAll('span'); + rawDataByteElements.forEach((el) => { + const classList = el.classList; + + const fieldOffsetClass = classList[0]; + assert(fieldOffsetClass.startsWith('field-offset-')); + + el.addEventListener('pointerenter', () => { + this.rawDataElement_.querySelectorAll(`.${fieldOffsetClass}`) + .forEach((el) => el.classList.add('hovered-field')); + const el = + this.rawDataTreeRoot_.querySelector(`.${fieldOffsetClass}`); + if (el) { + el.classList.add('hover'); + } + }); + + el.addEventListener('pointerleave', () => { + this.rawDataElement_.querySelectorAll(`.${fieldOffsetClass}`) + .forEach((el) => el.classList.remove('hovered-field')); + const el = + this.rawDataTreeRoot_.querySelector(`.${fieldOffsetClass}`); + if (el) { + el.classList.remove('hover'); + } + }); + + el.addEventListener('click', () => { + const el = + this.rawDataTreeRoot_.querySelector(`.${fieldOffsetClass}`); + if (el) { + el.click(); + } + }); + }); + } + + /** + * Renders an element to display the raw data in hex, byte by byte, and + * keeps every row no more than 16 bytes. + * @param {!Uint8Array} rawData + * @private + */ + renderRawDataBytes_(rawData) { + const rawDataByteTemplate = document.querySelector('#raw-data-byte'); + for (const [i, value] of rawData.entries()) { + const rawDataByteClone = + document.importNode(rawDataByteTemplate.content, true); + const rawDataByteElement = rawDataByteClone.querySelector('span'); + + rawDataByteElement.textContent = + value.toString(16).padStart(2, '0').slice(-2).toUpperCase(); + this.rawDataElement_.appendChild(rawDataByteElement); + } + } + + /** + * Renders a tree view to display the raw data in readable text. + * @param {!cr.ui.Tree|!cr.ui.TreeItem} root + * @param {!Array<Object>} fields + * @param {!Uint8Array} rawData + * @param {number} offset + * @param {string=} opt_parentClassName + * @return {number} + * @private + */ + renderRawDataTree_(root, fields, rawData, offset, opt_parentClassName) { + const rawDataByteElements = this.rawDataElement_.querySelectorAll('span'); + + for (const field of fields) { + const className = `field-offset-${offset}`; + + const item = customTreeItem( + `${field.label}: ${field.formatter(rawData, offset)}`, className); + + for (let i = 0; i < field.size; i++) { + rawDataByteElements[offset + i].classList.add(className); + if (opt_parentClassName) { + rawDataByteElements[offset + i].classList.add(opt_parentClassName); + } + } + + root.add(item); + + offset += field.size; + } + + return offset; + } + + /** + * Checks the if the status of a descriptor read indicates success. + * @param {number} status + * @param {string} defaultMessage + * @return {boolean} + * @private + */ + checkDescriptorGetSuccess_(status, defaultMessage) { + let failReason = ''; + switch (status) { + case device.mojom.UsbTransferStatus.COMPLETED: + return; + case device.mojom.UsbTransferStatus.SHORT_PACKET: + this.showError_('Descriptor is too short.'); + return; + case device.mojom.UsbTransferStatus.BABBLE: + this.showError_('Descriptor is too long.'); + return; + case device.mojom.UsbTransferStatus.TRANSFER_ERROR: + failReason = 'Transfer Error'; + break; + case device.mojom.UsbTransferStatus.TIMEOUT: + failReason = 'Timeout'; + break; + case device.mojom.UsbTransferStatus.CANCELLED: + failReason = 'Transfer was cancelled'; + break; + case device.mojom.UsbTransferStatus.STALLED: + failReason = 'Transfer Error'; + break; + case device.mojom.UsbTransferStatus.DISCONNECT: + failReason = 'Transfer stalled'; + break; + case device.mojom.UsbTransferStatus.PERMISSION_DENIED: + failReason = 'Permission denied'; + break; + } + this.showError_(`${defaultMessage} (Reason: ${failReason})`); + throw new Error(`${defaultMessage} (${failReason})`); + } + + /** + * Shows an error message if error occurs in getting or rendering + * descriptors. + * @param {string} message + * @private + */ + showError_(message) { + const errorTemplate = document.querySelector('#error'); + + const clone = document.importNode(errorTemplate.content, true); + + const errorText = clone.querySelector('error'); + errorText.textContent = message; + + this.rootElement_.prepend(clone); + } + + /** + * Gets device descriptor of current device. + * @return {!Uint8Array} + * @private + */ + async getDeviceDescriptor_() { + /** @type {device.mojom.UsbControlTransferParams} */ + const usbControlTransferParams = {}; + usbControlTransferParams.type = + device.mojom.UsbControlTransferType.STANDARD; + usbControlTransferParams.recipient = + device.mojom.UsbControlTransferRecipient.DEVICE; + usbControlTransferParams.request = GET_DESCRIPTOR_REQUEST; + usbControlTransferParams.value = (DEVICE_DESCRIPTOR_TYPE << 8); + usbControlTransferParams.index = 0; + const length = DEVICE_DESCRIPTOR_LENGTH; + const timeout = CONTROL_TRANSFER_TIMEOUT_MS; + + await this.usbDeviceProxy_.open(); + + const response = await this.usbDeviceProxy_.controlTransferIn( + usbControlTransferParams, length, timeout); + + this.checkDescriptorGetSuccess_( + response.status, 'Failed to read the device descriptor'); + + return new Uint8Array(response.data); + } + + /** + * Renders a view to display device descriptor hex data in both tree view + * and raw form. + */ + async renderDeviceDescriptor() { + const rawData = await this.getDeviceDescriptor_(); + + this.renderRawDataBytes_(rawData); + + const fields = [ + { + label: 'Length', + size: 1, + formatter: formatByte, + }, + { + label: 'Descriptor Type', + size: 1, + formatter: formatDescriptorType, + }, + { + label: 'USB Version', + size: 2, + formatter: formatUsbVersion, + }, + { + label: 'Class Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Subclass Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Protocol Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Control Pipe Maximum Packet Size', + size: 1, + formatter: formatByte, + }, + { + label: 'Vendor ID', + size: 2, + formatter: formatTwoBytesToHex, + }, + { + label: 'Product ID', + size: 2, + formatter: formatTwoBytesToHex, + }, + { + label: 'Device Version', + size: 2, + formatter: formatUsbVersion, + }, + { + label: 'Manufacturer String Index', + size: 1, + formatter: formatByte, + }, + { + label: 'Product String Index', + size: 1, + formatter: formatByte, + }, + { + label: 'Serial Number Index', + size: 1, + formatter: formatByte, + }, + { + label: 'Number of Configurations', + size: 1, + formatter: formatByte, + }, + ]; + + let offset = 0; + offset = this.renderRawDataTree_( + this.rawDataTreeRoot_, fields, rawData, offset); + + assert( + offset === DEVICE_DESCRIPTOR_LENGTH, + 'Device Descriptor Rendering Error'); + + this.addMappingAction_(); + } + + /** + * Gets configuration descriptor of current device. + * @return {!Uint8Array} + * @private + */ + async getConfigurationDescriptor_() { + /** @type {device.mojom.UsbControlTransferParams} */ + const usbControlTransferParams = {}; + usbControlTransferParams.type = + device.mojom.UsbControlTransferType.STANDARD; + usbControlTransferParams.recipient = + device.mojom.UsbControlTransferRecipient.DEVICE; + usbControlTransferParams.request = GET_DESCRIPTOR_REQUEST; + usbControlTransferParams.value = (CONFIGURATION_DESCRIPTOR_TYPE << 8); + usbControlTransferParams.index = 0; + let length = CONFIGURATION_DESCRIPTOR_LENGTH; + const timeout = CONTROL_TRANSFER_TIMEOUT_MS; + + await this.usbDeviceProxy_.open(); + + let response = await this.usbDeviceProxy_.controlTransferIn( + usbControlTransferParams, length, timeout); + + this.checkDescriptorGetSuccess_( + response.status, + 'Failed to read the device configuration descriptor to determine ' + + 'the total descriptor length.'); + + const data = new DataView(new Uint8Array(response.data).buffer); + length = data.getUint16(2, true); + // Re-gets the data use the full length. + response = await this.usbDeviceProxy_.controlTransferIn( + usbControlTransferParams, length, timeout); + + this.checkDescriptorGetSuccess_( + response.status, + 'Failed to read the complete configuration descriptor'); + + return new Uint8Array(response.data); + } + + /** + * Renders a view to display configuration descriptor hex data in both tree + * view and raw form. + */ + async renderConfigurationDescriptor() { + const rawData = await this.getConfigurationDescriptor_(); + + this.renderRawDataBytes_(rawData); + + const fields = [ + { + label: 'Length', + size: 1, + formatter: formatByte, + }, + { + label: 'Descriptor Type', + size: 1, + formatter: formatDescriptorType, + }, + { + label: 'Total Length', + size: 2, + formatter: formatShort, + }, + { + label: 'Number of Interfaces', + size: 1, + formatter: formatByte, + }, + { + label: 'Configuration Value', + size: 1, + formatter: formatByte, + }, + { + label: 'Configuration String Index', + size: 1, + formatter: formatByte, + }, + { + label: 'Attribute Bitmap', + size: 1, + formatter: formatBitmap, + }, + { + label: 'Max Power (2mA increments)', + size: 1, + formatter: formatByte, + }, + ]; + + let offset = 0; + + const expectNumInterfaces = rawData[offset + 4]; + + offset = this.renderRawDataTree_( + this.rawDataTreeRoot_, fields, rawData, offset); + + if (offset != CONFIGURATION_DESCRIPTOR_LENGTH) { + this.showError_( + 'Some error(s) occurs during rendering configuration descriptor'); + } + + let indexInterface = 0; + let indexEndpoint = 0; + let indexUnknown = 0; + let expectNumEndpoints = 0; + + while ((offset + 1) < rawData.length) { + // The descriptor length and type byte still exists. + switch (rawData[offset + 1]) { + case INTERFACE_DESCRIPTOR_TYPE: + [offset, expectNumEndpoints] = this.renderInterfaceDescriptor_( + rawData, offset, indexInterface, expectNumEndpoints); + indexInterface++; + break; + case ENDPOINT_DESCRIPTOR_TYPE: + offset = + this.renderEndpointDescriptor_(rawData, offset, indexEndpoint); + indexEndpoint++; + break; + default: + offset = + this.renderUnknownDescriptor_(rawData, offset, indexUnknown); + indexUnknown++; + break; + } + } + + if (expectNumInterfaces != indexInterface) { + this.showError_(`Expected to find ${ + expectNumInterfaces} interface descriptors but only encountered ${ + indexInterface}.`); + } + + if (expectNumEndpoints != indexEndpoint) { + this.showError_(`Expected to find ${ + expectNumEndpoints} interface descriptors but only encountered ${ + indexEndpoint}.`); + } + + assert( + offset === rawData.length, + 'Complete Configuration Descriptor Rendering Error'); + + this.addMappingAction_(); + } + + /** + * Renders a tree item to display indexInterface-th interface descriptor. + * @param {!Uint8Array} rawData + * @param {number} originalOffset + * @param {number} indexInterface + * @param {number} expectNumEndpoints + * @return {number} + * @private + */ + renderInterfaceDescriptor_( + rawData, originalOffset, indexInterface, expectNumEndpoints) { + if (originalOffset + INTERFACE_DESCRIPTOR_LENGTH > rawData.length) { + this.showError_( + `Failed to read the ${indexInterface}-th interface descriptor.`); + } + + const interfaceItem = customTreeItem( + `Interface ${indexInterface}`, + `descriptor-interface-${indexInterface}`); + this.rawDataTreeRoot_.add(interfaceItem); + + const fields = [ + { + label: 'Length', + size: 1, + formatter: formatByte, + }, + { + label: 'Descriptor Type', + size: 1, + formatter: formatDescriptorType, + }, + { + label: 'Interface Number', + size: 1, + formatter: formatByte, + }, + { + label: 'Alternate String', + size: 1, + formatter: formatByte, + }, + { + label: 'Number of Endpoints', + size: 1, + formatter: formatByte, + }, + { + label: 'Interface Class Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Interface Subclass Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Interface Protocol Code', + size: 1, + formatter: formatByte, + }, + { + label: 'Interface String Index', + size: 1, + formatter: formatByte, + }, + ]; + + let offset = originalOffset; + + expectNumEndpoints += rawData[offset + 4]; + + offset = this.renderRawDataTree_( + interfaceItem, fields, rawData, offset, + `descriptor-interface-${indexInterface}`); + + if (offset != originalOffset + INTERFACE_DESCRIPTOR_LENGTH) { + this.showError_(`Some error(s) occurred while rendering ${ + indexInterface}-th interface descriptor.`); + } + + return [offset, expectNumEndpoints]; + } + + /** + * Renders a tree item to display indexEndpoint-th endpoint descriptor. + * @param {!Uint8Array} rawData + * @param {number} originalOffset + * @param {number} indexInterface + * @return {number} + * @private + */ + renderEndpointDescriptor_(rawData, originalOffset, indexEndpoint) { + if (originalOffset + ENDPOINT_DESCRIPTOR_LENGTH > rawData.length) { + this.showError_( + `Failed to read the ${indexEndpoint}-th endpoint descriptor.`); + } + + const endpointItem = customTreeItem( + `Endpoint ${indexEndpoint}`, `descriptor-endpoint-${indexEndpoint}`); + this.rawDataTreeRoot_.add(endpointItem); + + const fields = [ + { + label: 'Length', + size: 1, + formatter: formatByte, + }, + { + label: 'Descriptor Type', + size: 1, + formatter: formatDescriptorType, + }, + { + label: 'EndPoint Address', + size: 1, + formatter: formatByte, + }, + { + label: 'Attribute Bitmap', + size: 1, + formatter: formatBitmap, + }, + { + label: 'Max Packet Size', + size: 2, + formatter: formatShort, + }, + { + label: 'Interval', + size: 1, + formatter: formatByte, + }, + ]; + + let offset = originalOffset; + offset = this.renderRawDataTree_( + endpointItem, fields, rawData, offset, + `descriptor-endpoint-${indexEndpoint}`); + + if (offset != originalOffset + ENDPOINT_DESCRIPTOR_LENGTH) { + this.showError_(`Some error(s) occurred while rendering ${ + indexEndpoint}-th endpoint descriptor.`); + } + + return offset; + } + + /** + * Renders a tree item to display length and type of indexUnknown-th unknown + * descriptor. + * @param {!Uint8Array} rawData + * @param {number} originalOffset + * @param {number} indexInterface + * @return {number} + * @private + */ + renderUnknownDescriptor_(rawData, originalOffset, indexUnknown) { + const length = rawData[originalOffset]; + + if (originalOffset + length > rawData.length) { + this.showError_( + `Failed to read the ${indexUnknown}-th unknown descriptor.`); + return; + } + + const unknownItem = customTreeItem( + `Unknown Descriptor ${indexUnknown}`, + `descriptor-unknown-${indexUnknown}`); + this.rawDataTreeRoot_.add(unknownItem); + + const fields = [ + { + label: 'Length', + size: 1, + formatter: formatByte, + }, + { + label: 'Descriptor Type', + size: 1, + formatter: formatDescriptorType, + }, + ]; + + let offset = originalOffset; + offset = this.renderRawDataTree_( + unknownItem, fields, rawData, offset, + `descriptor-unknown-${indexUnknown}`); + + const rawDataByteElements = this.rawDataElement_.querySelectorAll('span'); + + for (; offset < originalOffset + length; offset++) { + rawDataByteElements[offset].classList.add(`field-offset-${offset}`); + rawDataByteElements[offset].classList.add( + `descriptor-unknown-${indexUnknown}`); + } + + return offset; + } + } + + /** + * Renders a customized TreeItem with the given content and class name. + * @param {string} itemLabel + * @param {string=} opt_className + * @return {!cr.ui.TreeItem} + */ + function customTreeItem(itemLabel, opt_className) { + const item = new cr.ui.TreeItem({ + label: itemLabel, + icon: '', + }); + if (opt_className) { + item.querySelector('.tree-row').classList.add(opt_className); + } + return item; + } + + /** + * Parses one byte to decimal number string. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatByte(rawData, offset) { + return rawData[offset].toString(); + } + + /** + * Parses two bytes to decimal number. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {number} + */ + function parseShort(rawData, offset) { + const data = new DataView(rawData.buffer); + return data.getUint16(offset, true); + } + + /** + * Parses two bytes to decimal number string. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatShort(rawData, offset) { + return parseShort(rawData, offset).toString(); + } + + /** + * Parses two bytes to a hex string. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatTwoBytesToHex(rawData, offset) { + const num = parseShort(rawData, offset); + return `0x${num.toString(16).padStart(4, '0').slice(-4).toUpperCase()}`; + } + + /** + * Parses two bytes to USB version format. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatUsbVersion(rawData, offset) { + return `${rawData[offset + 1]}.${rawData[offset] >> 4}.${ + rawData[offset] & 0x0F}`; + } + + /** + * Parses one byte to a bitmap. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatBitmap(rawData, offset) { + return rawData[offset].toString(2).padStart(8, '0').slice(-8); + } + + /** + * Parses descriptor type to a hex string. + * @param {!Uint8Array} rawData + * @param {number} offset + * @return {string} + */ + function formatDescriptorType(rawData, offset) { + return `0x${ + rawData[offset].toString(16).padStart(2, '0').slice(-2).toUpperCase()}`; + } + + return { + DescriptorPanel, + }; +}); \ No newline at end of file
diff --git a/chrome/browser/resources/usb_internals/devices_page.js b/chrome/browser/resources/usb_internals/devices_page.js index 4ce09539..d5111093 100644 --- a/chrome/browser/resources/usb_internals/devices_page.js +++ b/chrome/browser/resources/usb_internals/devices_page.js
@@ -8,41 +8,344 @@ */ cr.define('devices_page', function() { + const UsbDeviceProxy = device.mojom.UsbDeviceProxy; + /** - * Sets the device collection for the page's device table. - * @param {!Array<!device.mojom.UsbDeviceInfo>} devices + * Page that contains a tab header and a tab panel displaying devices table. */ - function setDevices(devices) { - const tableBody = $('device-list'); - tableBody.innerHTML = ''; + class DevicesPage { + /** + * @param {!device.mojom.UsbDeviceManagerProxy} usbManager + */ + constructor(usbManager) { + /** @private {device.mojom.UsbDeviceManagerProxy} */ + this.usbManager_ = usbManager; - const rowTemplate = document.querySelector('#device-row'); + this.renderDeviceList_(); + } - for (const device of devices) { - const clone = document.importNode(rowTemplate.content, true); + /** + * Sets the device collection for the page's device table. + * @private + */ + async renderDeviceList_() { + const response = await this.usbManager_.getDevices(); - const td = clone.querySelectorAll('td'); + /** @type {!Array<!device.mojom.UsbDeviceInfo>} */ + const devices = response.results; - td[0].textContent = device.busNumber; - td[1].textContent = device.portNumber; - td[2].textContent = toHex_(device.vendorId); - td[3].textContent = toHex_(device.productId); - if (device.manufacturerName) { - td[4].textContent = decodeString16_(device.manufacturerName.data); + const tableBody = $('device-list'); + tableBody.innerHTML = ''; + + const rowTemplate = document.querySelector('#device-row'); + + for (const device of devices) { + const clone = document.importNode(rowTemplate.content, true); + + const td = clone.querySelectorAll('td'); + + td[0].textContent = device.busNumber; + td[1].textContent = device.portNumber; + td[2].textContent = toHex(device.vendorId); + td[3].textContent = toHex(device.productId); + if (device.manufacturerName) { + td[4].textContent = decodeString16(device.manufacturerName.data); + } + if (device.productName) { + td[5].textContent = decodeString16(device.productName.data); + } + if (device.serialNumber) { + td[6].textContent = decodeString16(device.serialNumber.data); + } + + const inspectButton = clone.querySelector('button'); + inspectButton.addEventListener('click', () => { + this.switchToTab_(device); + }); + + tableBody.appendChild(clone); } + } + + /** + * Switches to the device's tab, creating one if necessary. + * @param {!device.mojom.UsbDeviceInfo} device + * @private + */ + switchToTab_(device) { + const tabId = device.guid; + + if (null == $(tabId)) { + const devicePage = new DevicePage(this.usbManager_); + devicePage.renderTab(device); + } + $(tabId).selected = true; + } + } + + /** + * Page that contains a tree view displaying devices detail and can get + * descriptors. + */ + class DevicePage { + /** + * @param {!device.mojom.UsbDeviceManagerProxy} usbManager + */ + constructor(usbManager) { + /** @private {device.mojom.UsbDeviceManagerProxy} */ + this.usbManager_ = usbManager; + + /** @private {boolean} */ + this.showDeviceDescriptor_ = false; + /** @private {boolean} */ + this.showConfigurationDescriptor_ = false; + } + + /** + * Renders a tab to display a tree view showing device's detail information. + * @param {!device.mojom.UsbDeviceInfo} device + * @private + */ + renderTab(device) { + const tabs = document.querySelector('tabs'); + + const tabTemplate = document.querySelector('#tab-template'); + const tabClone = document.importNode(tabTemplate.content, true); + + const tab = tabClone.querySelector('tab'); if (device.productName) { - td[5].textContent = decodeString16_(device.productName.data); + tab.textContent = decodeString16(device.productName.data); + } else { + const vendorId = toHex(device.vendorId).slice(2); + const productId = toHex(device.productId).slice(2); + tab.textContent = `${vendorId}:${productId}`; } - if (device.serialNumber) { - td[6].textContent = decodeString16_(device.serialNumber.data); - } + tab.id = device.guid; - const inspectButton = clone.querySelector('button'); - inspectButton.addEventListener('click', () => { - switchToTab_(device); + tabs.appendChild(tabClone); + cr.ui.decorate('tab', cr.ui.Tab); + + const tabPanels = document.querySelector('tabpanels'); + + const tabPanelTemplate = document.querySelector('#tabpanel-template'); + const tabPanelClone = document.importNode(tabPanelTemplate.content, true); + + /** + * Root of the WebContents tree of current device. + * @type {cr.ui.Tree|null} + */ + const treeViewRoot = tabPanelClone.querySelector('#tree-view'); + cr.ui.decorate(treeViewRoot, cr.ui.Tree); + treeViewRoot.detail = {payload: {}, children: {}}; + // Clear the tree first before populating it with the new content. + treeViewRoot.innerText = ''; + this.renderDeviceTree_(device, treeViewRoot); + + const usbDeviceProxy = new UsbDeviceProxy; + this.usbManager_.getDevice(device.guid, usbDeviceProxy.$.createRequest()); + + const getDeviceDescriptorButton = + tabPanelClone.querySelector('#device-descriptor-button'); + const deviceDescriptorElement = + tabPanelClone.querySelector('.device-descriptor-panel'); + + const deviceDescriptorPanel = new descriptor_panel.DescriptorPanel( + usbDeviceProxy, deviceDescriptorElement); + getDeviceDescriptorButton.addEventListener('click', () => { + this.showDeviceDescriptor_ = !this.showDeviceDescriptor_; + + // Clear the panel before rendering new data. + deviceDescriptorPanel.clearView(); + + if (this.showDeviceDescriptor_) { + deviceDescriptorPanel.renderDeviceDescriptor(); + } }); - tableBody.appendChild(clone); + const getConfigurationDescriptorButton = + tabPanelClone.querySelector('#configuration-descriptor-button'); + const configurationDescriptorElement = + tabPanelClone.querySelector('.configuration-descriptor-panel'); + const configurationDescriptorPanel = new descriptor_panel.DescriptorPanel( + usbDeviceProxy, configurationDescriptorElement); + getConfigurationDescriptorButton.addEventListener('click', () => { + this.showConfigurationDescriptor_ = !this.showConfigurationDescriptor_; + + // Clear the panel before rendering new data. + configurationDescriptorPanel.clearView(); + + if (this.showConfigurationDescriptor_) { + configurationDescriptorPanel.renderConfigurationDescriptor(); + } + }); + + tabPanels.appendChild(tabPanelClone); + cr.ui.decorate('tabpanel', cr.ui.TabPanel); + } + + /** + * Renders a tree to display the device's detail information. + * @param {!device.mojom.UsbDeviceInfo} device + * @param {!cr.ui.Tree} root + * @private + */ + renderDeviceTree_(device, root) { + root.add(customTreeItem(`USB Version: ${device.usbVersionMajor}.${ + device.usbVersionMinor}.${device.usbVersionSubminor}`)); + + root.add(customTreeItem(`Class Code: ${device.classCode}`)); + + root.add(customTreeItem(`Subclass Code: ${device.subclassCode}`)); + + root.add(customTreeItem(`Protocol Code: ${device.protocolCode}`)); + + root.add(customTreeItem(`Port Number: ${device.portNumber}`)); + + root.add(customTreeItem(`Vendor Id: ${toHex(device.vendorId)}`)); + + root.add(customTreeItem(`Product Id: ${toHex(device.productId)}`)); + + root.add(customTreeItem(`Device Version: ${device.deviceVersionMajor}.${ + device.deviceVersionMinor}.${device.deviceVersionSubminor}`)); + + root.add(customTreeItem(`Manufacturer Name: ${ + decodeString16(device.manufacturerName.data)}`)); + + root.add(customTreeItem( + `Product Name: ${decodeString16(device.productName.data)}`)); + + root.add(customTreeItem( + `Serial Number: ${decodeString16(device.serialNumber.data)}`)); + + root.add(customTreeItem( + `WebUSB Landing Page: ${device.webusbLandingPage.url}`)); + + root.add(customTreeItem( + `Active Configuration: ${device.activeConfiguration}`)); + + const configurationsArray = device.configurations; + this.renderConfigurationTreeItem_(configurationsArray, root); + } + + /** + * Renders a tree item to display the device's configurations information. + * @param {!Array<!device.mojom.UsbConfigurationInfo>} configurationsArray + * @param {!cr.ui.TreeItem} root + * @private + */ + renderConfigurationTreeItem_(configurationsArray, root) { + for (const configuration of configurationsArray) { + const configurationItem = + customTreeItem(`Configuration ${configuration.configurationValue}`); + + if (configuration.configurationName) { + configurationItem.add(customTreeItem(`Configuration Name: ${ + decodeString16(configuration.configurationName.data)}`)); + } + + const interfacesArray = configuration.interfaces; + this.renderInterfacesTreeItem_(interfacesArray, configurationItem); + + root.add(configurationItem); + } + } + + /** + * Renders a tree item to display the device's interfaces information. + * @param {!Array<!device.mojom.UsbInterfaceInfo>} interfacesArray + * @param {!cr.ui.TreeItem} root + * @private + */ + renderInterfacesTreeItem_(interfacesArray, root) { + for (const currentInterface of interfacesArray) { + const interfaceItem = + customTreeItem(`Interface ${currentInterface.interfaceNumber}`); + + const alternatesArray = currentInterface.alternates; + this.renderAlternatesTreeItem_(alternatesArray, interfaceItem); + + root.add(interfaceItem); + } + } + + /** + * Renders a tree item to display the device's alternate interfaces + * information. + * @param {!Array<!device.mojom.UsbAlternateInterfaceInfo>} alternatesArray + * @param {!cr.ui.TreeItem} root + * @private + */ + renderAlternatesTreeItem_(alternatesArray, root) { + for (const alternate of alternatesArray) { + const alternateItem = + customTreeItem(`Alternate ${alternate.alternateSetting}`); + + alternateItem.add(customTreeItem(`Class Code: ${alternate.classCode}`)); + + alternateItem.add( + customTreeItem(`Subclass Code: ${alternate.subclassCode}`)); + + alternateItem.add( + customTreeItem(`Protocol Code: ${alternate.protocolCode}`)); + + if (alternate.interfaceName) { + alternateItem.add(customTreeItem(`Interface Name: ${ + decodeString16(alternate.interfaceName.data)}`)); + } + + const endpointsArray = alternate.endpoints; + this.renderEndpointsTreeItem_(endpointsArray, alternateItem); + + root.add(alternateItem); + } + } + + /** + * Renders a tree item to display the device's endpoints information. + * @param {!Array<!device.mojom.UsbEndpointInfo>} endpointsArray + * @param {!cr.ui.TreeItem} root + * @private + */ + renderEndpointsTreeItem_(endpointsArray, root) { + for (const endpoint of endpointsArray) { + let itemLabel = 'Endpoint '; + + itemLabel += endpoint.endpointNumber; + + switch (endpoint.direction) { + case device.mojom.UsbTransferDirection.INBOUND: + itemLabel += ' (INBOUND)'; + break; + case device.mojom.UsbTransferDirection.OUTBOUND: + itemLabel += ' (OUTBOUND)'; + break; + } + + const endpointItem = customTreeItem(itemLabel); + + let usbTransferType = ''; + switch (endpoint.type) { + case device.mojom.UsbTransferType.CONTROL: + usbTransferType = 'CONTROL'; + break; + case device.mojom.UsbTransferType.ISOCHRONOUS: + usbTransferType = 'ISOCHRONOUS'; + break; + case device.mojom.UsbTransferType.BULK: + usbTransferType = 'BULK'; + break; + case device.mojom.UsbTransferType.INTERRUPT: + usbTransferType = 'INTERRUPT'; + break; + } + + endpointItem.add( + customTreeItem(`USB Transfer Type: ${usbTransferType}`)); + + endpointItem.add(customTreeItem(`Packet Size: ${endpoint.packetSize}`)); + + root.add(endpointItem); + } } } @@ -50,9 +353,8 @@ * Parses utf16 coded string. * @param {!mojoBase.mojom.String16} arr * @return {string} - * @private */ - function decodeString16_(arr) { + function decodeString16(arr) { return arr.map(ch => String.fromCodePoint(ch)).join(''); } @@ -60,67 +362,9 @@ * Parses the decimal number to hex format. * @param {number} num * @return {string} - * @private */ - function toHex_(num) { - return '0x' + num.toString(16).padStart(4, '0').slice(-4).toUpperCase(); - } - - /** - * Switches to the device's tab, creating one if necessary. - * @param {!device.mojom.UsbDeviceInfo} device - * @private - */ - function switchToTab_(device) { - const tabId = device.guid; - - if (null == $(tabId)) { - addTab_(device); - } - $(tabId).selected = true; - } - - /** - * Adds a tab to display a tree view showing device's detail information. - * @param {!device.mojom.UsbDeviceInfo} device - * @private - */ - function addTab_(device) { - const tabs = document.querySelector('tabs'); - - const tabTemplate = document.querySelector('#tab-template'); - const tabClone = document.importNode(tabTemplate.content, true); - - const tab = tabClone.querySelector('tab'); - if (device.productName) { - tab.textContent = decodeString16_(device.productName.data); - } else { - tab.textContent = toHex_(device.vendorId).slice(2) + ':' + - toHex_(device.productId).slice(2); - } - tab.id = device.guid; - - tabs.appendChild(tabClone); - cr.ui.decorate('tab', cr.ui.Tab); - - const tabPanels = document.querySelector('tabpanels'); - - const tabPanelTemplate = document.querySelector('#tabpanel-template'); - const tabPanelClone = document.importNode(tabPanelTemplate.content, true); - - /** - * Root of the WebContents tree of current device. - * @type {cr.ui.Tree|null} - */ - const treeViewRoot = tabPanelClone.querySelector('#tree-view'); - cr.ui.decorate(treeViewRoot, cr.ui.Tree); - treeViewRoot.detail = {payload: {}, children: {}}; - // Clear the tree first before populating it with the new content. - treeViewRoot.innerText = ''; - renderDeviceTree_(device, treeViewRoot); - - tabPanels.appendChild(tabPanelClone); - cr.ui.decorate('tabpanel', cr.ui.TabPanel); + function toHex(num) { + return `0x${num.toString(16).padStart(4, '0').slice(-4).toUpperCase()}`; } /** @@ -129,185 +373,15 @@ * @return {!cr.ui.TreeItem} * @private */ - function customTreeItem_(itemLabel) { - const item = new cr.ui.TreeItem({ + function customTreeItem(itemLabel) { + return item = new cr.ui.TreeItem({ label: itemLabel, icon: '', }); - return item; - } - - - /** - * Renders a tree to display the device's detail information. - * @param {!device.mojom.UsbDeviceInfo} device - * @param {!cr.ui.Tree} root - * @private - */ - function renderDeviceTree_(device, root) { - root.add(customTreeItem_( - 'USB Version: ' + device.usbVersionMajor + '.' + - device.usbVersionMinor + '.' + device.usbVersionSubminor)); - - root.add(customTreeItem_('Class Code: ' + device.classCode)); - - root.add(customTreeItem_('Subclass Code: ' + device.subclassCode)); - - root.add(customTreeItem_('Protocol Code: ' + device.protocolCode)); - - root.add(customTreeItem_('Port Number: ' + device.portNumber)); - - root.add(customTreeItem_('Vendor Id: ' + toHex_(device.vendorId))); - - root.add(customTreeItem_('Product Id: ' + toHex_(device.productId))); - - root.add(customTreeItem_( - 'Device Version: ' + device.deviceVersionMajor + ',' + - device.deviceVersionMinor + ',' + device.deviceVersionSubminor)); - - root.add(customTreeItem_( - 'Manufacturer Name: ' + decodeString16_(device.manufacturerName.data))); - - root.add(customTreeItem_( - 'Product Name: ' + decodeString16_(device.productName.data))); - - root.add(customTreeItem_( - 'Serial Number: ' + decodeString16_(device.serialNumber.data))); - - root.add(customTreeItem_( - 'WebUSB Landing Page: ' + device.webusbLandingPage.url)); - - root.add( - customTreeItem_('Active Configuration: ' + device.activeConfiguration)); - - const configurationsArray = device.configurations; - renderConfigurationTreeItem_(configurationsArray, root); - } - - /** - * Renders a tree item to display the device's configurations information. - * @param {!Array<!device.mojom.UsbConfigurationInfo>} configurationsArray - * @param {!cr.ui.TreeItem} root - * @private - */ - function renderConfigurationTreeItem_(configurationsArray, root) { - for (const configuration of configurationsArray) { - const configurationItem = - customTreeItem_('Configuration ' + configuration.configurationValue); - - if (configuration.configurationName) { - configurationItem.add(customTreeItem_( - 'Configuration Name: ' + - decodeString16_(configuration.configurationName.data))); - } - - const interfacesArray = configuration.interfaces; - renderInterfacesTreeItem_(interfacesArray, configurationItem); - - root.add(configurationItem); - } - } - - /** - * Renders a tree item to display the device's interfaces information. - * @param {!Array<!device.mojom.UsbInterfaceInfo>} interfacesArray - * @param {!cr.ui.TreeItem} root - * @private - */ - function renderInterfacesTreeItem_(interfacesArray, root) { - for (const currentInterface of interfacesArray) { - const interfaceItem = - customTreeItem_('Interface ' + currentInterface.interfaceNumber); - - const alternatesArray = currentInterface.alternates; - renderAlternatesTreeItem_(alternatesArray, interfaceItem); - - root.add(interfaceItem); - } - } - - /** - * Renders a tree item to display the device's alternate interfaces - * information. - * @param {!Array<!device.mojom.UsbAlternateInterfaceInfo>} alternatesArray - * @param {!cr.ui.TreeItem} root - * @private - */ - function renderAlternatesTreeItem_(alternatesArray, root) { - for (const alternate of alternatesArray) { - const alternateItem = - customTreeItem_('Alternate ' + alternate.alternateSetting); - - alternateItem.add(customTreeItem_('Class Code: ' + alternate.classCode)); - - alternateItem.add( - customTreeItem_('Subclass Code: ' + alternate.subclassCode)); - - alternateItem.add( - customTreeItem_('Protocol Code: ' + alternate.protocolCode)); - - if (alternate.interfaceName) { - alternateItem.add(customTreeItem_( - 'Interface Name: ' + - decodeString16_(alternate.interfaceName.data))); - } - - const endpointsArray = alternate.endpoints; - renderEndpointsTreeItem_(endpointsArray, alternateItem); - - root.add(alternateItem); - } - } - - /** - * Renders a tree item to display the device's endpoints information. - * @param {!Array<!device.mojom.UsbEndpointInfo>} endpointsArray - * @param {!cr.ui.TreeItem} root - * @private - */ - function renderEndpointsTreeItem_(endpointsArray, root) { - for (const endpoint of endpointsArray) { - let itemLabel = 'Endpoint '; - - itemLabel += endpoint.endpointNumber; - - switch (endpoint.direction) { - case device.mojom.UsbTransferDirection.INBOUND: - itemLabel += ' (INBOUND)'; - break; - case device.mojom.UsbTransferDirection.OUTBOUND: - itemLabel += ' (OUTBOUND)'; - break; - } - - const endpointItem = customTreeItem_(itemLabel); - - let usbTransferType = ''; - switch (endpoint.type) { - case device.mojom.UsbTransferType.CONTROL: - usbTransferType = 'CONTROL'; - break; - case device.mojom.UsbTransferType.ISOCHRONOUS: - usbTransferType = 'ISOCHRONOUS'; - break; - case device.mojom.UsbTransferType.BULK: - usbTransferType = 'BULK'; - break; - case device.mojom.UsbTransferType.INTERRUPT: - usbTransferType = 'INTERRUPT'; - break; - } - - endpointItem.add( - customTreeItem_('USB Transfer Type: ' + usbTransferType)); - - endpointItem.add(customTreeItem_('Packet Size: ' + endpoint.packetSize)); - - root.add(endpointItem); - } } return { - setDevices: setDevices, + DevicePage, + DevicesPage, }; }); \ No newline at end of file
diff --git a/chrome/browser/resources/usb_internals/usb_internals.css b/chrome/browser/resources/usb_internals/usb_internals.css index af12290b..996b14b4 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.css +++ b/chrome/browser/resources/usb_internals/usb_internals.css
@@ -32,3 +32,76 @@ .action-failure { color: red; } + +/* device page */ +.descriptor-button button { + width: 100%; +} + +/* descriptor panel */ +.device-descriptor-panel, +.configuration-descriptor-panel { + display: flex; + overflow: auto; +} + +#raw-data, +#raw-data-tree-view { + flex: 1 0; +} + +#raw-data { + font-size: 14px; + line-height: 250%; + white-space: pre; +} + +@media screen and (min-width: 1200px) { + #raw-data span:nth-child(16n)::after { + content: '\A'; + } +} + +@media screen and (min-width: 600px) and (max-width: 1199px) { + #raw-data span:nth-child(8n)::after { + content: '\A'; + } +} + +@media screen and (min-width: 300px) and (max-width: 599px) { + #raw-data span:nth-child(4n)::after { + content: '\A'; + } +} + +@media screen and (min-width: 150px) and (max-width: 299px) { + #raw-data span:nth-child(2n)::after { + content: '\A'; + } +} + +#raw-data span { + padding-inline-end: .5em; + padding-inline-start: .5em; +} + +#raw-data .selected-field { + background: red; +} + +#raw-data .hovered-field { + background: yellow; +} + +.tree-row.hover { + background-color: hsl(214, 91%, 97%); + border-color: hsl(214, 91%, 85%); + z-index: 1; +} + +error { + color: red; + display: block; + font-size: 16px; + padding-inline-start: 20px; +} \ No newline at end of file
diff --git a/chrome/browser/resources/usb_internals/usb_internals.html b/chrome/browser/resources/usb_internals/usb_internals.html index d1c93db30..310bb26 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.html +++ b/chrome/browser/resources/usb_internals/usb_internals.html
@@ -30,6 +30,7 @@ <script src="device_manager_test.mojom-lite.js"></script> <script src="usb_internals.mojom-lite.js"></script> + <script src="descriptor_panel.js"></script> <script src="devices_page.js"></script> </head> @@ -137,9 +138,32 @@ <template id="tabpanel-template"> <tabpanel> <tree id="tree-view"></tree> + <div class="descriptor-button"> + <button id="device-descriptor-button">Get Device Descriptor</button> + </div> + <div class="device-descriptor-panel"></div> + <div class="descriptor-button"> + <button id="configuration-descriptor-button"> + Get Configuration Descriptor + </button> + </div> + <div class="configuration-descriptor-panel"></div> </tabpanel> </template> + <template id="descriptor-panel-template"> + <tree id="raw-data-tree-view"></tree> + <div id="raw-data"></div> + </template> + + <template id="raw-data-byte"> + <span></span> + </template> + + <template id="error"> + <error></error> + </template> + <script src="usb_internals.js"></script> </body>
diff --git a/chrome/browser/resources/usb_internals/usb_internals.js b/chrome/browser/resources/usb_internals/usb_internals.js index accc7df..2ad4f6e 100644 --- a/chrome/browser/resources/usb_internals/usb_internals.js +++ b/chrome/browser/resources/usb_internals/usb_internals.js
@@ -21,19 +21,15 @@ this.usbManagerTest_ = new device.mojom.UsbDeviceManagerTestProxy; pageHandler.bindTestInterface(this.usbManagerTest_.$.createRequest()); - cr.ui.decorate('tabbox', cr.ui.TabBox); - - this.refreshDeviceList(); + /** @private {devices_page.DevicesPage} */ + this.devicesPage_ = new devices_page.DevicesPage(this.usbManager_); $('add-test-device-form').addEventListener('submit', (event) => { this.addTestDevice(event); }); this.refreshTestDeviceList(); - } - async refreshDeviceList() { - const response = await this.usbManager_.getDevices(); - devices_page.setDevices(response.results); + cr.ui.decorate('tabbox', cr.ui.TabBox); } async refreshTestDeviceList() {
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index d1fbd87..1ecdf4c1 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -86,6 +86,9 @@ namespace { +// Language code used to check features run in English in the US. +const char kEnUSLanguageCode[] = "en-US"; + // Signifies a locally constructed resource, i.e. not from grit/. const int kLocalResource = -1; @@ -841,10 +844,15 @@ return; } - MaybeServeSearchSuggestions(callback); + // Currently Vasco search suggestions are only available for en-US + // users. If this restriction is expanded or removed in the future this + // check must be changed. + if (one_google_bar_service_->language_code() == kEnUSLanguageCode) { + MaybeServeSearchSuggestions(callback); - search_suggest_requests_.emplace_back(base::TimeTicks::Now()); - search_suggest_service_->Refresh(); + search_suggest_requests_.emplace_back(base::TimeTicks::Now()); + search_suggest_service_->Refresh(); + } return; }
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_data.cc b/chrome/browser/search/one_google_bar/one_google_bar_data.cc index a5738e3..d08d1ba 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_data.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_data.cc
@@ -19,7 +19,8 @@ lhs.in_head_style == rhs.in_head_style && lhs.after_bar_script == rhs.after_bar_script && lhs.end_of_body_html == rhs.end_of_body_html && - lhs.end_of_body_script == rhs.end_of_body_script; + lhs.end_of_body_script == rhs.end_of_body_script && + lhs.language_code == rhs.language_code; } bool operator!=(const OneGoogleBarData& lhs, const OneGoogleBarData& rhs) {
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_data.h b/chrome/browser/search/one_google_bar/one_google_bar_data.h index f37cbb39..3e6889f7 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_data.h +++ b/chrome/browser/search/one_google_bar/one_google_bar_data.h
@@ -27,6 +27,9 @@ std::string after_bar_script; std::string end_of_body_html; std::string end_of_body_script; + + // User's language code returned by the server + std::string language_code; }; bool operator==(const OneGoogleBarData& lhs, const OneGoogleBarData& rhs);
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc index 2cc2a38..31f502d 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc
@@ -99,6 +99,12 @@ return base::nullopt; } + const base::Value* language = nullptr; + std::string language_code; + if (update->Get("language_code", &language)) { + language_code = language->GetString(); + } + const base::DictionaryValue* one_google_bar = nullptr; if (!update->GetDictionary("ogb", &one_google_bar)) { DVLOG(1) << "Parse error: no ogb"; @@ -106,6 +112,7 @@ } OneGoogleBarData result; + result.language_code = language_code; if (!safe_html::GetHtml(*one_google_bar, "html", &result.bar_html)) { DVLOG(1) << "Parse error: no html";
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc index a56c1e5..368ecc1 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl_unittest.cc
@@ -364,3 +364,22 @@ last_request_headers().HasHeader(signin::kChromeConnectedHeader)); #endif } + +TEST_F(OneGoogleBarLoaderImplTest, ParsesLanguageCode) { + SetUpResponseWithData(R"json({"update": { "language_code": "en-US", "ogb": { + "html": { "private_do_not_access_or_else_safe_html_wrapped_value": "" }, + "page_hooks": {} + }}})json"); + + base::MockCallback<OneGoogleBarLoader::OneGoogleCallback> callback; + one_google_bar_loader()->Load(callback.Get()); + + base::Optional<OneGoogleBarData> data; + base::RunLoop loop; + EXPECT_CALL(callback, Run(OneGoogleBarLoader::Status::OK, _)) + .WillOnce(DoAll(SaveArg<1>(&data), Quit(&loop))); + loop.Run(); + + ASSERT_TRUE(data.has_value()); + EXPECT_THAT(data->language_code, Eq("en-US")); +}
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service.cc b/chrome/browser/search/one_google_bar/one_google_bar_service.cc index e2cf94a..43cba45e 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_service.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_service.cc
@@ -70,6 +70,11 @@ observers_.RemoveObserver(observer); } +void OneGoogleBarService::SetLanguageCodeForTesting( + const std::string& language_code) { + language_code_ = language_code; +} + void OneGoogleBarService::SigninStatusChanged() { // If we have cached data, clear it and notify observers. if (one_google_bar_data_.has_value()) { @@ -85,6 +90,7 @@ // notify observers of the finished load (attempt). if (status != OneGoogleBarLoader::Status::TRANSIENT_ERROR) { one_google_bar_data_ = data; + language_code_ = data.has_value() ? data->language_code : std::string(); } NotifyObservers(); }
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service.h b/chrome/browser/search/one_google_bar/one_google_bar_service.h index 825cb209..377422a 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_service.h +++ b/chrome/browser/search/one_google_bar/one_google_bar_service.h
@@ -46,6 +46,11 @@ OneGoogleBarLoader* loader_for_testing() { return loader_.get(); } + std::string language_code() { return language_code_; } + + // Used for testing. + void SetLanguageCodeForTesting(const std::string& language_code); + private: class SigninObserver; @@ -63,6 +68,8 @@ base::ObserverList<OneGoogleBarServiceObserver, true>::Unchecked observers_; base::Optional<OneGoogleBarData> one_google_bar_data_; + + std::string language_code_; }; #endif // CHROME_BROWSER_SEARCH_ONE_GOOGLE_BAR_ONE_GOOGLE_BAR_SERVICE_H_
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc index 10628c9..4c2fc24d 100644 --- a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc +++ b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc
@@ -247,3 +247,33 @@ service()->RemoveObserver(&observer); } + +TEST_F(OneGoogleBarServiceTest, UpdatesLanguageCode) { + ASSERT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); + + // Request a refresh. That should arrive at the loader. + service()->Refresh(); + EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + + // Fulfill it. + OneGoogleBarData data; + data.language_code = "en-US"; + loader()->RespondToAllCallbacks(OneGoogleBarLoader::Status::OK, data); + EXPECT_THAT(service()->one_google_bar_data(), Eq(data)); + EXPECT_THAT(service()->language_code(), "en-US"); + + // Request another refresh. + service()->Refresh(); + EXPECT_THAT(loader()->GetCallbackCount(), Eq(1u)); + + // For now, the old data should still be there. + EXPECT_THAT(service()->one_google_bar_data(), Eq(data)); + EXPECT_THAT(service()->language_code(), "en-US"); + + // Fulfill the second request, the language code should now be updated. + OneGoogleBarData other_data; + other_data.language_code = "en-UK"; + loader()->RespondToAllCallbacks(OneGoogleBarLoader::Status::OK, other_data); + EXPECT_THAT(service()->one_google_bar_data(), Eq(other_data)); + EXPECT_THAT(service()->language_code(), "en-UK"); +}
diff --git a/chrome/browser/send_tab_to_self/desktop_notification_handler.cc b/chrome/browser/send_tab_to_self/desktop_notification_handler.cc index f9142ff..351c33f 100644 --- a/chrome/browser/send_tab_to_self/desktop_notification_handler.cc +++ b/chrome/browser/send_tab_to_self/desktop_notification_handler.cc
@@ -47,7 +47,8 @@ base::UTF8ToUTF16(url.host()), url, message_center::NotifierId(url), optional_fields, /*delegate=*/nullptr); NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( - NotificationHandler::Type::SEND_TAB_TO_SELF, notification); + NotificationHandler::Type::SEND_TAB_TO_SELF, notification, + /*metadata=*/nullptr); } void DesktopNotificationHandler::DismissEntries( @@ -103,7 +104,8 @@ base::UTF8ToUTF16(url.host()), url, message_center::NotifierId(url), message_center::RichNotificationData(), /*delegate=*/nullptr); NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( - NotificationHandler::Type::SEND_TAB_TO_SELF, notification); + NotificationHandler::Type::SEND_TAB_TO_SELF, notification, + /*metadata=*/nullptr); } void DesktopNotificationHandler::DisplayFailureMessage() {
diff --git a/chrome/browser/send_tab_to_self/desktop_notification_handler_unittest.cc b/chrome/browser/send_tab_to_self/desktop_notification_handler_unittest.cc new file mode 100644 index 0000000..c964648 --- /dev/null +++ b/chrome/browser/send_tab_to_self/desktop_notification_handler_unittest.cc
@@ -0,0 +1,211 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/send_tab_to_self/desktop_notification_handler.h" + +#include <vector> + +#include "base/bind.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/notifications/notification_common.h" +#include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" +#include "chrome/browser/notifications/notification_handler.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" +#include "chrome/test/base/browser_with_test_window_test.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" +#include "components/send_tab_to_self/send_tab_to_self_sync_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/image/image.h" +#include "ui/message_center/public/cpp/notification.h" + +#include "ui/base/resource/resource_bundle.h" +#include "ui/strings/grit/ui_strings.h" + +namespace send_tab_to_self { + +namespace { + +const char kDesktopNotificationOrigin[] = "https://www.google.com"; +const char kDesktopNotificationId[] = "notification_id"; +const char kDesktopNotificationGuid[] = "guid"; +const char kDesktopNotificationTitle[] = "title"; +const char kDesktopNotificationDeviceInfo[] = "device_info"; +const char kDesktopNotificationDeviceInfoWithPrefix[] = + "Shared from device_info"; + +class SendTabToSelfModelMock : public SendTabToSelfModel { + public: + SendTabToSelfModelMock() = default; + ~SendTabToSelfModelMock() override = default; + + MOCK_METHOD3(AddEntry, + const SendTabToSelfEntry*(const GURL&, + const std::string&, + base::Time navigation_time)); + MOCK_METHOD1(DeleteEntry, void(const std::string&)); + MOCK_METHOD1(DismissEntry, void(const std::string&)); + + MOCK_CONST_METHOD0(GetAllGuids, std::vector<std::string>()); + MOCK_METHOD0(DeleteAllEntries, void()); + MOCK_CONST_METHOD1(GetEntryByGUID, SendTabToSelfEntry*(const std::string&)); + + void AddObserver(SendTabToSelfModelObserver* observer) {} + void RemoveObserver(SendTabToSelfModelObserver* observer) {} +}; + +// Mock a SendTabToSelfSyncService to get SendTabToSelfModelMock +class SendTabToSelfSyncServiceMock : public SendTabToSelfSyncService { + public: + SendTabToSelfSyncServiceMock() = default; + ~SendTabToSelfSyncServiceMock() override = default; + + SendTabToSelfModel* GetSendTabToSelfModel() override { + return &send_tab_to_self_model_mock_; + } + + protected: + SendTabToSelfModelMock send_tab_to_self_model_mock_; +}; + +// Matcher to compare Notification object +MATCHER_P(EqualNotification, e, "") { + return arg.type() == e.type() && arg.id() == e.id() && + arg.title() == e.title() && arg.message() == e.message() && + arg.origin_url() == e.origin_url(); +} + +std::unique_ptr<KeyedService> BuildTestSendTabToSelfSyncService( + content::BrowserContext* context) { + return std::make_unique<SendTabToSelfSyncServiceMock>(); +} + +class NotificationDisplayServiceMock : public NotificationDisplayService { + public: + NotificationDisplayServiceMock() = default; + ~NotificationDisplayServiceMock() override = default; + + using NotificationDisplayService::DisplayedNotificationsCallback; + + MOCK_METHOD3(DisplayMockImpl, + void(NotificationHandler::Type, + const message_center::Notification&, + NotificationCommon::Metadata*)); + void Display( + NotificationHandler::Type notification_type, + const message_center::Notification& notification, + std::unique_ptr<NotificationCommon::Metadata> metadata) override { + DisplayMockImpl(notification_type, notification, metadata.get()); + } + + MOCK_METHOD2(Close, void(NotificationHandler::Type, const std::string&)); + MOCK_METHOD1(GetDisplayed, void(DisplayedNotificationsCallback)); +}; + +std::unique_ptr<KeyedService> BuildTestNotificationDisplayService( + content::BrowserContext* context) { + return std::make_unique<NotificationDisplayServiceMock>(); +} + +class DesktopNotificationHandlerTest : public BrowserWithTestWindowTest { + public: + DesktopNotificationHandlerTest() = default; + ~DesktopNotificationHandlerTest() override = default; + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + + display_service_mock_ = static_cast<NotificationDisplayServiceMock*>( + NotificationDisplayServiceFactory::GetInstance() + ->SetTestingFactoryAndUse( + profile(), + base::BindRepeating(&BuildTestNotificationDisplayService))); + + SendTabToSelfSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), base::BindRepeating(&BuildTestSendTabToSelfSyncService)); + + model_mock_ = static_cast<SendTabToSelfModelMock*>( + SendTabToSelfSyncServiceFactory::GetForProfile(profile()) + ->GetSendTabToSelfModel()); + } + + protected: + Profile* profile_; + SendTabToSelfModelMock* model_mock_; + NotificationDisplayServiceMock* display_service_mock_; +}; + +TEST_F(DesktopNotificationHandlerTest, DisplayNewEntry) { + const GURL& url = GURL(kDesktopNotificationOrigin); + message_center::RichNotificationData optional_fields; + optional_fields.never_timeout = true; + message_center::Notification notification( + message_center::NOTIFICATION_TYPE_SIMPLE, kDesktopNotificationGuid, + base::ASCIIToUTF16(kDesktopNotificationTitle), + base::ASCIIToUTF16(kDesktopNotificationDeviceInfoWithPrefix), + gfx::Image(), base::UTF8ToUTF16(url.host()), url, + message_center::NotifierId(url), optional_fields, /*delegate=*/nullptr); + + SendTabToSelfEntry entry(kDesktopNotificationGuid, url, + kDesktopNotificationTitle, base::Time::Now(), + base::Time::Now(), kDesktopNotificationDeviceInfo); + + DesktopNotificationHandler handler(profile()); + EXPECT_CALL(*display_service_mock_, + DisplayMockImpl(NotificationHandler::Type::SEND_TAB_TO_SELF, + EqualNotification(notification), nullptr)) + .WillOnce(::testing::Return()); + + handler.DisplayNewEntry(&entry); +} + +TEST_F(DesktopNotificationHandlerTest, DismissEntries) { + DesktopNotificationHandler handler(profile()); + EXPECT_CALL(*display_service_mock_, + Close(NotificationHandler::Type::SEND_TAB_TO_SELF, + kDesktopNotificationGuid)) + .WillOnce(::testing::Return()); + + std::vector<std::string> guids; + guids.push_back(kDesktopNotificationGuid); + handler.DismissEntries(guids); +} + +TEST_F(DesktopNotificationHandlerTest, CloseHandler) { + DesktopNotificationHandler handler(profile()); + + EXPECT_CALL(*model_mock_, DismissEntry(kDesktopNotificationId)) + .WillOnce(::testing::Return()); + + handler.OnClose(profile(), GURL(kDesktopNotificationOrigin), + kDesktopNotificationId, /*by_user=*/0, base::DoNothing()); + + EXPECT_CALL(*model_mock_, DismissEntry(kDesktopNotificationId)) + .WillOnce(::testing::Return()); + + handler.OnClose(profile(), GURL(kDesktopNotificationOrigin), + kDesktopNotificationId, /*by_user=*/1, base::DoNothing()); +} + +TEST_F(DesktopNotificationHandlerTest, ClickHandler) { + DesktopNotificationHandler handler(profile()); + + EXPECT_CALL(*display_service_mock_, + Close(NotificationHandler::Type::SEND_TAB_TO_SELF, + kDesktopNotificationId)) + .WillOnce(::testing::Return()); + EXPECT_CALL(*model_mock_, DeleteEntry(kDesktopNotificationId)) + .WillOnce(::testing::Return()); + + handler.OnClick(profile(), GURL(kDesktopNotificationOrigin), + kDesktopNotificationId, /*action_index=*/1, + /*reply=*/base::nullopt, base::DoNothing()); +} + +} // namespace + +} // namespace send_tab_to_self
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_client_service.cc b/chrome/browser/send_tab_to_self/send_tab_to_self_client_service.cc index 99630c7..f3f1862 100644 --- a/chrome/browser/send_tab_to_self/send_tab_to_self_client_service.cc +++ b/chrome/browser/send_tab_to_self/send_tab_to_self_client_service.cc
@@ -36,11 +36,11 @@ void SendTabToSelfClientService::EntriesAddedRemotely( const std::vector<const SendTabToSelfEntry*>& new_entries) { - // TODO(tgupta):Figure out whether it is better to pass in one entry at - // a time or to pass all the entries at once. - for (std::unique_ptr<ReceivingUiHandler>& handler : - registry_->GetHandlers()) { - handler->DisplayNewEntry(new_entries[0]); + for (const SendTabToSelfEntry* entry : new_entries) { + for (std::unique_ptr<ReceivingUiHandler>& handler : + registry_->GetHandlers()) { + handler->DisplayNewEntry(entry); + } } }
diff --git a/chrome/browser/signin/identity_manager_factory.cc b/chrome/browser/signin/identity_manager_factory.cc index b959db1..271777e 100644 --- a/chrome/browser/signin/identity_manager_factory.cc +++ b/chrome/browser/signin/identity_manager_factory.cc
@@ -88,7 +88,6 @@ GaiaCookieManagerServiceFactory::GetForProfile(profile), AccountConsistencyModeManager::GetMethodForProfile(profile)); #endif - AccountFetcherServiceFactory::GetForProfile(profile); signin_manager->Initialize(g_browser_process->local_state()); return signin_manager; }
diff --git a/chrome/browser/signin/signin_error_notifier_ash.cc b/chrome/browser/signin/signin_error_notifier_ash.cc index 03cf1b95..15fe137a 100644 --- a/chrome/browser/signin/signin_error_notifier_ash.cc +++ b/chrome/browser/signin/signin_error_notifier_ash.cc
@@ -146,7 +146,8 @@ // Update or add the notification. NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void SigninErrorNotifier::HandleSecondaryAccountError( @@ -182,7 +183,8 @@ // Update or add the notification. NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void SigninErrorNotifier::HandleSecondaryAccountReauthNotificationClick(
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.cc b/chrome/browser/signin/signin_profile_attributes_updater.cc index 835d9ca..e2f7406 100644 --- a/chrome/browser/signin/signin_profile_attributes_updater.cc +++ b/chrome/browser/signin/signin_profile_attributes_updater.cc
@@ -51,8 +51,6 @@ return; } - std::string old_gaia_id = entry->GetGAIAId(); - if (identity_manager_->HasPrimaryAccount()) { CoreAccountInfo account_info = identity_manager_->GetPrimaryAccountInfo(); entry->SetAuthInfo(account_info.gaia, @@ -63,9 +61,6 @@ if (!signin_util::IsForceSigninEnabled()) entry->SetIsSigninRequired(false); } - - if (old_gaia_id != entry->GetGAIAId()) - ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager); } void SigninProfileAttributesUpdater::OnErrorChanged() {
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc index cb866c7f..1f37b3dd 100644 --- a/chrome/browser/speech/speech_recognizer.cc +++ b/chrome/browser/speech/speech_recognizer.cc
@@ -43,7 +43,9 @@ // SpeechRecognizerDelegate via a weak pointer that is only ever referenced from // the UI thread. class SpeechRecognizer::EventListener - : public base::RefCountedThreadSafe<SpeechRecognizer::EventListener>, + : public base::RefCountedThreadSafe< + SpeechRecognizer::EventListener, + content::BrowserThread::DeleteOnIOThread>, public content::SpeechRecognitionEventListener { public: EventListener(const base::WeakPtr<SpeechRecognizerDelegate>& delegate, @@ -59,7 +61,9 @@ void StopOnIOThread(); private: - friend class base::RefCountedThreadSafe<SpeechRecognizer::EventListener>; + friend struct content::BrowserThread::DeleteOnThread< + content::BrowserThread::IO>; + friend class base::DeleteHelper<SpeechRecognizer::EventListener>; ~EventListener() override; void NotifyRecognitionStateChanged(SpeechRecognizerStatus new_state);
diff --git a/chrome/browser/status_icons/desktop_notification_balloon.cc b/chrome/browser/status_icons/desktop_notification_balloon.cc index 306bfb3..0460e84b 100644 --- a/chrome/browser/status_icons/desktop_notification_balloon.cc +++ b/chrome/browser/status_icons/desktop_notification_balloon.cc
@@ -51,5 +51,5 @@ new message_center::NotificationDelegate()); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, notification, /*metadata=*/nullptr); }
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc index 168b9ab..445ecb7 100644 --- a/chrome/browser/sync/sync_error_notifier_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -127,6 +127,7 @@ ash::kNotificationWarningIcon, message_center::SystemNotificationWarningLevel::WARNING); - display_service->Display(NotificationHandler::Type::TRANSIENT, *notification); + display_service->Display(NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); notification_displayed_ = true; }
diff --git a/chrome/browser/sync/test/integration/DEPS b/chrome/browser/sync/test/integration/DEPS deleted file mode 100644 index eefc17b..0000000 --- a/chrome/browser/sync/test/integration/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+jingle/glue/network_service_config_test_util.h", -]
diff --git a/chrome/browser/sync/test/integration/preferences_helper.cc b/chrome/browser/sync/test/integration/preferences_helper.cc index a45f9ae..e12dc931 100644 --- a/chrome/browser/sync/test/integration/preferences_helper.cc +++ b/chrome/browser/sync/test/integration/preferences_helper.cc
@@ -74,6 +74,12 @@ GetVerifierPrefs()->SetString(pref_name, new_value); } +void ClearPref(int index, const char* pref_name) { + GetPrefs(index)->ClearPref(pref_name); + if (test()->use_verifier()) + GetVerifierPrefs()->ClearPref(pref_name); +} + void ChangeFilePathPref(int index, const char* pref_name, const base::FilePath& new_value) { @@ -207,6 +213,23 @@ return true; } +bool ClearedPrefMatches(const char* pref_name) { + if (test()->use_verifier()) { + if (GetVerifierPrefs()->GetUserPrefValue(pref_name)) { + return false; + } + } + + for (int i = 0; i < test()->num_clients(); ++i) { + if (GetPrefs(i)->GetUserPrefValue(pref_name)) { + DVLOG(1) << "Preference " << pref_name << " isn't cleared in" + << " profile " << i << "."; + return false; + } + } + return true; +} + bool FilePathPrefMatches(const char* pref_name) { base::FilePath reference_value; if (test()->use_verifier()) { @@ -298,3 +321,10 @@ bool StringPrefMatchChecker::IsExitConditionSatisfied() { return preferences_helper::StringPrefMatches(GetPath()); } + +ClearedPrefMatchChecker::ClearedPrefMatchChecker(const char* path) + : PrefMatchChecker(path) {} + +bool ClearedPrefMatchChecker::IsExitConditionSatisfied() { + return preferences_helper::ClearedPrefMatches(GetPath()); +}
diff --git a/chrome/browser/sync/test/integration/preferences_helper.h b/chrome/browser/sync/test/integration/preferences_helper.h index f2e971a..1026688 100644 --- a/chrome/browser/sync/test/integration/preferences_helper.h +++ b/chrome/browser/sync/test/integration/preferences_helper.h
@@ -63,6 +63,11 @@ const char* pref_name, const std::string& new_value); +// Clears the value of the preference with name |pref_name| in the profile with +// index |index|. Also changes its value in |verifier| if DisableVerifier() +// hasn't been called. +void ClearPref(int index, const char* pref_name); + // Changes the value of the file path preference with name |pref_name| in the // profile with index |index| to |new_value|. Also changes its value in // |verifier| if DisableVerifier() hasn't been called. @@ -174,4 +179,13 @@ bool IsExitConditionSatisfied() override; }; +// Matcher that blocks until the specified pref is cleared on all clients. +class ClearedPrefMatchChecker : public PrefMatchChecker { + public: + explicit ClearedPrefMatchChecker(const char* path); + + // PrefMatchChecker implementation. + bool IsExitConditionSatisfied() override; +}; + #endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_PREFERENCES_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc index c3415eb..d401d8c5 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -82,7 +82,7 @@ if (HasAuthError(service())) { return true; } - if (service()->passphrase_required_reason_for_test() == + if (service()->GetPassphraseRequiredReasonForTest() == syncer::REASON_DECRYPTION) { LOG(FATAL) << "A passphrase is required for decryption but was not provided. " @@ -598,7 +598,7 @@ << snap.model_neutral_state().num_updates_downloaded_total << ", passphrase_required_reason: " << syncer::PassphraseRequiredReasonToString( - service()->passphrase_required_reason_for_test()) + service()->GetPassphraseRequiredReasonForTest()) << ", notifications_enabled: " << status.notifications_enabled << ", service_is_active: " << service()->IsSyncFeatureActive(); } else {
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index e00d5b0..5ca49cd 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -67,7 +67,6 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "google_apis/gaia/gaia_urls.h" -#include "jingle/glue/network_service_config_test_util.h" #include "net/base/port_util.h" #include "net/dns/mock_host_resolver.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" @@ -146,7 +145,7 @@ bool IsEncryptionComplete(const ProfileSyncService* service) { return service->GetUserSettings()->IsEncryptEverythingEnabled() && - !service->encryption_pending(); + !service->IsEncryptionPendingForTest(); } // Helper class to wait for encryption to complete.
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc index 51dcfed..97d959e 100644 --- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -1892,7 +1892,7 @@ ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); ASSERT_TRUE(IsEncryptionComplete(0)); ASSERT_TRUE(IsEncryptionComplete(1)); - ASSERT_TRUE(GetSyncService(1)->IsPassphraseRequired()); + ASSERT_TRUE(GetSyncService(1)->GetUserSettings()->IsPassphraseRequired()); // Client 0 adds bookmarks between the first two and between the second two. ASSERT_NE(nullptr, AddURL(0, 1, IndexedURLTitle(3), GURL(IndexedURL(3))));
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc index e6f9ea5..10f3ab60 100644 --- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -25,6 +25,7 @@ using preferences_helper::ChangeIntegerPref; using preferences_helper::ChangeListPref; using preferences_helper::ChangeStringPref; +using preferences_helper::ClearPref; using preferences_helper::GetPrefs; using preferences_helper::GetRegistry; using testing::Eq; @@ -135,6 +136,16 @@ ASSERT_TRUE(StringPrefMatchChecker(prefs::kHomePage).Wait()); } +IN_PROC_BROWSER_TEST_P(TwoClientPreferencesSyncTest, E2E_ENABLED(ClearPref)) { + ASSERT_TRUE(SetupSync()); + ChangeStringPref(0, prefs::kHomePage, "http://news.google.com"); + ASSERT_TRUE(StringPrefMatchChecker(prefs::kHomePage).Wait()); + + ClearPref(0, prefs::kHomePage); + + ASSERT_TRUE(ClearedPrefMatchChecker(prefs::kHomePage).Wait()); +} + IN_PROC_BROWSER_TEST_P(TwoClientPreferencesSyncTest, E2E_ENABLED(ComplexPrefs)) { ASSERT_TRUE(SetupSync());
diff --git a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc index 544cfab..9eebf752 100644 --- a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
@@ -196,7 +196,7 @@ : SingleClientStatusChangeChecker(service) {} bool IsExitConditionSatisfied() override { - return !service()->IsDataTypeControllerRunning(syncer::PREFERENCES); + return !service()->IsDataTypeControllerRunningForTest(syncer::PREFERENCES); } std::string GetDebugMessage() const override {
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index 2b4c00c..4dd33763 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -35,6 +35,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/common/buildflags.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/grit/theme_resources.h" #include "components/grit/components_scaled_resources.h" @@ -336,16 +337,17 @@ // there. const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch("install-colors-r") && - command_line->HasSwitch("install-colors-g") && - command_line->HasSwitch("install-colors-b")) { + if (command_line->HasSwitch(switches::kInstallAutogeneratedTheme)) { + std::string value = + command_line->GetSwitchValueASCII(switches::kInstallAutogeneratedTheme); + std::vector<std::string> rgb = base::SplitString( + value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (rgb.size() != 3) + return; int r, g, b; - base::StringToInt(command_line->GetSwitchValueASCII("install-colors-r"), - &r); - base::StringToInt(command_line->GetSwitchValueASCII("install-colors-g"), - &g); - base::StringToInt(command_line->GetSwitchValueASCII("install-colors-b"), - &b); + base::StringToInt(rgb[0], &r); + base::StringToInt(rgb[1], &g); + base::StringToInt(rgb[2], &b); BuildFromColor(SkColorSetRGB(r, g, b)); } }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 015a529..f29cbc5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2496,6 +2496,10 @@ "views/extensions/extension_keybinding_registry_views.cc", "views/extensions/extension_keybinding_registry_views.h", "views/extensions/extension_uninstall_dialog_view.cc", + "views/extensions/extensions_menu_view.cc", + "views/extensions/extensions_menu_view.h", + "views/extensions/extensions_toolbar_button.cc", + "views/extensions/extensions_toolbar_button.h", "views/extensions/pwa_confirmation_view.cc", "views/extensions/pwa_confirmation_view.h", "views/extensions/web_app_info_image_source.cc",
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index ac04345d..deb6cdc 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -95,26 +95,36 @@ } } -void AppListClientImpl::OpenSearchResult(const std::string& result_id, - int event_flags) { +void AppListClientImpl::OpenSearchResult( + const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) { if (!search_controller_) return; + ChromeSearchResult* result = search_controller_->FindSearchResult(result_id); - if (result) { - search_controller_->OpenResult(result, event_flags); + if (!result) + return; - // Send training signal to search controller. - search_controller_->Train( - result_id, app_list::RankingItemTypeFromSearchResult(*result)); + search_controller_->OpenResult(result, event_flags); + + // Send training signal to search controller. + search_controller_->Train(result_id, + app_list::RankingItemTypeFromSearchResult(*result)); + + if (launch_type == ash::mojom::AppListLaunchType::kAppSearchResult) { + // Log the AppResult (either in the search result page, or in chip form in + // AppsGridView) to the UKM system. + app_launch_event_logger_.OnSuggestionChipOrSearchBoxClicked( + result_id, suggestion_index, static_cast<int>(launched_from)); } -} -void AppListClientImpl::LogSearchClick( - const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) { - app_launch_event_logger_.OnSuggestionChipOrSearchBoxClicked( - result_id, suggestion_index, static_cast<int>(launched_from)); + if (launched_from == + ash::mojom::AppListLaunchedFrom::kLaunchedFromSearchBox) { + RecordSearchResultOpenTypeHistogram(result->GetSearchResultType()); + } } void AppListClientImpl::InvokeSearchResultAction(const std::string& result_id,
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.h b/chrome/browser/ui/app_list/app_list_client_impl.h index 1692366..96a829ac 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.h +++ b/chrome/browser/ui/app_list/app_list_client_impl.h
@@ -48,10 +48,11 @@ // ash::mojom::AppListClient: void StartSearch(const base::string16& trimmed_query) override; - void OpenSearchResult(const std::string& result_id, int event_flags) override; - void LogSearchClick(const std::string& result_id, - int suggestion_index, - ash::mojom::AppListLaunchedFrom launched_from) override; + void OpenSearchResult(const std::string& result_id, + int event_flags, + ash::mojom::AppListLaunchedFrom launched_from, + ash::mojom::AppListLaunchType launch_type, + int suggestion_index) override; void InvokeSearchResultAction(const std::string& result_id, int action_index, int event_flags) override;
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.cc index 3107011..98d1c04 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.cc +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/ui/app_list/search/answer_card/answer_card_result.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" -#include "chrome/browser/ui/app_list/search/search_util.h" namespace app_list { @@ -32,7 +31,10 @@ list_controller_->OpenURL(profile_, search_result_url_, ui::PAGE_TRANSITION_GENERATED, ui::DispositionFromEventFlags(event_flags)); - RecordHistogram(ANSWER_CARD); +} + +SearchResultType AnswerCardResult::GetSearchResultType() const { + return ANSWER_CARD; } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h index 4aae534..9b83a2c9 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_result.h
@@ -9,6 +9,7 @@ #include <string> #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "url/gurl.h" class AppListControllerDelegate; @@ -29,6 +30,8 @@ void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; + const GURL& search_result_url() const { return search_result_url_; } private:
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc index d99e5590a..391a9cf 100644 --- a/chrome/browser/ui/app_list/search/app_result.cc +++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -43,4 +43,8 @@ set_relevance(1 / (1 + delta.InSecondsF() / kSecondsInWeek)); } +SearchResultType AppResult::GetSearchResultType() const { + return SEARCH_RESULT_TYPE_BOUNDARY; +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/app_result.h b/chrome/browser/ui/app_list/search/app_result.h index f49c97f..15182c7 100644 --- a/chrome/browser/ui/app_list/search/app_result.h +++ b/chrome/browser/ui/app_list/search/app_result.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" class AppListControllerDelegate; class Profile; @@ -32,6 +33,8 @@ const std::string& app_id() const { return app_id_; } + SearchResultType GetSearchResultType() const override; + protected: AppResult(Profile* profile, const std::string& app_id,
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc index 178e6128..2bfd6c1 100644 --- a/chrome/browser/ui/app_list/search/app_service_app_result.cc +++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -88,6 +88,23 @@ context_menu_->GetMenuModel(std::move(callback)); } +SearchResultType AppServiceAppResult::GetSearchResultType() const { + switch (app_type_) { + case apps::mojom::AppType::kArc: + return PLAY_STORE_APP; + case apps::mojom::AppType::kBuiltIn: + return INTERNAL_APP; + case apps::mojom::AppType::kCrostini: + return CROSTINI_APP; + case apps::mojom::AppType::kExtension: + case apps::mojom::AppType::kWeb: + return EXTENSION_APP; + default: + NOTREACHED(); + return SEARCH_RESULT_TYPE_BOUNDARY; + } +} + AppContextMenu* AppServiceAppResult::GetAppContextMenu() { return context_menu_.get(); }
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.h b/chrome/browser/ui/app_list/search/app_service_app_result.h index fd7619671..9d71233b 100644 --- a/chrome/browser/ui/app_list/search/app_service_app_result.h +++ b/chrome/browser/ui/app_list/search/app_service_app_result.h
@@ -7,6 +7,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" class AppListControllerDelegate; @@ -26,6 +27,7 @@ // ChromeSearchResult overrides: void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; + SearchResultType GetSearchResultType() const override; AppContextMenu* GetAppContextMenu() override; // AppContextMenuDelegate overrides:
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.cc index dacef22..994dafd 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.cc
@@ -125,4 +125,16 @@ SetIcon(icon); } +SearchResultType ArcAppDataSearchResult::GetSearchResultType() const { + switch (data_->type) { + case arc::mojom::AppDataResultType::PERSON: + return APP_DATA_RESULT_PERSON; + case arc::mojom::AppDataResultType::NOTE_DOCUMENT: + return APP_DATA_RESULT_NOTE_DOCUMENT; + default: + NOTREACHED(); + return SEARCH_RESULT_TYPE_BOUNDARY; + } +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.h index 33678753..47071f8 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/common/app.mojom.h" class AppListControllerDelegate; @@ -31,6 +32,7 @@ // ChromeSearchResult: void GetContextMenuModel(GetMenuModelCallback callback) override; void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; private: const std::string& launch_intent_uri() const {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc index 8c8b425..eadb8b6 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
@@ -57,4 +57,8 @@ observer_->OnVisibilityChanged(id(), visibility); } +SearchResultType ArcAppReinstallAppResult::GetSearchResultType() const { + return PLAY_STORE_REINSTALL_APP; +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h index 14ce37e..7887df2 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/common/app.mojom.h" #include "ui/gfx/image/image_skia.h" @@ -38,6 +39,7 @@ // ChromeSearchResult: void Open(int event_flags) override; void OnVisibilityChanged(bool visibility) override; + SearchResultType GetSearchResultType() const override; private: // Observer passed in constructor. not owned.
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc index 2622baa..60b7d44 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider_unittest.cc
@@ -106,6 +106,9 @@ // set_id is protected in chromesearchresult. ChromeSearchResult::set_id(str); } + app_list::SearchResultType GetSearchResultType() const override { + return app_list::SEARCH_RESULT_TYPE_BOUNDARY; + } }; } // namespace
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc index 0bbc6d5c..d231352 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" -#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -57,11 +56,14 @@ ArcAppShortcutSearchResult::~ArcAppShortcutSearchResult() = default; void ArcAppShortcutSearchResult::Open(int event_flags) { - RecordHistogram(PLAY_STORE_APP_SHORTCUT); arc::LaunchAppShortcutItem(profile_, GetAppId(), data_->shortcut_id, list_controller_->GetAppListDisplayId()); } +SearchResultType ArcAppShortcutSearchResult::GetSearchResultType() const { + return PLAY_STORE_APP_SHORTCUT; +} + void ArcAppShortcutSearchResult::OnAppImageUpdated( const std::string& app_id, const gfx::ImageSkia& image) {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h index 1783891..c292371 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/app_icon_loader_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/common/app.mojom.h" #include "ui/gfx/image/image_skia.h" @@ -34,6 +35,7 @@ // ChromeSearchResult: void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; private: // AppIconLoaderDelegate:
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc index e112ea91..9e5a76c 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_playstore_app_context_menu.h" -#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/common/app.mojom.h" @@ -134,14 +133,12 @@ ArcPlayStoreSearchResult::~ArcPlayStoreSearchResult() = default; void ArcPlayStoreSearchResult::Open(int event_flags) { - if (!LaunchIntent(install_intent_uri().value(), - list_controller_->GetAppListDisplayId())) { - return; - } + LaunchIntent(install_intent_uri().value(), + list_controller_->GetAppListDisplayId()); +} - // Open the installing page of this result in Play Store. - RecordHistogram(is_instant_app() ? PLAY_STORE_INSTANT_APP - : PLAY_STORE_UNINSTALLED_APP); +SearchResultType ArcPlayStoreSearchResult::GetSearchResultType() const { + return is_instant_app() ? PLAY_STORE_INSTANT_APP : PLAY_STORE_UNINSTALLED_APP; } void ArcPlayStoreSearchResult::GetContextMenuModel(
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h index e8a37ca..527182d 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
@@ -13,6 +13,7 @@ #include "base/optional.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/common/app.mojom.h" class AppListControllerDelegate; @@ -36,6 +37,7 @@ // ChromeSearchResult overrides: void GetContextMenuModel(GetMenuModelCallback callback) override; void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; // app_list::AppContextMenuDelegate overrides: void ExecuteLaunchCommand(int event_flags) override;
diff --git a/chrome/browser/ui/app_list/search/arc_app_result.cc b/chrome/browser/ui/app_list/search/arc_app_result.cc index df94f58c..bc1f68a 100644 --- a/chrome/browser/ui/app_list/search/arc_app_result.cc +++ b/chrome/browser/ui/app_list/search/arc_app_result.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_context_menu.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" -#include "chrome/browser/ui/app_list/search/search_util.h" namespace { const char kArcAppPrefix[] = "arc://"; @@ -78,16 +77,16 @@ context_menu_->GetMenuModel(std::move(callback)); } +SearchResultType ArcAppResult::GetSearchResultType() const { + return PLAY_STORE_APP; +} + AppContextMenu* ArcAppResult::GetAppContextMenu() { return context_menu_.get(); } void ArcAppResult::Launch(int event_flags, arc::UserInteractionType interaction) { - // Record the search metric if the result is not a suggested app. - if (display_type() != ash::SearchResultDisplayType::kRecommendation) - RecordHistogram(APP_SEARCH_RESULT); - arc::LaunchApp(profile(), app_id(), event_flags, interaction, controller()->GetAppListDisplayId()); }
diff --git a/chrome/browser/ui/app_list/search/arc_app_result.h b/chrome/browser/ui/app_list/search/arc_app_result.h index 7038d518..1752bd4 100644 --- a/chrome/browser/ui/app_list/search/arc_app_result.h +++ b/chrome/browser/ui/app_list/search/arc_app_result.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/app_icon_loader_delegate.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/arc/metrics/arc_metrics_constants.h" class AppListControllerDelegate; @@ -33,6 +34,7 @@ // ChromeSearchResult overrides: void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; + SearchResultType GetSearchResultType() const override; // AppContextMenuDelegate overrides: void ExecuteLaunchCommand(int event_flags) override;
diff --git a/chrome/browser/ui/app_list/search/chrome_search_result.h b/chrome/browser/ui/app_list/search/chrome_search_result.h index b218830..f519fa9 100644 --- a/chrome/browser/ui/app_list/search/chrome_search_result.h +++ b/chrome/browser/ui/app_list/search/chrome_search_result.h
@@ -13,6 +13,7 @@ #include "ash/public/interfaces/app_list.mojom.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_list_model_updater.h" +#include "chrome/browser/ui/app_list/search/search_util.h" namespace app_list { class AppContextMenu; @@ -134,6 +135,9 @@ // OmniboxResult overrides it to return AutocompleteMatch::Type. virtual int GetSubType() const; + // Get the type of the result, used in metrics. + virtual app_list::SearchResultType GetSearchResultType() const = 0; + protected: // These id setters should be called in derived class constructors only. void set_id(const std::string& id) { metadata_->id = id; }
diff --git a/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.cc b/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.cc index 58867801..a659f096 100644 --- a/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.cc +++ b/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.cc
@@ -65,4 +65,8 @@ weak_ptr_factory_.GetWeakPtr())); } +SearchResultType CrostiniRepositorySearchResult::GetSearchResultType() const { + return CROSTINI_APP; +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.h b/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.h index d289cd4..7b1c852d 100644 --- a/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.h +++ b/chrome/browser/ui/app_list/search/crostini/crostini_repository_search_result.h
@@ -11,6 +11,7 @@ #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" class Profile; @@ -23,6 +24,7 @@ // ChromeSearchResult overrides: void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; private: void OnOpen(const crostini::LinuxPackageInfo& package);
diff --git a/chrome/browser/ui/app_list/search/crostini_app_result.cc b/chrome/browser/ui/app_list/search/crostini_app_result.cc index 457d8189..765e330 100644 --- a/chrome/browser/ui/app_list/search/crostini_app_result.cc +++ b/chrome/browser/ui/app_list/search/crostini_app_result.cc
@@ -57,6 +57,10 @@ Open(event_flags); } +SearchResultType CrostiniAppResult::GetSearchResultType() const { + return CROSTINI_APP; +} + void CrostiniAppResult::OnAppImageUpdated(const std::string& app_id, const gfx::ImageSkia& image) { const gfx::Size icon_size(
diff --git a/chrome/browser/ui/app_list/search/crostini_app_result.h b/chrome/browser/ui/app_list/search/crostini_app_result.h index 37f2dc9a..224504a 100644 --- a/chrome/browser/ui/app_list/search/crostini_app_result.h +++ b/chrome/browser/ui/app_list/search/crostini_app_result.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "chrome/browser/ui/app_icon_loader_delegate.h" #include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" class CrostiniAppContextMenu; class CrostiniAppIconLoader; @@ -31,6 +32,7 @@ void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; void ExecuteLaunchCommand(int event_flags) override; + SearchResultType GetSearchResultType() const override; // AppIconLoaderDelegate overrides: void OnAppImageUpdated(const std::string& app_id,
diff --git a/chrome/browser/ui/app_list/search/extension_app_result.cc b/chrome/browser/ui/app_list/search/extension_app_result.cc index c175c47..adc728a 100644 --- a/chrome/browser/ui/app_list/search/extension_app_result.cc +++ b/chrome/browser/ui/app_list/search/extension_app_result.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/extension_app_context_menu.h" #include "chrome/browser/ui/app_list/md_icon_normalizer.h" -#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/browser/ui/extensions/extension_enable_flow.h" #include "chrome/common/extensions/extension_metrics.h" #include "extensions/browser/extension_registry.h" @@ -80,10 +79,8 @@ return; // Record the search metrics if the ChromeSearchResult is not a suggested app. - if (display_type() != ash::SearchResultDisplayType::kRecommendation) { - RecordHistogram(APP_SEARCH_RESULT); + if (display_type() != ash::SearchResultDisplayType::kRecommendation) extensions::RecordAppListSearchLaunch(extension); - } controller()->ActivateApp( profile(), extension, @@ -99,6 +96,10 @@ context_menu_->GetMenuModel(std::move(callback)); } +SearchResultType ExtensionAppResult::GetSearchResultType() const { + return EXTENSION_APP; +} + void ExtensionAppResult::StartObservingExtensionRegistry() { DCHECK(!extension_registry_);
diff --git a/chrome/browser/ui/app_list/search/extension_app_result.h b/chrome/browser/ui/app_list/search/extension_app_result.h index 6d521fb..2718084 100644 --- a/chrome/browser/ui/app_list/search/extension_app_result.h +++ b/chrome/browser/ui/app_list/search/extension_app_result.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "chrome/browser/extensions/chrome_app_icon_delegate.h" #include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" #include "extensions/browser/extension_icon_image.h" #include "extensions/browser/extension_registry_observer.h" @@ -41,6 +42,7 @@ // ChromeSearchResult overrides: void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; + SearchResultType GetSearchResultType() const override; private: void StartObservingExtensionRegistry();
diff --git a/chrome/browser/ui/app_list/search/internal_app_result.cc b/chrome/browser/ui/app_list/search/internal_app_result.cc index 8cda11f..b55b4f67 100644 --- a/chrome/browser/ui/app_list/search/internal_app_result.cc +++ b/chrome/browser/ui/app_list/search/internal_app_result.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/ui/app_list/app_context_menu.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h" -#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/favicon/core/favicon_server_fetcher_params.h" #include "components/favicon/core/large_icon_service.h" #include "components/favicon_base/fallback_icon_style.h" @@ -72,10 +71,6 @@ } void InternalAppResult::Open(int event_flags) { - // Record the search metric if the result is not a suggested app. - if (display_type() != DisplayType::kRecommendation) - RecordHistogram(APP_SEARCH_RESULT); - RecordOpenHistogram(id()); if (id() == kInternalAppIdContinueReading && @@ -184,6 +179,10 @@ context_menu_->GetMenuModel(std::move(callback)); } +SearchResultType InternalAppResult::GetSearchResultType() const { + return INTERNAL_APP; +} + AppContextMenu* InternalAppResult::GetAppContextMenu() { return context_menu_.get(); }
diff --git a/chrome/browser/ui/app_list/search/internal_app_result.h b/chrome/browser/ui/app_list/search/internal_app_result.h index 56f9068e..82ece7c 100644 --- a/chrome/browser/ui/app_list/search/internal_app_result.h +++ b/chrome/browser/ui/app_list/search/internal_app_result.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/task/cancelable_task_tracker.h" #include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/favicon_base/favicon_types.h" #include "url/gurl.h" @@ -44,6 +45,7 @@ // ChromeSearchResult overrides: void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; + SearchResultType GetSearchResultType() const override; // AppContextMenuDelegate overrides: void ExecuteLaunchCommand(int event_flags) override;
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc index 59217b2..8c0fc656 100644 --- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc +++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.cc
@@ -62,12 +62,14 @@ } void LauncherSearchResult::Open(int event_flags) { - RecordHistogram(LAUNCHER_SEARCH_PROVIDER_RESULT); - Service* service = Service::Get(profile_); service->OnOpenResult(extension_->id(), item_id_); } +SearchResultType LauncherSearchResult::GetSearchResultType() const { + return LAUNCHER_SEARCH_PROVIDER_RESULT; +} + void LauncherSearchResult::OnIconImageChanged( LauncherSearchIconImageLoader* image_loader) { DCHECK_EQ(image_loader, icon_image_loader_.get());
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h index 602ece9..0a8ce79 100644 --- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h +++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h
@@ -13,6 +13,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" #include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "extensions/common/extension.h" #include "url/gurl.h" @@ -31,7 +32,10 @@ error_reporter); ~LauncherSearchResult() override; std::unique_ptr<LauncherSearchResult> Duplicate() const; + + // ChromeSearchResult overrides: void Open(int event_flags) override; + SearchResultType GetSearchResultType() const override; void OnIconImageChanged(LauncherSearchIconImageLoader* image_loader) override; void OnBadgeIconImageChanged(
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.cc b/chrome/browser/ui/app_list/search/omnibox_result.cc index 044e15d2..8f3d2b4 100644 --- a/chrome/browser/ui/app_list/search/omnibox_result.cc +++ b/chrome/browser/ui/app_list/search/omnibox_result.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" -#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/grit/generated_resources.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/omnibox/browser/autocomplete_controller.h" @@ -162,7 +161,6 @@ OmniboxResult::~OmniboxResult() = default; void OmniboxResult::Open(int event_flags) { - RecordHistogram(OMNIBOX_SEARCH_RESULT); RecordOmniboxResultHistogram(); list_controller_->OpenURL(profile_, match_.destination_url, match_.transition, ui::DispositionFromEventFlags(event_flags)); @@ -188,6 +186,55 @@ return static_cast<int>(match_.type); } +SearchResultType OmniboxResult::GetSearchResultType() const { + switch (match_.type) { + case AutocompleteMatchType::URL_WHAT_YOU_TYPED: + return OMNIBOX_URL_WHAT_YOU_TYPED; + case AutocompleteMatchType::HISTORY_URL: { + BookmarkModel* bookmark_model = + BookmarkModelFactory::GetForBrowserContext(profile_); + if (bookmark_model && + bookmark_model->IsBookmarked(match_.destination_url)) { + return OMNIBOX_BOOKMARK; + } + return OMNIBOX_RECENTLY_VISITED_WEBSITE; + } + case AutocompleteMatchType::HISTORY_TITLE: + return OMNIBOX_RECENT_DOC_IN_DRIVE; + case AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED: + return OMNIBOX_WEB_QUERY; + case AutocompleteMatchType::SEARCH_HISTORY: + case AutocompleteMatchType::SEARCH_SUGGEST: + case AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED: + return OMNIBOX_HISTORY; + + case AutocompleteMatchType::HISTORY_KEYWORD: + case AutocompleteMatchType::NAVSUGGEST: + case AutocompleteMatchType::SEARCH_SUGGEST_ENTITY: + case AutocompleteMatchType::SEARCH_SUGGEST_TAIL: + case AutocompleteMatchType::SEARCH_SUGGEST_PROFILE: + case AutocompleteMatchType::SEARCH_OTHER_ENGINE: + case AutocompleteMatchType::CONTACT_DEPRECATED: + case AutocompleteMatchType::BOOKMARK_TITLE: + case AutocompleteMatchType::NAVSUGGEST_PERSONALIZED: + case AutocompleteMatchType::CALCULATOR: + case AutocompleteMatchType::CLIPBOARD_URL: + case AutocompleteMatchType::VOICE_SUGGEST: + case AutocompleteMatchType::PHYSICAL_WEB_DEPRECATED: + case AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW_DEPRECATED: + case AutocompleteMatchType::EXTENSION_APP_DEPRECATED: + case AutocompleteMatchType::TAB_SEARCH_DEPRECATED: + case AutocompleteMatchType::DOCUMENT_SUGGESTION: + case AutocompleteMatchType::PEDAL: + case AutocompleteMatchType::CLIPBOARD_TEXT: + case AutocompleteMatchType::CLIPBOARD_IMAGE: + case AutocompleteMatchType::NUM_TYPES: + case AutocompleteMatchType::HISTORY_BODY: + NOTREACHED(); + return SEARCH_RESULT_TYPE_BOUNDARY; + } +} + void OmniboxResult::UpdateIcon() { BookmarkModel* bookmark_model = BookmarkModelFactory::GetForBrowserContext(profile_);
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.h b/chrome/browser/ui/app_list/search/omnibox_result.h index 7746b6f..c54aada 100644 --- a/chrome/browser/ui/app_list/search/omnibox_result.h +++ b/chrome/browser/ui/app_list/search/omnibox_result.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "components/omnibox/browser/autocomplete_match.h" class AppListControllerDelegate; @@ -39,6 +40,7 @@ void Open(int event_flags) override; void InvokeAction(int action_index, int event_flags) override; int GetSubType() const override; + SearchResultType GetSearchResultType() const override; private: void UpdateIcon();
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc index 01825e2..dded19b 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
@@ -14,13 +14,11 @@ namespace app_list { -using SearchResultType = ash::SearchResultType; - // Given a |ChromeSearchResult| representing an omnibox result, convert it based // on the subtype specified by |ChromeSearchResult::GetSubType|. Any // unanticipated subtypes are converted into |RankingItemType::kOmniboxGeneric|. RankingItemType ExpandOmniboxType(const ChromeSearchResult& result) { - if (result.result_type() != SearchResultType::kOmnibox) { + if (result.result_type() != ash::SearchResultType::kOmnibox) { NOTREACHED(); return RankingItemType::kUnknown; } @@ -66,24 +64,24 @@ false); switch (result.result_type()) { - case SearchResultType::kInstalledApp: - case SearchResultType::kInternalApp: + case ash::SearchResultType::kInstalledApp: + case ash::SearchResultType::kInternalApp: return RankingItemType::kApp; - case SearchResultType::kOmnibox: + case ash::SearchResultType::kOmnibox: if (expand_omnibox_types) return ExpandOmniboxType(result); return RankingItemType::kOmniboxGeneric; - case SearchResultType::kLauncher: + case ash::SearchResultType::kLauncher: return RankingItemType::kFile; - case SearchResultType::kUnknown: - case SearchResultType::kPlayStoreApp: - case SearchResultType::kInstantApp: - case SearchResultType::kWebStoreApp: - case SearchResultType::kAnswerCard: - case SearchResultType::kPlayStoreReinstallApp: - case SearchResultType::kWebStoreSearch: + case ash::SearchResultType::kUnknown: + case ash::SearchResultType::kPlayStoreApp: + case ash::SearchResultType::kInstantApp: + case ash::SearchResultType::kWebStoreApp: + case ash::SearchResultType::kAnswerCard: + case ash::SearchResultType::kPlayStoreReinstallApp: + case ash::SearchResultType::kWebStoreSearch: return RankingItemType::kIgnored; - case SearchResultType::kArcAppShortcut: + case ash::SearchResultType::kArcAppShortcut: return RankingItemType::kArcAppShortcut; } }
diff --git a/chrome/browser/ui/app_list/search/search_util.cc b/chrome/browser/ui/app_list/search/search_util.cc index e984a9e..28cd705 100644 --- a/chrome/browser/ui/app_list/search/search_util.cc +++ b/chrome/browser/ui/app_list/search/search_util.cc
@@ -13,7 +13,12 @@ namespace app_list { -void RecordHistogram(SearchResultType type) { +void RecordSearchResultOpenTypeHistogram(SearchResultType type) { + if (type == SEARCH_RESULT_TYPE_BOUNDARY) { + NOTREACHED(); + return; + } + UMA_HISTOGRAM_ENUMERATION( kAppListSearchResultOpenTypeHistogram, type, SEARCH_RESULT_TYPE_BOUNDARY); }
diff --git a/chrome/browser/ui/app_list/search/search_util.h b/chrome/browser/ui/app_list/search/search_util.h index 860567fe..5fd44823 100644 --- a/chrome/browser/ui/app_list/search/search_util.h +++ b/chrome/browser/ui/app_list/search/search_util.h
@@ -6,14 +6,15 @@ #define CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_UTIL_H_ namespace app_list { - -// The type of the chrome search result. This is used for logging so do not -// change the order of this enum. +// The type of the ChromeSearchResult. This is used for logging so do not +// change the order of this enum. If you add to this enum update +// AppListSearchResult in enums.xml. enum SearchResultType { - // A result that forwards an omnibox search result. - OMNIBOX_SEARCH_RESULT, - // An app result. - APP_SEARCH_RESULT, + // A result that forwards an omnibox search result. Use or create OMNIBOX_* + // instead (Deprecated). + OMNIBOX_SEARCH_RESULT_DEPRECATED, + // An app result. Use or create platform specific types below (Deprecated). + APP_SEARCH_RESULT_DEPRECATED, // A search result from the webstore (Deprecated). WEBSTORE_SEARCH_RESULT_DEPRECATED, // A result that opens a webstore search (Deprecated) @@ -22,7 +23,7 @@ SEARCH_PEOPLE_SEARCH_RESULT_DEPRECATED, // A result that opens a suggestion (Deprecated). SUGGESTIONS_SEARCH_RESULT_DEPRECATED, - // A result that is provided by the custom launcher search provider. + // A result which is either a local file or drive file. LAUNCHER_SEARCH_PROVIDER_RESULT, // A result that is an uninstalled app from a Play Store app search. PLAY_STORE_UNINSTALLED_APP, @@ -30,14 +31,42 @@ PLAY_STORE_INSTANT_APP, // A result that is an answer card. ANSWER_CARD, - // A result that open a specific activity in an app installed from Play Store. + // A result that opens a specific activity in an app installed from Play + // Store. PLAY_STORE_APP_SHORTCUT, + // A result that is a URL. + OMNIBOX_URL_WHAT_YOU_TYPED, + // A result which is a bookmark. + OMNIBOX_BOOKMARK, + // A result which is a recently visited website. + OMNIBOX_RECENTLY_VISITED_WEBSITE, + // A result which is a recently used doc in drive. + OMNIBOX_RECENT_DOC_IN_DRIVE, + // A result which is a web query. + OMNIBOX_WEB_QUERY, + // A result which was a web query that was previously searched. + OMNIBOX_HISTORY, + // An app result which is an installed playstore app. + PLAY_STORE_APP, + // An app result which is an app that was installed on another device. + PLAY_STORE_REINSTALL_APP, + // An app result which is an internal app (files, settings, etc). + INTERNAL_APP, + // An app result which is an extension. + EXTENSION_APP, + // A Crostini App Result. + CROSTINI_APP, + // An app result which is a quick action in settings. + SETTINGS_SHORTCUT, + // An ArcAppDataSearchResult which is a person from contacts. + APP_DATA_RESULT_PERSON, + // An ArcAppDataSearchResult which is a note document. + APP_DATA_RESULT_NOTE_DOCUMENT, // Boundary is always last. SEARCH_RESULT_TYPE_BOUNDARY }; -// Record a UMA histogram. -void RecordHistogram(SearchResultType type); +void RecordSearchResultOpenTypeHistogram(SearchResultType type); } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.cc b/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.cc index 579e0981..5416ab4 100644 --- a/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.cc +++ b/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.cc
@@ -49,4 +49,8 @@ std::move(callback).Run(nullptr); } +SearchResultType SettingsShortcutResult::GetSearchResultType() const { + return SETTINGS_SHORTCUT; +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.h b/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.h index 3ba8855..474b60d 100644 --- a/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.h +++ b/chrome/browser/ui/app_list/search/settings_shortcut/settings_shortcut_result.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" class Profile; @@ -27,6 +28,7 @@ // SearchResult overrides: void Open(int event_flags) override; void GetContextMenuModel(GetMenuModelCallback callback) override; + SearchResultType GetSearchResultType() const override; private: Profile* const profile_;
diff --git a/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc b/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc index 9f00090..1a9f5a64c 100644 --- a/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc +++ b/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc
@@ -20,9 +20,11 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "chrome/browser/ui/app_list/search/chrome_search_result.h" #include "chrome/browser/ui/app_list/search/search_provider.h" #include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h" #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h" #include "testing/gtest/include/gtest/gtest.h" @@ -53,6 +55,9 @@ // ChromeSearchResult overrides: void Open(int event_flags) override {} void InvokeAction(int action_index, int event_flags) override {} + SearchResultType GetSearchResultType() const override { + return app_list::SEARCH_RESULT_TYPE_BOUNDARY; + } // For reference equality testing. (Addresses cannot be used to test reference // equality because it is possible that an object will be allocated at the
diff --git a/chrome/browser/ui/ash/assistant/assistant_setup.cc b/chrome/browser/ui/ash/assistant/assistant_setup.cc index cee0021..83ec501 100644 --- a/chrome/browser/ui/ash/assistant/assistant_setup.cc +++ b/chrome/browser/ui/ash/assistant/assistant_setup.cc
@@ -151,7 +151,8 @@ message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void AssistantSetup::SyncActivityControlState() {
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 1fd6af2..bb15f7da 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -701,7 +701,8 @@ message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(GetProfile()) - ->Display(NotificationHandler::Type::TRANSIENT, *notification); + ->Display(NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } Profile* ChromeScreenshotGrabber::GetProfile() {
diff --git a/chrome/browser/ui/ash/network/tether_notification_presenter.cc b/chrome/browser/ui/ash/network/tether_notification_presenter.cc index 879797c..9d4b492 100644 --- a/chrome/browser/ui/ash/network/tether_notification_presenter.cc +++ b/chrome/browser/ui/ash/network/tether_notification_presenter.cc
@@ -319,7 +319,8 @@ std::unique_ptr<message_center::Notification> notification) { showing_notification_id_ = notification->id(); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } void TetherNotificationPresenter::OpenSettingsAndRemoveNotification(
diff --git a/chrome/browser/ui/blocked_content/blocked_window_params.h b/chrome/browser/ui/blocked_content/blocked_window_params.h index 26857e6..00917fb 100644 --- a/chrome/browser/ui/blocked_content/blocked_window_params.h +++ b/chrome/browser/ui/blocked_content/blocked_window_params.h
@@ -7,7 +7,7 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "content/public/common/referrer.h" -#include "third_party/blink/public/web/window_features.mojom.h" +#include "third_party/blink/public/mojom/window_features/window_features.mojom.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h" #include "url/origin.h"
diff --git a/chrome/browser/ui/blocked_content/popup_blocker.h b/chrome/browser/ui/blocked_content/popup_blocker.h index 8298d95..1cb99b9 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker.h +++ b/chrome/browser/ui/blocked_content/popup_blocker.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_H_ #include "base/optional.h" -#include "third_party/blink/public/web/window_features.mojom.h" +#include "third_party/blink/public/mojom/window_features/window_features.mojom.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h"
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc index ef63b4e..5366f7f 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -48,8 +48,7 @@ constexpr char kTabUnderVisibleTime[] = "Tab.TabUnder.VisibleTime"; constexpr char kTabUnderVisibleTimeBefore[] = "Tab.TabUnder.VisibleTimeBefore"; constexpr char kPopupToTabUnder[] = "Tab.TabUnder.PopupToTabUnderTime"; -constexpr char kTabUnderActionOTR[] = "Tab.TabUnderAction.OTR"; -constexpr char kTabUnderActionNonOTR[] = "Tab.TabUnderAction.NonOTR"; +constexpr char kTabUnderAction[] = "Tab.TabUnderAction"; class PopupOpenerTabHelperTest : public ChromeRenderViewHostTestHarness { public: @@ -375,43 +374,6 @@ DISALLOW_COPY_AND_ASSIGN(BlockTabUnderTest); }; -// Parameterized by a boolean which determines if an incognito profile should be -// used. -class BlockTabUnderIncognitoTest : public BlockTabUnderTest, - public testing::WithParamInterface<bool> { - public: - BlockTabUnderIncognitoTest() {} - ~BlockTabUnderIncognitoTest() override {} - - content::BrowserContext* CreateBrowserContext() override { - original_profile_ = ChromeRenderViewHostTestHarness::CreateBrowserContext(); - incognito_profile_ = - static_cast<Profile*>(original_profile_)->GetOffTheRecordProfile(); - return original_profile_; - } - - content::BrowserContext* GetBrowserContext() override { - return GetParam() ? incognito_profile_ : original_profile_; - } - - const char* GetActionHistogram() const { - return GetParam() ? kTabUnderActionOTR : kTabUnderActionNonOTR; - } - - private: - // Owned by the original profile. - content::BrowserContext* incognito_profile_ = nullptr; - - // Owned by the RenderViewHostTestHarness. - content::BrowserContext* original_profile_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(BlockTabUnderIncognitoTest); -}; - -INSTANTIATE_TEST_SUITE_P(, - BlockTabUnderIncognitoTest, - testing::Values(true, false)); - TEST_F(BlockTabUnderTest, SimpleTabUnder_IsBlocked) { EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); SimulatePopup(); @@ -531,11 +493,11 @@ ExpectUIShown(true); } -TEST_P(BlockTabUnderIncognitoTest, +TEST_F(BlockTabUnderTest, MultipleRedirectAttempts_AreBlockedAndLogsActionMetrics) { EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); histogram_tester()->ExpectUniqueSample( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kStarted), 1); SimulatePopup(); @@ -545,21 +507,21 @@ EXPECT_FALSE(NavigateAndCommitWithoutGesture(blocked_url)); histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kStarted), 4); histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kBlocked), 3); histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kDidTabUnder), 3); - histogram_tester()->ExpectTotalCount(GetActionHistogram(), 10); + histogram_tester()->ExpectTotalCount(kTabUnderAction, 10); } -TEST_P(BlockTabUnderIncognitoTest, ClickThroughAction) { +TEST_F(BlockTabUnderTest, ClickThroughAction) { EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); histogram_tester()->ExpectUniqueSample( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kStarted), 1); SimulatePopup(); @@ -580,12 +542,12 @@ static_cast<int>(ListItemPosition::kLastItem), 1); #endif histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kClickedThrough), 1); } // kDidTabUnder is not reported multiple times for redirects. -TEST_P(BlockTabUnderIncognitoTest, DisableFeature_LogsDidTabUnder) { +TEST_F(BlockTabUnderTest, DisableFeature_LogsDidTabUnder) { DisableFeature(); EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); SimulatePopup(); @@ -599,12 +561,12 @@ simulator->Redirect(a_url); simulator->Commit(); histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kStarted), 2); histogram_tester()->ExpectBucketCount( - GetActionHistogram(), + kTabUnderAction, static_cast<int>(TabUnderNavigationThrottle::Action::kDidTabUnder), 1); - histogram_tester()->ExpectTotalCount(GetActionHistogram(), 3); + histogram_tester()->ExpectTotalCount(kTabUnderAction, 3); } TEST_F(BlockTabUnderTest, LogsUkm) {
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc index 1f5ec42..f582fba 100644 --- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc +++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
@@ -50,16 +50,9 @@ namespace { -void LogAction(TabUnderNavigationThrottle::Action action, bool off_the_record) { +void LogAction(TabUnderNavigationThrottle::Action action) { UMA_HISTOGRAM_ENUMERATION("Tab.TabUnderAction", action, TabUnderNavigationThrottle::Action::kCount); - if (off_the_record) { - UMA_HISTOGRAM_ENUMERATION("Tab.TabUnderAction.OTR", action, - TabUnderNavigationThrottle::Action::kCount); - } else { - UMA_HISTOGRAM_ENUMERATION("Tab.TabUnderAction.NonOTR", action, - TabUnderNavigationThrottle::Action::kCount); - } } #if defined(OS_ANDROID) @@ -76,24 +69,19 @@ NOTREACHED(); } -void LogOutcome(bool off_the_record, InterventionOutcome outcome) { - LogAction(GetActionForOutcome(outcome), off_the_record); +void LogOutcome(InterventionOutcome outcome) { + LogAction(GetActionForOutcome(outcome)); } #else -void OnListItemClicked(bool off_the_record, - const GURL& url, - size_t index, - size_t total_size) { - LogAction(TabUnderNavigationThrottle::Action::kClickedThrough, - off_the_record); +void OnListItemClicked(const GURL& url, size_t index, size_t total_size) { + LogAction(TabUnderNavigationThrottle::Action::kClickedThrough); UMA_HISTOGRAM_ENUMERATION("Tab.TabUnder.ClickThroughPosition", GetListItemPositionFromDistance(index, total_size)); } #endif -void LogTabUnderAttempt(content::NavigationHandle* handle, - bool off_the_record) { - LogAction(TabUnderNavigationThrottle::Action::kDidTabUnder, off_the_record); +void LogTabUnderAttempt(content::NavigationHandle* handle) { + LogAction(TabUnderNavigationThrottle::Action::kDidTabUnder); // The source id should generally be set, except for very rare circumstances // where the popup opener tab helper is not observing at the time the @@ -126,8 +114,6 @@ TabUnderNavigationThrottle::TabUnderNavigationThrottle( content::NavigationHandle* handle) : content::NavigationThrottle(handle), - off_the_record_( - handle->GetWebContents()->GetBrowserContext()->IsOffTheRecord()), block_(base::FeatureList::IsEnabled(kBlockTabUnders)), has_opened_popup_since_last_user_gesture_at_start_( HasOpenedPopupSinceLastUserGesture()), @@ -185,7 +171,7 @@ DCHECK(popup_opener); popup_opener->OnDidTabUnder(); - LogTabUnderAttempt(navigation_handle(), off_the_record_); + LogTabUnderAttempt(navigation_handle()); if (block_ && !TabUndersAllowedBySettings()) { const std::string error = @@ -193,7 +179,7 @@ navigation_handle()->GetURL().spec().c_str()); contents->GetMainFrame()->AddMessageToConsole( blink::mojom::ConsoleMessageLevel::kError, error.c_str()); - LogAction(Action::kBlocked, off_the_record_); + LogAction(Action::kBlocked); ShowUI(); return content::NavigationThrottle::CANCEL; } @@ -203,17 +189,14 @@ void TabUnderNavigationThrottle::ShowUI() { content::WebContents* web_contents = navigation_handle()->GetWebContents(); const GURL& url = navigation_handle()->GetURL(); - bool off_the_record = web_contents->GetBrowserContext()->IsOffTheRecord(); #if defined(OS_ANDROID) FramebustBlockInfoBar::Show( - web_contents, - std::make_unique<FramebustBlockMessageDelegate>( - web_contents, url, base::BindOnce(&LogOutcome, off_the_record))); + web_contents, std::make_unique<FramebustBlockMessageDelegate>( + web_contents, url, base::BindOnce(&LogOutcome))); #else if (auto* tab_helper = FramebustBlockTabHelper::FromWebContents(web_contents)) { - tab_helper->AddBlockedUrl( - url, base::BindOnce(&OnListItemClicked, off_the_record)); + tab_helper->AddBlockedUrl(url, base::BindOnce(&OnListItemClicked)); } #endif } @@ -239,7 +222,7 @@ content::NavigationThrottle::ThrottleCheckResult TabUnderNavigationThrottle::WillStartRequest() { - LogAction(Action::kStarted, off_the_record_); + LogAction(Action::kStarted); return MaybeBlockNavigation(); }
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h index 8a4f438a..694bd6f 100644 --- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h +++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
@@ -96,10 +96,6 @@ override; const char* GetNameForLogging() override; - // Store whether we're off the record as a member to avoid looking it up all - // the time. - const bool off_the_record_ = false; - // True if the experiment is turned on and the class should actually attempt // to block tab-unders. const bool block_ = false;
diff --git a/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc b/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc index 2c48fe0..f6ef61a 100644 --- a/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc +++ b/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/defaults.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/search.h" #include "chrome/browser/ui/bookmarks/bookmark_tab_helper_observer.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/sad_tab.h" @@ -16,17 +17,62 @@ #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/sync_preferences/pref_service_syncable.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; +namespace { + +bool IsNTP(content::WebContents* web_contents) { + // Use the committed entry so the bookmarks bar disappears at the same time + // the page does. + content::NavigationEntry* entry = + web_contents->GetController().GetLastCommittedEntry(); + if (!entry) + entry = web_contents->GetController().GetVisibleEntry(); + return (entry && NewTabUI::IsNewTab(entry->GetURL())) || + search::NavEntryIsInstantNTP(web_contents, entry); +} + +} // namespace + BookmarkTabHelper::~BookmarkTabHelper() { if (bookmark_model_) bookmark_model_->RemoveObserver(this); } +bool BookmarkTabHelper::ShouldShowBookmarkBar() const { + if (web_contents()->ShowingInterstitialPage()) + return false; + + if (SadTab::ShouldShow(web_contents()->GetCrashedStatus())) + return false; + + if (!browser_defaults::bookmarks_enabled) + return false; + + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + +#if !defined(OS_CHROMEOS) + if (profile->IsGuestSession()) + return false; +#endif + + PrefService* prefs = profile->GetPrefs(); + if (prefs->IsManagedPreference(bookmarks::prefs::kShowBookmarkBar) && + !prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar)) + return false; + + // The bookmark bar is only shown on the NTP if the user + // has added something to it. + return IsNTP(web_contents()) && bookmark_model_ && + bookmark_model_->HasBookmarks(); +} + void BookmarkTabHelper::AddObserver(BookmarkTabHelperObserver* observer) { observers_.AddObserver(observer); }
diff --git a/chrome/browser/ui/bookmarks/bookmark_tab_helper.h b/chrome/browser/ui/bookmarks/bookmark_tab_helper.h index 280310aa..1dca47d99 100644 --- a/chrome/browser/ui/bookmarks/bookmark_tab_helper.h +++ b/chrome/browser/ui/bookmarks/bookmark_tab_helper.h
@@ -51,6 +51,8 @@ bool is_starred() const { return is_starred_; } + bool ShouldShowBookmarkBar() const; + void AddObserver(BookmarkTabHelperObserver* observer); void RemoveObserver(BookmarkTabHelperObserver* observer); bool HasObserver(BookmarkTabHelperObserver* observer) const;
diff --git a/chrome/browser/ui/bookmarks/bookmark_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_unittest.cc index 34141ff..42f3c24 100644 --- a/chrome/browser/ui/bookmarks/bookmark_unittest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_unittest.cc
@@ -2,25 +2,35 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <memory> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/browser_with_test_window_test.h" -#include "components/search_engines/search_terms_data.h" -#include "components/search_engines/template_url_service.h" -#include "components/search_engines/template_url_service_client.h" +#include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/test/bookmark_test_helpers.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" typedef BrowserWithTestWindowTest BookmarkTest; -// Verify that the detached bookmark bar is hidden on custom NTP pages. -TEST_F(BookmarkTest, DetachedBookmarkBarOnCustomNTP) { +TEST_F(BookmarkTest, NonEmptyBookmarkBarShownOnNTP) { + profile()->CreateBookmarkModel(true); + bookmarks::BookmarkModel* bookmark_model = + BookmarkModelFactory::GetForBrowserContext(profile()); + bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); + bookmarks::AddIfNotBookmarked(bookmark_model, GURL("https://www.test.com"), + base::string16()); + + AddTab(browser(), GURL(chrome::kChromeUINewTabURL)); + EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state()); +} + +TEST_F(BookmarkTest, EmptyBookmarkBarNotShownOnNTP) { + AddTab(browser(), GURL(chrome::kChromeUINewTabURL)); + EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); +} + +// Verify that the bookmark bar is hidden on custom NTP pages. +TEST_F(BookmarkTest, BookmarkBarOnCustomNTP) { // Create a empty commited web contents. std::unique_ptr<content::WebContents> web_contents = content::WebContents::Create( @@ -35,38 +45,9 @@ content::NavigationEntry* entry = controller->GetVisibleEntry(); entry->SetVirtualURL(GURL(chrome::kChromeUINewTabURL)); - // Verify that the detached bookmark bar is hidden. + // Verify that the bookmark bar is hidden. EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), true); EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state()); } - -class BookmarkInstantExtendedTest : public BrowserWithTestWindowTest { - public: - BookmarkInstantExtendedTest() { - } - - protected: - TestingProfile* CreateProfile() override { - TestingProfile* profile = BrowserWithTestWindowTest::CreateProfile(); - // TemplateURLService is normally NULL during testing. Instant extended - // needs this service so set a custom factory function. - TemplateURLServiceFactory::GetInstance()->SetTestingFactory( - profile, base::BindRepeating( - &BookmarkInstantExtendedTest::CreateTemplateURLService)); - return profile; - } - - private: - static std::unique_ptr<KeyedService> CreateTemplateURLService( - content::BrowserContext* profile) { - return base::WrapUnique( - new TemplateURLService(static_cast<Profile*>(profile)->GetPrefs(), - base::WrapUnique(new SearchTermsData), NULL, - std::unique_ptr<TemplateURLServiceClient>(), - NULL, NULL, base::Closure())); - } - - DISALLOW_COPY_AND_ASSIGN(BookmarkInstantExtendedTest); -};
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 6d7fce9..c8e49a1 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -2607,18 +2607,8 @@ } void Browser::UpdateBookmarkBarState(BookmarkBarStateChangeReason reason) { - BookmarkBar::State state; - // The bookmark bar is always hidden for Guest Sessions and in fullscreen - // mode, unless on the new tab page. - if (profile_->IsGuestSession()) { - state = BookmarkBar::HIDDEN; - } else if (browser_defaults::bookmarks_enabled && - profile_->GetPrefs()->GetBoolean(bookmarks::prefs::kShowBookmarkBar) && - !ShouldHideUIForFullscreen()) { - state = BookmarkBar::SHOW; - } else { - state = BookmarkBar::HIDDEN; - } + BookmarkBar::State state = + ShouldShowBookmarkBar() ? BookmarkBar::SHOW : BookmarkBar::HIDDEN; if (state == bookmark_bar_state_) return; @@ -2641,6 +2631,24 @@ BookmarkBar::DONT_ANIMATE_STATE_CHANGE); } +bool Browser::ShouldShowBookmarkBar() const { + if (profile_->IsGuestSession()) + return false; + + if (browser_defaults::bookmarks_enabled && + profile_->GetPrefs()->GetBoolean(bookmarks::prefs::kShowBookmarkBar) && + !ShouldHideUIForFullscreen()) + return true; + + WebContents* web_contents = tab_strip_model_->GetActiveWebContents(); + if (!web_contents) + return false; + + BookmarkTabHelper* bookmark_tab_helper = + BookmarkTabHelper::FromWebContents(web_contents); + return bookmark_tab_helper && bookmark_tab_helper->ShouldShowBookmarkBar(); +} + bool Browser::ShouldHideUIForFullscreen() const { // Windows and GTK remove the browser controls in fullscreen, but Mac and Ash // keep the controls in a slide-down panel.
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 83f9875..e77fd8ba 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -937,6 +937,8 @@ // BrowserWindow if necessary. void UpdateBookmarkBarState(BookmarkBarStateChangeReason reason); + bool ShouldShowBookmarkBar() const; + bool ShouldHideUIForFullscreen() const; // Indicates if we have called BrowserList::NotifyBrowserCloseStarted for the
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index b4f557ed..30b77fa 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -77,7 +77,7 @@ #endif #if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_context_menu.h" #include "chrome/browser/ui/browser_commands_chromeos.h" #endif @@ -1275,7 +1275,8 @@ } // namespace void BrowserCommandController::UpdateCommandsForLockedFullscreenMode() { - bool is_locked_fullscreen = ash::IsWindowTrustedPinned(browser_->window()); + bool is_locked_fullscreen = + platform_util::IsBrowserLockedFullscreen(browser_); // Sanity check to make sure this function is called only on state change. DCHECK_NE(is_locked_fullscreen, is_locked_fullscreen_); if (is_locked_fullscreen == is_locked_fullscreen_)
diff --git a/chrome/browser/ui/browser_command_controller_browsertest.cc b/chrome/browser/ui/browser_command_controller_browsertest.cc index aeb3726..6e85720 100644 --- a/chrome/browser/ui/browser_command_controller_browsertest.cc +++ b/chrome/browser/ui/browser_command_controller_browsertest.cc
@@ -35,7 +35,6 @@ #include "content/public/test/test_utils.h" #if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "chromeos/constants/chromeos_switches.h"
diff --git a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc index de4cf8b0..4c3a684 100644 --- a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc +++ b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc
@@ -186,7 +186,8 @@ CloseNotification(notification_profile_); notification_profile_ = profiles[0]; NotificationDisplayService::GetForProfile(notification_profile_) - ->Display(NotificationHandler::Type::TRANSIENT, *notification_); + ->Display(NotificationHandler::Type::TRANSIENT, *notification_, + /*metadata=*/nullptr); // Always return false, the notification UI can be used to quit all apps which // will cause Chrome to quit.
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index 2f1868aef..d1cb667c 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -9,6 +9,7 @@ #include "apps/launcher.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" @@ -34,6 +35,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/url_constants.h" #include "content/public/browser/web_contents.h" @@ -338,6 +340,22 @@ return tab; } +Browser* ReparentWebContentsWithBrowserCreateParams( + content::WebContents* contents, + const Browser::CreateParams& browser_params) { + Browser* source_browser = chrome::FindBrowserWithWebContents(contents); + Browser* target_browser = Browser::Create(browser_params); + + TabStripModel* source_tabstrip = source_browser->tab_strip_model(); + target_browser->tab_strip_model()->AppendWebContents( + source_tabstrip->DetachWebContentsAt( + source_tabstrip->GetIndexOfWebContents(contents)), + true); + target_browser->window()->Show(); + + return target_browser; +} + } // namespace WebContents* OpenApplication(const AppLaunchParams& params) { @@ -468,26 +486,27 @@ Browser* ReparentWebContentsIntoAppBrowser( content::WebContents* contents, const extensions::Extension* extension) { - Browser* source_browser = chrome::FindBrowserWithWebContents(contents); Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); // Incognito tabs reparent correctly, but remain incognito without any // indication to the user, so disallow it. DCHECK(!profile->IsOffTheRecord()); - Browser::CreateParams browser_params(Browser::CreateParams::CreateForApp( web_app::GenerateApplicationNameFromAppId(extension->id()), true /* trusted_source */, gfx::Rect(), profile, true /* user_gesture */)); - Browser* target_browser = new Browser(browser_params); + return ReparentWebContentsWithBrowserCreateParams(contents, browser_params); +} - TabStripModel* source_tabstrip = source_browser->tab_strip_model(); - target_browser->tab_strip_model()->AppendWebContents( - source_tabstrip->DetachWebContentsAt( - source_tabstrip->GetIndexOfWebContents(contents)), - true); - target_browser->window()->Show(); - - return target_browser; +Browser* ReparentWebContentsForFocusMode(content::WebContents* contents) { + DCHECK(base::FeatureList::IsEnabled(features::kFocusMode)); + Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); + // TODO(crbug.com/941577): Remove DCHECK when focus mode is permitted in guest + // and incognito sessions. + DCHECK(!profile->IsOffTheRecord()); + Browser::CreateParams browser_params(Browser::CreateParams::CreateForApp( + web_app::GenerateApplicationNameForFocusMode(), true /* trusted_source */, + gfx::Rect(), profile, true /* user_gesture */)); + return ReparentWebContentsWithBrowserCreateParams(contents, browser_params); } Browser* ReparentSecureActiveTabIntoPwaWindow(Browser* browser) {
diff --git a/chrome/browser/ui/extensions/application_launch.h b/chrome/browser/ui/extensions/application_launch.h index 6df2cdb..8867a26 100644 --- a/chrome/browser/ui/extensions/application_launch.h +++ b/chrome/browser/ui/extensions/application_launch.h
@@ -59,6 +59,9 @@ content::WebContents* contents, const extensions::Extension* extension); +// Reparents contents to a new app browser when entering the Focus Mode. +Browser* ReparentWebContentsForFocusMode(content::WebContents* contents); + // Reparents the active tab into a new app browser for the PWA that has the // tab's URL in its scope. Does nothing if the tab is not secure or there is no // applicable PWA.
diff --git a/chrome/browser/ui/extensions/application_launch_browsertest.cc b/chrome/browser/ui/extensions/application_launch_browsertest.cc new file mode 100644 index 0000000..d14718d --- /dev/null +++ b/chrome/browser/ui/extensions/application_launch_browsertest.cc
@@ -0,0 +1,60 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/chrome_test_suite.h" +#include "chrome/test/base/test_launcher_utils.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test_utils.h" +#include "url/gurl.h" + +class ApplicationLaunchBrowserTest : public InProcessBrowserTest { + public: + ApplicationLaunchBrowserTest() = default; + + content::WebContents* GetWebContentsForTab(Browser* browser, int index) { + return browser->tab_strip_model()->GetWebContentsAt(index); + } + + protected: + base::test::ScopedFeatureList feature_list; +}; + +IN_PROC_BROWSER_TEST_F(ApplicationLaunchBrowserTest, + ReparentWebContentsForFocusModeSingleTab) { + feature_list.InitAndEnableFeature(features::kFocusMode); + const GURL url("http://aaa.com/empty.html"); + ui_test_utils::NavigateToURL(browser(), url); + + Browser* app_browser = + ReparentWebContentsForFocusMode(GetWebContentsForTab(browser(), 0)); + EXPECT_TRUE(app_browser->is_app()); + EXPECT_NE(app_browser, browser()); + EXPECT_EQ(nullptr, browser()->tab_strip_model()->GetActiveWebContents()); + + GURL app_browser_url = app_browser->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL(); + EXPECT_EQ(url, app_browser_url); +} + +IN_PROC_BROWSER_TEST_F(ApplicationLaunchBrowserTest, + ReparentWebContentsForFocusModeMultipleTabs) { + const GURL url("http://aaa.com/empty.html"); + feature_list.InitAndEnableFeature(features::kFocusMode); + chrome::AddTabAt(browser(), url, -1, true); + chrome::AddTabAt(browser(), GURL(), -1, true); + ASSERT_EQ(3, browser()->tab_strip_model()->count()); + + Browser* app_browser = + ReparentWebContentsForFocusMode(GetWebContentsForTab(browser(), 1)); + EXPECT_TRUE(app_browser->is_app()); + EXPECT_NE(app_browser, browser()); + EXPECT_EQ(url, GetWebContentsForTab(app_browser, 0)->GetURL()); + EXPECT_EQ(2, browser()->tab_strip_model()->count()); +}
diff --git a/chrome/browser/ui/extensions/extension_installed_notification.cc b/chrome/browser/ui/extensions/extension_installed_notification.cc index 50b2c10..d63de75 100644 --- a/chrome/browser/ui/extensions/extension_installed_notification.cc +++ b/chrome/browser/ui/extensions/extension_installed_notification.cc
@@ -54,7 +54,8 @@ message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(profile_)->Display( - NotificationHandler::Type::TRANSIENT, *notification); + NotificationHandler::Type::TRANSIENT, *notification, + /*metadata=*/nullptr); } ExtensionInstalledNotification::~ExtensionInstalledNotification() {}
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc index e8e772d..ec3102b 100644 --- a/chrome/browser/ui/login/login_handler.cc +++ b/chrome/browser/ui/login/login_handler.cc
@@ -185,7 +185,7 @@ if (password_manager) { password_form_.username_value = username; password_form_.password_value = password; - password_manager->ProvisionallySavePassword(password_form_, nullptr); + password_manager->OnPasswordHttpAuthFormSubmitted(password_form_); if (logger) { logger->LogPasswordForm( autofill::SavePasswordProgressLogger::STRING_LOGINHANDLER_FORM,
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc index 86fcd28..4a66755 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.cc +++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -76,8 +76,6 @@ return GetSecurityChipColor(tint, state); case OmniboxPart::LOCATION_BAR_SELECTED_KEYWORD: return dark ? gfx::kGoogleGrey100 : gfx::kGoogleBlue600; - case OmniboxPart::LOCATION_BAR_FOCUS_RING: - return dark ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600; case OmniboxPart::RESULTS_BACKGROUND: { // High contrast mode needs a darker base - Grey 800 with 14% white // overlaid on it (see below) is hard to produce good contrast ratios @@ -104,12 +102,6 @@ // This is a pre-lightened (or darkened) variant of the base text color. return dark ? gfx::kGoogleGrey400 : gfx::kGoogleGrey700; - case OmniboxPart::RESULTS_TEXT_INVISIBLE: - return SK_ColorTRANSPARENT; - case OmniboxPart::RESULTS_TEXT_NEGATIVE: - return dark ? gfx::kGoogleRed300 : gfx::kGoogleRed600; - case OmniboxPart::RESULTS_TEXT_POSITIVE: - return dark ? gfx::kGoogleGreen300 : gfx::kGoogleGreen600; case OmniboxPart::RESULTS_TEXT_URL: if (high_contrast) return dark ? gfx::kGoogleBlue300 : gfx::kGoogleBlue700;
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.h b/chrome/browser/ui/omnibox/omnibox_theme.h index 3790fa4..b3de6ac 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.h +++ b/chrome/browser/ui/omnibox/omnibox_theme.h
@@ -19,15 +19,11 @@ LOCATION_BAR_TEXT_DEFAULT, LOCATION_BAR_TEXT_DIMMED, LOCATION_BAR_BUBBLE_OUTLINE, - LOCATION_BAR_FOCUS_RING, RESULTS_BACKGROUND, // Background of the results dropdown. RESULTS_ICON, RESULTS_TEXT_DEFAULT, RESULTS_TEXT_DIMMED, - RESULTS_TEXT_INVISIBLE, - RESULTS_TEXT_NEGATIVE, - RESULTS_TEXT_POSITIVE, RESULTS_TEXT_URL, };
diff --git a/chrome/browser/ui/search/local_ntp_suggestions_browsertest.cc b/chrome/browser/ui/search/local_ntp_suggestions_browsertest.cc index 41811f8..ad739a2 100644 --- a/chrome/browser/ui/search/local_ntp_suggestions_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_suggestions_browsertest.cc
@@ -6,6 +6,8 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/ntp_features.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_service.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" #include "chrome/browser/search/search_suggest/search_suggest_service.h" #include "chrome/browser/search/search_suggest/search_suggest_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -16,18 +18,24 @@ #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +using ::testing::Invoke; + class MockSearchSuggestService : public SearchSuggestService { public: - explicit MockSearchSuggestService(Profile* profile) - : SearchSuggestService(profile, nullptr, nullptr) {} + MOCK_METHOD0(Refresh, void()); - void Refresh() override { + void RefreshImpl() { SearchSuggestDataLoaded(SearchSuggestLoader::Status::OK, search_suggest_data_); } + explicit MockSearchSuggestService(Profile* profile) + : SearchSuggestService(profile, nullptr, nullptr) {} + void set_search_suggest_data(const SearchSuggestData& search_suggest_data) { search_suggest_data_ = search_suggest_data; } @@ -88,14 +96,23 @@ subscription_; }; -IN_PROC_BROWSER_TEST_F(LocalNTPSearchSuggestTest, SuggestionsInjectedIntoPage) { +IN_PROC_BROWSER_TEST_F(LocalNTPSearchSuggestTest, + SuggestionsInjectedIntoPageEnUS) { EXPECT_EQ(base::nullopt, search_suggest_service()->search_suggest_data()); + OneGoogleBarService* one_google_bar_service = + OneGoogleBarServiceFactory::GetForProfile(browser()->profile()); + one_google_bar_service->SetLanguageCodeForTesting("en-US"); + SearchSuggestData data; data.suggestions_html = "<div>suggestions</div>"; data.end_of_body_script = "console.log('suggestions-done')"; search_suggest_service()->set_search_suggest_data(data); + EXPECT_CALL(*search_suggest_service(), Refresh()) + .WillOnce(Invoke(search_suggest_service(), + &MockSearchSuggestService::RefreshImpl)); + // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); @@ -115,9 +132,45 @@ EXPECT_EQ(1, search_suggest_service()->impression_count()); } -IN_PROC_BROWSER_TEST_F(LocalNTPSearchSuggestTest, NoSuggestionsjectedIntoPage) { +IN_PROC_BROWSER_TEST_F(LocalNTPSearchSuggestTest, + SuggestionsNotInjectedIntoPageNonEnUS) { EXPECT_EQ(base::nullopt, search_suggest_service()->search_suggest_data()); + OneGoogleBarService* one_google_bar_service = + OneGoogleBarServiceFactory::GetForProfile(browser()->profile()); + one_google_bar_service->SetLanguageCodeForTesting("en-UK"); + + SearchSuggestData data; + data.suggestions_html = "<div>suggestions</div>"; + data.end_of_body_script = "console.log('suggestions-done')"; + search_suggest_service()->set_search_suggest_data(data); + + EXPECT_CALL(*search_suggest_service(), Refresh()).Times(0); + + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser(), + /*delay=*/1000); + bool result; + ASSERT_TRUE(instant_test_utils::GetBoolFromJS( + active_tab, "$('suggestions') === null", &result)); + EXPECT_TRUE(result); + EXPECT_EQ(0, search_suggest_service()->impression_count()); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPSearchSuggestTest, + EmptySuggestionsNotInjectedIntoPage) { + EXPECT_EQ(base::nullopt, search_suggest_service()->search_suggest_data()); + + OneGoogleBarService* one_google_bar_service = + OneGoogleBarServiceFactory::GetForProfile(browser()->profile()); + one_google_bar_service->SetLanguageCodeForTesting("en-US"); + + SearchSuggestData data; + EXPECT_CALL(*search_suggest_service(), Refresh()) + .WillOnce(Invoke(search_suggest_service(), + &MockSearchSuggestService::RefreshImpl)); + content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser(),
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index d5d754bb..da45b9b 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "chrome/browser/browser_features.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h" @@ -64,8 +65,11 @@ : l10n_util::GetPluralStringFUTF16(IDS_TAB_CXMENU_UNPIN_TAB, num_affected_tabs)); if (base::FeatureList::IsEnabled(features::kFocusMode)) { - AddItemWithStringId(TabStripModel::CommandFocusMode, - IDS_TAB_CXMENU_FOCUS_THIS_TAB); + // TODO(crbug.com/941577): Allow Focus Mode in Incognito and Guest Session. + if (!tab_strip->profile()->IsOffTheRecord()) { + AddItemWithStringId(TabStripModel::CommandFocusMode, + IDS_TAB_CXMENU_FOCUS_THIS_TAB); + } } const bool will_mute = !chrome::AreAllSitesMuted(*tab_strip, affected_indices); @@ -78,8 +82,8 @@ Browser* browser = chrome::FindBrowserWithWebContents(tab_strip->GetWebContentsAt(index)); if (send_tab_to_self::ShouldOfferFeature(browser)) { - AddItemWithStringId(TabStripModel::CommandSendToMyDevices, - IDS_TAB_CXMENU_SEND_TO_MY_DEVICES); + AddItemWithStringId(TabStripModel::CommandSendTabToSelf, + IDS_CONTEXT_MENU_SEND_TAB_TO_SELF); } AddSeparator(ui::NORMAL_SEPARATOR); AddItem(TabStripModel::CommandCloseTab,
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index c0660ca2..76a6e2c2 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -25,10 +25,12 @@ #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/ui/tabs/tab_group_data.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" #include "chrome/browser/ui/tabs/tab_utils.h" +#include "chrome/browser/ui/web_applications/web_app_dialog_utils.h" #include "chrome/browser/ui/web_contents_sizer.h" #include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -1082,9 +1084,9 @@ return true; case CommandFocusMode: - return true; + return GetIndicesForCommand(context_index).size() == 1; - case CommandSendToMyDevices: + case CommandSendTabToSelf: return true; case CommandAddToNewGroup: @@ -1182,7 +1184,7 @@ break; } - case CommandSendToMyDevices: { + case CommandSendTabToSelf: { base::RecordAction(UserMetricsAction("TabContextMenu_SendToMyDevices")); send_tab_to_self::CreateNewEntry(GetActiveWebContents(), profile_); break; @@ -1205,7 +1207,10 @@ } case CommandFocusMode: { - // TODO(yiningwang) (936096): Add Implementation. + base::RecordAction(UserMetricsAction("TabContextMenu_FocusMode")); + std::vector<int> indices = GetIndicesForCommand(context_index); + WebContents* contents = GetWebContentsAt(indices[0]); + ReparentWebContentsForFocusMode(contents); break; } @@ -1288,8 +1293,8 @@ case CommandDuplicate: *browser_cmd = IDC_DUPLICATE_TAB; break; - case CommandSendToMyDevices: - *browser_cmd = IDC_SEND_TO_MY_DEVICES; + case CommandSendTabToSelf: + *browser_cmd = IDC_SEND_TAB_TO_SELF; break; case CommandCloseTab: *browser_cmd = IDC_CLOSE_TAB;
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 140b2ab1..83985d35 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -401,7 +401,7 @@ CommandTogglePinned, CommandFocusMode, CommandToggleSiteMuted, - CommandSendToMyDevices, + CommandSendTabToSelf, CommandBookmarkAllTabs, CommandAddToNewGroup, CommandAddToExistingGroup,
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 76ca46c..52997ca5 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -20,6 +20,7 @@ #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/banners/app_banner_manager.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/extension_util.h" @@ -837,6 +838,10 @@ } bool AppMenuModel::CreateActionToolbarOverflowMenu() { + // The extensions menu replaces the 3-dot menu entry. + if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) + return false; + // We only add the extensions overflow container if there are any icons that // aren't shown in the main container. // browser_->window() can return null during startup, and
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc index 2e4641d..022697f2 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -96,7 +96,7 @@ private: // Overridden from views::View: void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { views::DialogDelegateView::ViewHierarchyChanged(details); if (details.is_add && details.child == this) GetFocusManager()->AdvanceFocus(false);
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc index a991009..0800a788 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
@@ -128,7 +128,7 @@ // Make a vertically stacked view of all the panels we want to display in the // dialog. - views::View* dialog_body_contents = new views::View(); + auto dialog_body_contents = std::make_unique<views::View>(); const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); dialog_body_contents->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, @@ -159,7 +159,7 @@ const int kMaxDialogHeight = 1000; dialog_body_ = new views::ScrollView(); dialog_body_->ClipHeightTo(kMaxDialogHeight, kMaxDialogHeight); - dialog_body_->SetContents(dialog_body_contents); + dialog_body_->SetContents(std::move(dialog_body_contents)); AddChildView(dialog_header_);
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index 3af4bdd..e7d140c 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -947,7 +947,7 @@ if (!rows_.empty()) { // Create a container to wrap the "regular" (non-footer) rows. - views::View* body_container = new views::View(); + auto body_container = std::make_unique<views::View>(); views::BoxLayout* body_layout = body_container->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); body_layout->set_main_axis_alignment( @@ -958,9 +958,11 @@ scroll_view_ = new views::ScrollView(); scroll_view_->set_hide_horizontal_scrollbar(true); - scroll_view_->SetContents(body_container); + auto* body_container_ptr = + scroll_view_->SetContents(std::move(body_container)); scroll_view_->set_draw_overflow_indicator(false); - scroll_view_->ClipHeightTo(0, body_container->GetPreferredSize().height()); + scroll_view_->ClipHeightTo(0, + body_container_ptr->GetPreferredSize().height()); // Use an additional container to apply padding outside the scroll view, so // that the padding area is stationary. This ensures that the rounded
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc index b8099b99..1f3cd41 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc
@@ -138,7 +138,7 @@ LocalCardMigrationDialogView* dialog_view, bool should_show_checkbox) { ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - auto* card_list_view = new views::View(); + auto card_list_view = std::make_unique<views::View>(); constexpr int kCardListSmallVerticalDistance = 8; auto* card_list_view_layout = card_list_view->SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -156,7 +156,7 @@ auto card_list_scroll_view = std::make_unique<views::ScrollView>(); card_list_scroll_view->set_hide_horizontal_scrollbar(true); - card_list_scroll_view->SetContents(card_list_view); + card_list_scroll_view->SetContents(std::move(card_list_view)); card_list_scroll_view->set_draw_overflow_indicator(false); constexpr int kCardListScrollViewHeight = 140; card_list_scroll_view->ClipHeightTo(0, kCardListScrollViewHeight);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 8973956a..8a53ce5 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -899,7 +899,7 @@ } void BookmarkBarView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) { // We may get inserted into a hierarchy with a profile - this typically // occurs when the bar's contents get populated fast enough that the
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h index 4a04d38..d3c4cd8 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.h
@@ -159,7 +159,7 @@ gfx::Size GetMinimumSize() const override; void Layout() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void PaintChildren(const views::PaintInfo& paint_info) override; bool GetDropFormats(int* formats, std::set<ui::ClipboardFormatType>* format_types) override;
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc index 186116f..568b714 100644 --- a/chrome/browser/ui/views/certificate_selector.cc +++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -26,6 +26,7 @@ #include "ui/base/models/table_model.h" #include "ui/base/models/table_model_observer.h" #include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/table/table_view.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/widget/widget.h" @@ -228,13 +229,15 @@ } columns.push_back(ui::TableColumn(IDS_CERT_SELECTOR_SERIAL_COLUMN, ui::TableColumn::LEFT, -1, 0.2f)); - table_ = new views::TableView(model_.get(), columns, views::TEXT_ONLY, - true /* single_selection */); - table_->set_observer(this); + auto table = std::make_unique<views::TableView>( + model_.get(), columns, views::TEXT_ONLY, true /* single_selection */); + table_ = table.get(); + table->set_observer(this); layout->StartRow(1.0, kColumnSetId); - layout->AddView(table_->CreateParentIfNecessary(), 1, 1, - views::GridLayout::FILL, views::GridLayout::FILL, - kTableViewWidth, kTableViewHeight); + layout->AddView( + views::TableView::CreateScrollViewWithTable(std::move(table)).release(), + 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, kTableViewWidth, + kTableViewHeight); layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing); }
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc index 071696d..8519ed1 100644 --- a/chrome/browser/ui/views/collected_cookies_views.cc +++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -251,7 +251,7 @@ } void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (details.is_add && details.child == this) Init(); } @@ -381,7 +381,7 @@ } void CollectedCookiesViews::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { views::DialogDelegateView::ViewHierarchyChanged(details); if (details.is_add && details.child == this) Init(); @@ -455,14 +455,13 @@ std::unique_ptr<CookiesTreeViewDrawingProvider> allowed_drawing_provider = std::make_unique<CookiesTreeViewDrawingProvider>(); allowed_cookies_drawing_provider_ = allowed_drawing_provider.get(); - allowed_cookies_tree_ = new views::TreeView(); - allowed_cookies_tree_->SetModel(allowed_cookies_tree_model_.get()); - allowed_cookies_tree_->SetDrawingProvider( - std::move(allowed_drawing_provider)); - allowed_cookies_tree_->SetRootShown(false); - allowed_cookies_tree_->SetEditable(false); - allowed_cookies_tree_->set_auto_expand_children(true); - allowed_cookies_tree_->SetController(this); + auto allowed_cookies_tree = std::make_unique<views::TreeView>(); + allowed_cookies_tree->SetModel(allowed_cookies_tree_model_.get()); + allowed_cookies_tree->SetDrawingProvider(std::move(allowed_drawing_provider)); + allowed_cookies_tree->SetRootShown(false); + allowed_cookies_tree->SetEditable(false); + allowed_cookies_tree->set_auto_expand_children(true); + allowed_cookies_tree->SetController(this); // Create the view that holds all the controls together. This will be the // pane added to the tabbed pane. @@ -489,7 +488,9 @@ unrelated_vertical_distance); layout->StartRow(1.0, single_column_layout_id); - layout->AddView(CreateScrollView(allowed_cookies_tree_), 1, 1, + + allowed_cookies_tree_ = allowed_cookies_tree.get(); + layout->AddView(CreateScrollView(std::move(allowed_cookies_tree)), 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, kTreeViewWidth, kTreeViewHeight); layout->AddPaddingRow(views::GridLayout::kFixedSize, @@ -521,14 +522,13 @@ std::unique_ptr<CookiesTreeViewDrawingProvider> blocked_drawing_provider = std::make_unique<CookiesTreeViewDrawingProvider>(); blocked_cookies_drawing_provider_ = blocked_drawing_provider.get(); - blocked_cookies_tree_ = new views::TreeView(); - blocked_cookies_tree_->SetModel(blocked_cookies_tree_model_.get()); - blocked_cookies_tree_->SetDrawingProvider( - std::move(blocked_drawing_provider)); - blocked_cookies_tree_->SetRootShown(false); - blocked_cookies_tree_->SetEditable(false); - blocked_cookies_tree_->set_auto_expand_children(true); - blocked_cookies_tree_->SetController(this); + auto blocked_cookies_tree = std::make_unique<views::TreeView>(); + blocked_cookies_tree->SetModel(blocked_cookies_tree_model_.get()); + blocked_cookies_tree->SetDrawingProvider(std::move(blocked_drawing_provider)); + blocked_cookies_tree->SetRootShown(false); + blocked_cookies_tree->SetEditable(false); + blocked_cookies_tree->set_auto_expand_children(true); + blocked_cookies_tree->SetController(this); // Create the view that holds all the controls together. This will be the // pane added to the tabbed pane. @@ -555,7 +555,9 @@ unrelated_vertical_distance); layout->StartRow(1.0, single_column_layout_id); - layout->AddView(CreateScrollView(blocked_cookies_tree_), 1, 1, + + blocked_cookies_tree_ = blocked_cookies_tree.get(); + layout->AddView(CreateScrollView(std::move(blocked_cookies_tree)), 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, kTreeViewWidth, kTreeViewHeight); layout->AddPaddingRow(views::GridLayout::kFixedSize, @@ -607,10 +609,11 @@ return view; } -views::View* CollectedCookiesViews::CreateScrollView(views::TreeView* pane) { +views::View* CollectedCookiesViews::CreateScrollView( + std::unique_ptr<views::TreeView> pane) { views::ScrollView* scroll_view = views::ScrollView::CreateScrollViewWithBorder(); - scroll_view->SetContents(pane); + scroll_view->SetContents(std::move(pane)); return scroll_view; }
diff --git a/chrome/browser/ui/views/collected_cookies_views.h b/chrome/browser/ui/views/collected_cookies_views.h index ebd370d..3026193 100644 --- a/chrome/browser/ui/views/collected_cookies_views.h +++ b/chrome/browser/ui/views/collected_cookies_views.h
@@ -66,7 +66,7 @@ // views::View: gfx::Size GetMinimumSize() const override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; private: friend class CollectedCookiesViewsTest; @@ -85,7 +85,7 @@ std::unique_ptr<views::View> CreateButtonsPane(); // Creates and returns a containing ScrollView around the given tree view. - views::View* CreateScrollView(views::TreeView* pane); + views::View* CreateScrollView(std::unique_ptr<views::TreeView> pane); void EnableControls();
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index 3716fb1..e8f817d 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -455,11 +455,12 @@ // Layout for the item list (blocked plugins and popups). if (!bubble_content.list_items.empty()) { - list_item_container_ = new ListItemContainer(this); - list_item_container_->SetBorder( + auto list_item_container = std::make_unique<ListItemContainer>(this); + list_item_container->SetBorder( views::CreateEmptyBorder(0, margins().left(), 0, margins().right())); auto scroll_view = std::make_unique<views::ScrollView>(); - scroll_view->SetContents(list_item_container_); + list_item_container_ = + scroll_view->SetContents(std::move(list_item_container)); rows.push_back({std::move(scroll_view), LayoutRowType::FULL_WIDTH}); for (const ContentSettingBubbleModel::ListItem& list_item :
diff --git a/chrome/browser/ui/views/cookie_info_view.cc b/chrome/browser/ui/views/cookie_info_view.cc index 37aa82f..e61748b 100644 --- a/chrome/browser/ui/views/cookie_info_view.cc +++ b/chrome/browser/ui/views/cookie_info_view.cc
@@ -94,7 +94,7 @@ // CookieInfoView, views::View overrides. void CookieInfoView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) Init(); }
diff --git a/chrome/browser/ui/views/cookie_info_view.h b/chrome/browser/ui/views/cookie_info_view.h index ec041daf..9e9242f 100644 --- a/chrome/browser/ui/views/cookie_info_view.h +++ b/chrome/browser/ui/views/cookie_info_view.h
@@ -46,7 +46,7 @@ protected: // views::View: void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; private: // Layout helper routines.
diff --git a/chrome/browser/ui/views/critical_notification_bubble_view.cc b/chrome/browser/ui/views/critical_notification_bubble_view.cc index 0e4f2dd..1f6b7c9e 100644 --- a/chrome/browser/ui/views/critical_notification_bubble_view.cc +++ b/chrome/browser/ui/views/critical_notification_bubble_view.cc
@@ -148,7 +148,7 @@ } void CriticalNotificationBubbleView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); }
diff --git a/chrome/browser/ui/views/critical_notification_bubble_view.h b/chrome/browser/ui/views/critical_notification_bubble_view.h index b2efec7..31e86e7 100644 --- a/chrome/browser/ui/views/critical_notification_bubble_view.h +++ b/chrome/browser/ui/views/critical_notification_bubble_view.h
@@ -23,7 +23,7 @@ base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; private: // Helper function to calculate the remaining time (in seconds) until
diff --git a/chrome/browser/ui/views/crostini/crostini_app_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_app_installer_view.cc index f0493aa5..f5c247d5 100644 --- a/chrome/browser/ui/views/crostini/crostini_app_installer_view.cc +++ b/chrome/browser/ui/views/crostini/crostini_app_installer_view.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/views/crostini/crostini_app_installer_view.h" +#include <memory> +#include <utility> + #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/crostini/crostini_package_service.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" @@ -65,15 +68,15 @@ IDS_CROSTINI_APP_INSTALL_DIALOG_PACKAGE_TEXT, base::UTF8ToUTF16(package_info_.version), description); - message_label_ = new views::Label(message); - message_label_->SetMultiLine(true); - message_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + auto message_label = std::make_unique<views::Label>(message); + message_label->SetMultiLine(true); + message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); views::ScrollView* scroll_view = new views::ScrollView; scroll_view->set_draw_overflow_indicator(true); scroll_view->ClipHeightTo(crostini::kMinScrollHeight, crostini::kMaxScrollHeight); - scroll_view->SetContents(message_label_); + message_label_ = scroll_view->SetContents(std::move(message_label)); AddChildView(scroll_view); }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index 1dadbd7..5f3e83cb 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
@@ -107,11 +107,12 @@ views::ScrollView::CreateScrollViewWithBorder(); base::string16 screen_title_text = l10n_util::GetStringUTF16( IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN); - list_views_.push_back(new DesktopMediaListView( + auto list_view = std::make_unique<DesktopMediaListView>( this, std::move(source_list), kGenericScreenStyle, - kSingleScreenStyle, screen_title_text)); + kSingleScreenStyle, screen_title_text); + list_views_.push_back( + screen_scroll_view->SetContents(std::move(list_view))); - screen_scroll_view->SetContents(list_views_.back()); screen_scroll_view->ClipHeightTo( kGenericScreenStyle.item_size.height(), kGenericScreenStyle.item_size.height() * 2); @@ -138,10 +139,12 @@ views::ScrollView::CreateScrollViewWithBorder(); base::string16 window_title_text = l10n_util::GetStringUTF16( IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_WINDOW); + auto list_view = std::make_unique<DesktopMediaListView>( + this, std::move(source_list), kWindowStyle, kWindowStyle, + window_title_text); list_views_.push_back( - new DesktopMediaListView(this, std::move(source_list), kWindowStyle, - kWindowStyle, window_title_text)); - window_scroll_view->SetContents(list_views_.back()); + window_scroll_view->SetContents(std::move(list_view))); + window_scroll_view->ClipHeightTo(kWindowStyle.item_size.height(), kWindowStyle.item_size.height() * 2); window_scroll_view->set_hide_horizontal_scrollbar(true); @@ -167,11 +170,11 @@ views::ScrollView::CreateScrollViewWithBorder(); base::string16 tab_title_text = l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_TAB); + auto list_view = std::make_unique<DesktopMediaListView>( + this, std::move(source_list), kTabStyle, kTabStyle, tab_title_text); list_views_.push_back( - new DesktopMediaListView(this, std::move(source_list), kTabStyle, - kTabStyle, tab_title_text)); + tab_scroll_view->SetContents(std::move(list_view))); - tab_scroll_view->SetContents(list_views_.back()); tab_scroll_view->ClipHeightTo(kTabStyle.item_size.height() * 10, kTabStyle.item_size.height() * 10); tab_scroll_view->set_hide_horizontal_scrollbar(true);
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc index 3499d53a..f2bd4f6 100644 --- a/chrome/browser/ui/views/device_chooser_content_view.cc +++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -22,6 +22,7 @@ #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/styled_label.h" #include "ui/views/controls/table/table_view.h" #include "ui/views/controls/throbber.h" @@ -127,16 +128,17 @@ chooser_controller_->set_view(this); std::vector<ui::TableColumn> table_columns; table_columns.push_back(ui::TableColumn()); - table_view_ = new views::TableView( + auto table_view = std::make_unique<views::TableView>( this, table_columns, chooser_controller_->ShouldShowIconBeforeText() ? views::ICON_AND_TEXT : views::TEXT_ONLY, !chooser_controller_->AllowMultipleSelection() /* single_selection */); - table_view_->set_select_on_remove(false); - table_view_->set_observer(table_view_observer); + table_view_ = table_view.get(); + table_view->set_select_on_remove(false); + table_view->set_observer(table_view_observer); - table_parent_ = table_view_->CreateParentIfNecessary(); - AddChildView(table_parent_); + table_parent_ = AddChildView( + views::TableView::CreateScrollViewWithTable(std::move(table_view))); no_options_help_ = new views::Label(chooser_controller_->GetNoOptionsText()); no_options_help_->SetMultiLine(true);
diff --git a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc index e3d17449..c1b6e682 100644 --- a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc +++ b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/extensions/extension_view_host.h" #include "chrome/browser/profiles/profile.h" @@ -148,6 +149,13 @@ void ExtensionActionPlatformDelegateViews::UnregisterCommand( bool only_if_removed) { + if (!GetDelegateViews()) { + // The delegate can currently be null in the extensions menu. + // TODO(pbos): Remove this when the menu implementation is more + // complete. + DCHECK(base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)); + return; + } views::FocusManager* focus_manager = GetDelegateViews()->GetFocusManagerForAccelerator(); if (!focus_manager || !action_keybinding_.get())
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index ef647e5..53f6ef6d 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -525,7 +525,7 @@ scroll_view_ = new views::ScrollView(); scroll_view_->set_hide_horizontal_scrollbar(true); - scroll_view_->SetContents(extension_info_container.release()); + scroll_view_->SetContents(std::move(extension_info_container)); scroll_view_->ClipHeightTo( 0, provider->GetDistanceMetric( views::DISTANCE_DIALOG_SCROLLABLE_AREA_MAX_HEIGHT));
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_view.cc new file mode 100644 index 0000000..eb68ecc --- /dev/null +++ b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
@@ -0,0 +1,104 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/extensions/extensions_menu_view.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" +#include "chrome/browser/ui/views/chrome_layout_provider.h" +#include "chrome/browser/ui/views/hover_button.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/layout/box_layout.h" + +namespace { +ExtensionsMenuView* g_extensions_dialog = nullptr; +} // namespace + +ExtensionsMenuView::ExtensionsMenuView(views::View* anchor_view, + Browser* browser) + : BubbleDialogDelegateView(anchor_view, + views::BubbleBorder::Arrow::TOP_RIGHT), + browser_(browser), + model_(ToolbarActionsModel::Get(browser_->profile())), + model_observer_(this) { + model_observer_.Add(model_); + + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(0), + ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_UNRELATED_CONTROL_HORIZONTAL))); + Repopulate(); +} + +ExtensionsMenuView::~ExtensionsMenuView() { + DCHECK_EQ(g_extensions_dialog, this); + g_extensions_dialog = nullptr; +} + +base::string16 ExtensionsMenuView::GetWindowTitle() const { + return l10n_util::GetStringUTF16(IDS_EXTENSIONS_MENU_TITLE); +} + +void ExtensionsMenuView::Repopulate() { + RemoveAllChildViews(true); + for (auto action_id : model_->action_ids()) { + // TODO(pbos): Revisit this skeleton with appropriate click behavior. + AddChildView(std::make_unique<HoverButton>( + nullptr, model_->CreateActionForId(browser_, nullptr, action_id) + ->GetActionName())); + } +} + +// TODO(pbos): Revisit observed events below. +void ExtensionsMenuView::OnToolbarActionAdded( + const ToolbarActionsModel::ActionId& item, + int index) { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarActionRemoved( + const ToolbarActionsModel::ActionId& action_id) { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarActionMoved( + const ToolbarActionsModel::ActionId& action_id, + int index) { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarActionLoadFailed() { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarActionUpdated( + const ToolbarActionsModel::ActionId& action_id) { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarVisibleCountChanged() { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarHighlightModeChanged(bool is_highlighting) { + Repopulate(); +} +void ExtensionsMenuView::OnToolbarModelInitialized() { + Repopulate(); +} + +// static +void ExtensionsMenuView::ShowBubble(views::View* anchor_view, + Browser* browser) { + DCHECK(!g_extensions_dialog); + g_extensions_dialog = new ExtensionsMenuView(anchor_view, browser); + views::BubbleDialogDelegateView::CreateBubble(g_extensions_dialog)->Show(); +} + +// static +bool ExtensionsMenuView::IsShowing() { + return g_extensions_dialog != nullptr; +} + +// static +void ExtensionsMenuView::Hide() { + if (IsShowing()) + g_extensions_dialog->GetWidget()->Close(); +}
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.h b/chrome/browser/ui/views/extensions/extensions_menu_view.h new file mode 100644 index 0000000..e6496da --- /dev/null +++ b/chrome/browser/ui/views/extensions/extensions_menu_view.h
@@ -0,0 +1,56 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_MENU_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_MENU_VIEW_H_ + +#include "chrome/browser/ui/toolbar/toolbar_actions_model.h" +#include "ui/views/bubble/bubble_dialog_delegate_view.h" + +namespace views { +class View; +} // namespace views + +// This bubble view displays a list of user extensions. +// TODO(pbos): Once there's more functionality in here (getting to +// chrome://extensions, pinning, extension settings), update this comment. +class ExtensionsMenuView : public views::BubbleDialogDelegateView, + public ToolbarActionsModel::Observer { + public: + ExtensionsMenuView(views::View* anchor_view, Browser* browser); + ~ExtensionsMenuView() override; + + static void ShowBubble(views::View* anchor_view, Browser* browser); + static bool IsShowing(); + static void Hide(); + + // views::BubbleDialogDelegateView: + base::string16 GetWindowTitle() const override; + + // ToolbarActionsModel::Observer: + void OnToolbarActionAdded(const ToolbarActionsModel::ActionId& item, + int index) override; + void OnToolbarActionRemoved( + const ToolbarActionsModel::ActionId& action_id) override; + void OnToolbarActionMoved(const ToolbarActionsModel::ActionId& action_id, + int index) override; + void OnToolbarActionLoadFailed() override; + void OnToolbarActionUpdated( + const ToolbarActionsModel::ActionId& action_id) override; + void OnToolbarVisibleCountChanged() override; + void OnToolbarHighlightModeChanged(bool is_highlighting) override; + void OnToolbarModelInitialized() override; + + private: + void Repopulate(); + + Browser* const browser_; + ToolbarActionsModel* const model_; + ScopedObserver<ToolbarActionsModel, ToolbarActionsModel::Observer> + model_observer_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionsMenuView); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_MENU_VIEW_H_
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc new file mode 100644 index 0000000..6e77a25a --- /dev/null +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
@@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" + +#include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/views/extensions/extensions_menu_view.h" +#include "chrome/grit/generated_resources.h" +#include "extensions/browser/extension_registry.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/material_design/material_design_controller.h" +#include "ui/base/theme_provider.h" +#include "ui/gfx/paint_vector_icon.h" + +ExtensionsToolbarButton::ExtensionsToolbarButton(Browser* browser) + : ToolbarButton(this), browser_(browser) { + SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_EXTENSIONS_BUTTON)); + set_notify_action(Button::NOTIFY_ON_PRESS); +} + +void ExtensionsToolbarButton::UpdateIcon() { + const int icon_size = ui::MaterialDesignController::touch_ui() + ? kDefaultTouchableIconSize + : kDefaultIconSize; + const SkColor normal_color = + GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON); + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(kExtensionIcon, icon_size, normal_color)); +} + +void ExtensionsToolbarButton::ButtonPressed(views::Button* sender, + const ui::Event& event) { + if (ExtensionsMenuView::IsShowing()) { + ExtensionsMenuView::Hide(); + return; + } + ExtensionsMenuView::ShowBubble(this, browser_); +}
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.h b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h new file mode 100644 index 0000000..5e39142 --- /dev/null +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_TOOLBAR_BUTTON_H_ +#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_TOOLBAR_BUTTON_H_ + +#include "chrome/browser/ui/views/toolbar/toolbar_button.h" + +class Browser; + +// Button in the toolbar that provides access to the corresponding extensions +// menu. +class ExtensionsToolbarButton : public ToolbarButton, + public views::ButtonListener { + public: + explicit ExtensionsToolbarButton(Browser* browser); + + void UpdateIcon(); + + private: + // views::ButtonListener: + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + Browser* const browser_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionsToolbarButton); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_TOOLBAR_BUTTON_H_
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc index ca53bf0..763eaf5a 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -129,7 +129,7 @@ // Scrollable area for checkboxes. const int small_vertical_padding = provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_VERTICAL_SMALL); - ScrollableView* scroll_container = new ScrollableView(); + auto scroll_container = std::make_unique<ScrollableView>(); scroll_container->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(), small_vertical_padding)); scroll_container->SetBorder( @@ -160,7 +160,7 @@ MediaGalleriesDialogController::Entries::const_iterator iter; for (iter = entries.begin(); iter != entries.end(); ++iter) { int spacing = iter + 1 == entries.end() ? small_vertical_padding : 0; - AddOrUpdateGallery(*iter, scroll_container, spacing); + AddOrUpdateGallery(*iter, scroll_container.get(), spacing); } } @@ -168,9 +168,8 @@ // Add the scrollable area to the outer dialog view. It will squeeze against // the title/subtitle and buttons to occupy all available space in the dialog. - views::ScrollView* scroll_view = - views::ScrollView::CreateScrollViewWithBorder(); - scroll_view->SetContents(scroll_container); + auto* scroll_view = views::ScrollView::CreateScrollViewWithBorder(); + scroll_view->SetContents(std::move(scroll_container)); layout->StartRowWithPadding(1.0, column_set_id, views::GridLayout::kFixedSize, vertical_padding); layout->AddView(scroll_view, 1.0, 1.0, views::GridLayout::FILL,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index bc2722a7..41ca136 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -16,7 +16,6 @@ #include "ash/public/cpp/frame_utils.h" #include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/touch_uma.h" -#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/public/interfaces/window_state_type.mojom.h" @@ -25,6 +24,7 @@ #include "base/metrics/user_metrics.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client.h" @@ -301,7 +301,7 @@ } bool BrowserNonClientFrameViewAsh::CanUserExitFullscreen() const { - return ash::IsWindowTrustedPinned(GetFrameWindow()) ? false : true; + return !platform_util::IsBrowserLockedFullscreen(browser_view()->browser()); } SkColor BrowserNonClientFrameViewAsh::GetCaptionColor(
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index f1e5448..90a6abd 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -33,6 +33,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/native_window_notification_source.h" #include "chrome/browser/permissions/permission_request_manager.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" @@ -165,7 +166,6 @@ #include "ui/views/window/dialog_delegate.h" #if defined(OS_CHROMEOS) -#include "ash/public/cpp/window_pin_type.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/ash/window_properties.h" #include "chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h" @@ -2328,7 +2328,7 @@ } void BrowserView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.child != this) return; @@ -2731,15 +2731,9 @@ const bool should_stay_in_immersive = !fullscreen && immersive_mode_controller_->ShouldStayImmersiveAfterExitingFullscreen(); - bool is_locked_fullscreen = false; -#if defined(OS_CHROMEOS) - is_locked_fullscreen = ash::IsWindowTrustedPinned( - features::IsUsingWindowService() ? GetNativeWindow()->GetRootWindow() - : GetNativeWindow()); -#endif // Never use immersive in locked fullscreen as it allows the user to exit the // locked mode. - if (is_locked_fullscreen) { + if (platform_util::IsBrowserLockedFullscreen(browser_.get())) { immersive_mode_controller_->SetEnabled(false); } else if (ShouldUseImmersiveFullscreenForUrl(url) && !should_stay_in_immersive) {
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 08629a2..4eebb79 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -495,7 +495,7 @@ void Layout() override; void OnGestureEvent(ui::GestureEvent* event) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void PaintChildren(const views::PaintInfo& paint_info) override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override; void ChildPreferredSizeChanged(View* child) override;
diff --git a/chrome/browser/ui/views/frame/contents_web_view.cc b/chrome/browser/ui/views/frame/contents_web_view.cc index 6eb1308..c228f113 100644 --- a/chrome/browser/ui/views/frame/contents_web_view.cc +++ b/chrome/browser/ui/views/frame/contents_web_view.cc
@@ -42,7 +42,7 @@ } void ContentsWebView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { WebView::ViewHierarchyChanged(details); if (details.is_add) UpdateBackgroundColor();
diff --git a/chrome/browser/ui/views/frame/contents_web_view.h b/chrome/browser/ui/views/frame/contents_web_view.h index 3da7fc6..87609e7 100644 --- a/chrome/browser/ui/views/frame/contents_web_view.h +++ b/chrome/browser/ui/views/frame/contents_web_view.h
@@ -34,7 +34,7 @@ bool GetNeedsNotificationWhenVisibleBoundsChange() const override; void OnVisibleBoundsChanged() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void OnThemeChanged() override; void RenderViewReady() override; void OnLetterboxingChanged() override;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index c461815..b103aae 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -5,13 +5,12 @@ #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h" #include "ash/public/cpp/immersive/immersive_revealed_lock.h" -#include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_properties.h" -#include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/shell.h" // mash-ok #include "base/macros.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -192,9 +191,7 @@ // Don't use immersive mode as long as we are in the locked fullscreen mode // since immersive shows browser controls which allow exiting the mode. - aura::Window* window = widget->GetNativeWindow(); - window = features::IsUsingWindowService() ? window->GetRootWindow() : window; - if (ash::IsWindowTrustedPinned(window)) + if (platform_util::IsBrowserLockedFullscreen(browser_view_->browser())) return; // Enable immersive mode if the widget is activated. Do not disable immersive
diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc index b1a73be..e3f72c8 100644 --- a/chrome/browser/ui/views/hung_renderer_view.cc +++ b/chrome/browser/ui/views/hung_renderer_view.cc
@@ -42,6 +42,7 @@ #include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/widget/widget.h" @@ -436,7 +437,7 @@ // HungRendererDialogView, views::View overrides: void HungRendererDialogView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { views::DialogDelegateView::ViewHierarchyChanged(details); if (!initialized_ && details.is_add && details.child == this && GetWidget()) Init(); @@ -454,8 +455,9 @@ hung_pages_table_model_.reset(new HungPagesTableModel(this)); std::vector<ui::TableColumn> columns; columns.push_back(ui::TableColumn()); - hung_pages_table_ = new views::TableView( + auto hung_pages_table = std::make_unique<views::TableView>( hung_pages_table_model_.get(), columns, views::ICON_AND_TEXT, true); + hung_pages_table_ = hung_pages_table.get(); views::GridLayout* layout = SetLayoutManager(std::make_unique<views::GridLayout>(this)); @@ -474,9 +476,11 @@ provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)); layout->StartRow(1.0, kColumnSetId); - layout->AddView(hung_pages_table_->CreateParentIfNecessary(), 1, 1, - views::GridLayout::FILL, views::GridLayout::FILL, - kTableViewWidth, kTableViewHeight); + layout->AddView( + views::TableView::CreateScrollViewWithTable(std::move(hung_pages_table)) + .release(), + 1, 1, views::GridLayout::FILL, views::GridLayout::FILL, kTableViewWidth, + kTableViewHeight); initialized_ = true; }
diff --git a/chrome/browser/ui/views/hung_renderer_view.h b/chrome/browser/ui/views/hung_renderer_view.h index b1a9aba..f9ad921 100644 --- a/chrome/browser/ui/views/hung_renderer_view.h +++ b/chrome/browser/ui/views/hung_renderer_view.h
@@ -181,7 +181,7 @@ // views::View overrides: void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; static HungRendererDialogView* g_instance_;
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc index 680278b..d5d52ce0 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.cc +++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -190,7 +190,7 @@ } void InfoBarView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { View::ViewHierarchyChanged(details); // Anything that needs to happen once after all subclasses add their children.
diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h index fa56391..385042a 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.h +++ b/chrome/browser/ui/views/infobars/infobar_view.h
@@ -39,7 +39,7 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; gfx::Size CalculatePreferredSize() const override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void OnPaint(gfx::Canvas* canvas) override; void OnThemeChanged() override; void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc index 5717366e..7872380 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -231,7 +231,7 @@ SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Creates a view to hold the views for each app. - views::View* scrollable_view = new views::View(); + auto scrollable_view = std::make_unique<views::View>(); scrollable_view->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); @@ -256,7 +256,7 @@ scroll_view_ = new views::ScrollView(); scroll_view_->SetBackgroundColor(SK_ColorWHITE); - scroll_view_->SetContents(scrollable_view); + scroll_view_->SetContents(std::move(scrollable_view)); // This part gives the scroll a fixed width and height. The height depends on // how many app candidates we got and how many we actually want to show. // The added 0.5 on the else block allow us to let the user know there are
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc index e137e575..d72d508f 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -337,7 +337,7 @@ void CastDialogView::PopulateScrollView(const std::vector<UIMediaSink>& sinks) { sink_buttons_.clear(); - views::View* sink_list_view = new views::View(); + auto sink_list_view = std::make_unique<views::View>(); sink_list_view->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); for (size_t i = 0; i < sinks.size(); i++) { @@ -347,7 +347,7 @@ sink_buttons_.push_back(sink_button); sink_list_view->AddChildView(sink_button); } - scroll_view_->SetContents(sink_list_view); + scroll_view_->SetContents(std::move(sink_list_view)); MaybeSizeToContents(); Layout();
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_view.cc index cd30ce25..4f2521f 100644 --- a/chrome/browser/ui/views/page_action/page_action_icon_view.cc +++ b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
@@ -144,7 +144,7 @@ } void PageActionIconView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { View::ViewHierarchyChanged(details); if (details.is_add && details.child == this && GetNativeTheme()) UpdateIconImage();
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.h b/chrome/browser/ui/views/page_action/page_action_icon_view.h index ae8b5ed..0ad8eb7f 100644 --- a/chrome/browser/ui/views/page_action/page_action_icon_view.h +++ b/chrome/browser/ui/views/page_action/page_action_icon_view.h
@@ -98,7 +98,7 @@ bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnKeyReleased(const ui::KeyEvent& event) override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void OnNativeThemeChanged(const ui::NativeTheme* theme) override; void OnThemeChanged() override; void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc index 1f1f7d84..50c5a26 100644 --- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc +++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -44,7 +44,7 @@ const PasswordDialogController::FormsVector& forms, views::ButtonListener* button_listener, network::mojom::URLLoaderFactory* loader_factory) { - views::View* list_view = new views::View; + auto list_view = std::make_unique<views::View>(); list_view->SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); int item_height = 0; @@ -67,7 +67,7 @@ } views::ScrollView* scroll_view = new views::ScrollView; scroll_view->ClipHeightTo(0, kMaxHeightAccounts * item_height); - scroll_view->SetContents(list_view); + scroll_view->SetContents(std::move(list_view)); return scroll_view; }
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc index 4e44ab7..e9cbb44804 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -477,7 +477,7 @@ } void PaymentRequestDialogView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (being_closed_) return;
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.h b/chrome/browser/ui/views/payments/payment_request_dialog_view.h index 29d7028..9dfea0d 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.h +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.h
@@ -189,7 +189,7 @@ // views::View gfx::Size CalculatePreferredSize() const override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // Non-owned reference to the PaymentRequest that initiated this dialog. Since // the PaymentRequest object always outlives this one, the pointer should
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc index 556790c..9f37748d 100644 --- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc +++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -113,7 +113,7 @@ } void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (!details.is_add && details.child == first_focusable_) first_focusable_ = nullptr; } @@ -250,9 +250,10 @@ // |content_view| will go into a views::ScrollView so it needs to be sized now // otherwise it'll be sized to the ScrollView's viewport height, preventing // the scroll bar from ever being shown. - pane_ = new views::View; + auto pane = std::make_unique<views::View>(); + pane_ = pane.get(); views::GridLayout* pane_layout = - pane_->SetLayoutManager(std::make_unique<views::GridLayout>(pane_)); + pane->SetLayoutManager(std::make_unique<views::GridLayout>(pane.get())); views::ColumnSet* pane_columns = pane_layout->AddColumnSet(0); pane_columns->AddColumn( views::GridLayout::Alignment::FILL, views::GridLayout::Alignment::LEADING, @@ -267,14 +268,14 @@ content_view_, ui::NativeTheme::kColorId_DialogBackground)); content_view_->set_id(static_cast<int>(DialogViewID::CONTENT_VIEW)); pane_layout->AddView(content_view_); - pane_->SizeToPreferredSize(); + pane->SizeToPreferredSize(); scroll_ = DisplayDynamicBorderForHiddenContents() ? std::make_unique<BorderedScrollView>() : std::make_unique<views::ScrollView>(); scroll_->set_owned_by_client(); scroll_->set_hide_horizontal_scrollbar(true); - scroll_->SetContents(pane_); + scroll_->SetContents(std::move(pane)); layout->AddView(scroll_.get()); if (footer) {
diff --git a/chrome/browser/ui/views/payments/validating_combobox.cc b/chrome/browser/ui/views/payments/validating_combobox.cc index 8527ac8f..7bbec03 100644 --- a/chrome/browser/ui/views/payments/validating_combobox.cc +++ b/chrome/browser/ui/views/payments/validating_combobox.cc
@@ -32,7 +32,7 @@ } void ValidatingCombobox::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.child == this && !details.is_add) being_removed_ = true; }
diff --git a/chrome/browser/ui/views/payments/validating_combobox.h b/chrome/browser/ui/views/payments/validating_combobox.h index e4ec1aa..1714ec29 100644 --- a/chrome/browser/ui/views/payments/validating_combobox.h +++ b/chrome/browser/ui/views/payments/validating_combobox.h
@@ -26,7 +26,7 @@ void OnBlur() override; // Used to keep track of our own destruction. void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // Called when the combobox contents is changed. May do validation. void OnContentsChanged();
diff --git a/chrome/browser/ui/views/payments/validating_textfield.cc b/chrome/browser/ui/views/payments/validating_textfield.cc index 04c21a2..5bd7446 100644 --- a/chrome/browser/ui/views/payments/validating_textfield.cc +++ b/chrome/browser/ui/views/payments/validating_textfield.cc
@@ -27,7 +27,7 @@ } void ValidatingTextfield::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.child == this && !details.is_add) being_removed_ = true; }
diff --git a/chrome/browser/ui/views/payments/validating_textfield.h b/chrome/browser/ui/views/payments/validating_textfield.h index 69bcbc59..fd352eb5f 100644 --- a/chrome/browser/ui/views/payments/validating_textfield.h +++ b/chrome/browser/ui/views/payments/validating_textfield.h
@@ -23,7 +23,7 @@ void OnBlur() override; // Used to keep track of our own destruction. void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // Called when the textfield contents is changed. May do validation. void OnContentsChanged();
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc index ed7c8d9e..f0adf991 100644 --- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc +++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -307,7 +307,10 @@ } gfx::ImageSkia AvatarToolbarButton::GetAvatarIcon() const { - const int icon_size = ui::MaterialDesignController::touch_ui() ? 24 : 20; + // Note that the non-touchable icon size is larger than the default to + // make the avatar icon easier to read. + const int icon_size = + ui::MaterialDesignController::touch_ui() ? kDefaultTouchableIconSize : 20; SkColor icon_color = GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index 2e53e89..7c898355 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/ui/views/profiles/profile_chooser_view.h" #include <algorithm> -#include <memory> #include <string> #include "base/bind.h" @@ -284,7 +283,7 @@ view_mode_ = view_to_display; int width_override = -1; - views::View* sub_view = nullptr; + std::unique_ptr<views::View> sub_view; switch (view_mode_) { case profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN: case profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT: @@ -301,7 +300,7 @@ break; } - SetContentsView(sub_view, width_override); + SetContentsView(std::move(sub_view), width_override); } void ProfileChooserView::ShowViewFromMode(profiles::BubbleViewMode mode) { @@ -513,11 +512,13 @@ } } -views::View* ProfileChooserView::CreateIncognitoWindowCountView() { +std::unique_ptr<views::View> +ProfileChooserView::CreateIncognitoWindowCountView() { // TODO(https://crbug.com/896235): Refactor to merge this view with other // views. - views::View* view = new views::View(); - views::GridLayout* layout = CreateSingleColumnLayout(view, menu_width()); + auto view = std::make_unique<views::View>(); + views::GridLayout* layout = + CreateSingleColumnLayout(view.get(), menu_width()); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); int content_list_vert_spacing = @@ -568,10 +569,11 @@ return view; } -views::View* ProfileChooserView::CreateProfileChooserView( +std::unique_ptr<views::View> ProfileChooserView::CreateProfileChooserView( AvatarMenu* avatar_menu) { - views::View* view = new views::View(); - views::GridLayout* layout = CreateSingleColumnLayout(view, menu_width()); + auto view = std::make_unique<views::View>(); + views::GridLayout* layout = + CreateSingleColumnLayout(view.get(), menu_width()); // Separate items into active and alternatives. Indexes other_profiles; views::View* sync_error_view = nullptr;
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.h b/chrome/browser/ui/views/profiles/profile_chooser_view.h index 68f6117e..0b8501e 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.h +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <map> +#include <memory> #include <vector> #include "base/macros.h" @@ -115,10 +116,11 @@ void FocusFirstProfileButton(); // Creates the profile chooser view. - views::View* CreateProfileChooserView(AvatarMenu* avatar_menu); + std::unique_ptr<views::View> CreateProfileChooserView( + AvatarMenu* avatar_menu); // Creates the incognito window count view. - views::View* CreateIncognitoWindowCountView(); + std::unique_ptr<views::View> CreateIncognitoWindowCountView(); // Creates the main profile card for the profile |avatar_item|. |is_guest| // is used to determine whether to show any Sign in/Sign out/Manage accounts
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index e77a4d49..1ab6a516 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/ui/views/profiles/profile_menu_view_base.h" #include <algorithm> -#include <memory> +#include <utility> #include "base/macros.h" #include "build/build_config.h" @@ -112,7 +112,7 @@ return std::max(kMinimumScrollableContentHeight, available_space); } -void ProfileMenuViewBase::SetContentsView(views::View* view, +void ProfileMenuViewBase::SetContentsView(std::unique_ptr<views::View> view, int width_override) { RemoveAllChildViews(true); if (width_override == -1) @@ -125,7 +125,7 @@ // TODO(https://crbug.com/871762): it's a workaround for the crash. scroll_view->set_draw_overflow_indicator(false); scroll_view->ClipHeightTo(0, GetMaxHeight()); - scroll_view->SetContents(view); + scroll_view->SetContents(std::move(view)); layout->StartRow(1.0, 0); layout->AddView(scroll_view);
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index a4f2ba0..3df7b049 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <map> +#include <memory> #include <vector> #include "base/macros.h" @@ -43,7 +44,7 @@ ~ProfileMenuViewBase() override; void ShowMenu(); - void SetContentsView(views::View* view, int width_override); + void SetContentsView(std::unique_ptr<views::View> view, int width_override); Browser* browser() const { return browser_; }
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc index 45d2c50..e29783f 100644 --- a/chrome/browser/ui/views/status_bubble_views.cc +++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/timer/timer.h" #include "build/build_config.h" #include "cc/paint/paint_flags.h" #include "chrome/browser/themes/theme_properties.h" @@ -76,6 +77,11 @@ constexpr auto kMaxExpansionStepDuration = base::TimeDelta::FromMilliseconds(150); +#if !defined(OS_MACOSX) +// How long to delay before destroying an unused status bubble widget. +constexpr auto kDestroyPopupDelay = base::TimeDelta::FromSeconds(10); +#endif + const gfx::FontList& GetFont() { return views::style::GetFont(views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY); @@ -164,6 +170,12 @@ void SetWidth(int new_width); + gfx::Animation* animation() { return animation_.get(); } + + bool IsDestroyPopupTimerRunning() const { + return destroy_popup_timer_.IsRunning(); + } + private: class InitialTimer; @@ -195,6 +207,11 @@ gfx::Size popup_size_; + // A timer used to delay destruction of the popup widget. This is meant to + // balance the performance tradeoffs of rapid creation/destruction and the + // memory savings of closing the widget when it's hidden and unused. + base::OneShotTimer destroy_popup_timer_; + base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_{this}; DISALLOW_COPY_AND_ASSIGN(StatusView); @@ -237,6 +254,7 @@ GetWidget()->ShowInactive(); #else GetWidget()->ShowInactive(); + destroy_popup_timer_.Stop(); #endif } @@ -250,7 +268,13 @@ // Don't orderOut: the window on macOS. Doing so for a child window requires // it to be detached/reattached, which may trigger a space switch. Instead, // just leave the window fully transparent and unclickable. - status_bubble_->DestroyPopup(); + GetWidget()->Hide(); + destroy_popup_timer_.Stop(); + // This isn't done in the constructor as tests may change the task runner + // after the fact. + destroy_popup_timer_.SetTaskRunner(status_bubble_->task_runner_); + destroy_popup_timer_.Start(FROM_HERE, kDestroyPopupDelay, status_bubble_, + &StatusBubbleViews::DestroyPopup); #endif } @@ -258,7 +282,7 @@ if (timer_factory_.HasWeakPtrs()) timer_factory_.InvalidateWeakPtrs(); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + status_bubble_->task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&StatusBubbleViews::StatusView::OnTimer, timer_factory_.GetWeakPtr()), @@ -320,6 +344,10 @@ } void StatusBubbleViews::StatusView::StartShowing() { +#if !defined(OS_MACOSX) + destroy_popup_timer_.Stop(); +#endif + if (state_ == BUBBLE_HIDDEN) { GetWidget()->ShowInactive(); state_ = BUBBLE_SHOWING_TIMER; @@ -597,7 +625,8 @@ const int StatusBubbleViews::kShadowThickness = 1; StatusBubbleViews::StatusBubbleViews(views::View* base_view) - : base_view_(base_view) {} + : base_view_(base_view), + task_runner_(base::ThreadTaskRunnerHandle::Get().get()) {} StatusBubbleViews::~StatusBubbleViews() { DestroyPopup(); @@ -746,7 +775,7 @@ ExpandBubble(); } else if (url_formatter::FormatUrl(url).length() > url_text_.length()) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + task_runner_->PostDelayedTask( FROM_HERE, base::BindOnce(&StatusBubbleViews::ExpandBubble, expand_timer_factory_.GetWeakPtr()), @@ -792,6 +821,7 @@ } void StatusBubbleViews::AvoidMouse(const gfx::Point& location) { + DCHECK(view_); // Get the position of the frame. gfx::Point top_left; views::View::ConvertPointToScreen(base_view_, &top_left); @@ -930,3 +960,11 @@ if (expand_timer_factory_.HasWeakPtrs()) expand_timer_factory_.InvalidateWeakPtrs(); } + +gfx::Animation* StatusBubbleViews::GetShowHideAnimationForTest() { + return view_ ? view_->animation() : nullptr; +} + +bool StatusBubbleViews::IsDestroyPopupTimerRunningForTest() { + return view_ && view_->IsDestroyPopupTimerRunning(); +}
diff --git a/chrome/browser/ui/views/status_bubble_views.h b/chrome/browser/ui/views/status_bubble_views.h index a5df98a8..60e3dc23 100644 --- a/chrome/browser/ui/views/status_bubble_views.h +++ b/chrome/browser/ui/views/status_bubble_views.h
@@ -15,7 +15,11 @@ #include "ui/gfx/geometry/rect.h" #include "url/gurl.h" +namespace base { +class SequencedTaskRunner; +} namespace gfx { +class Animation; class Point; } namespace views { @@ -108,6 +112,9 @@ // Set the bounds of the bubble relative to |base_view_|. void SetBounds(int x, int y, int w, int h); + gfx::Animation* GetShowHideAnimationForTest(); + bool IsDestroyPopupTimerRunningForTest(); + // The status text we want to display when there are no URLs to display. base::string16 status_text_; @@ -132,8 +139,8 @@ // How vertically offset the bubble is from its root position_. int offset_ = 0; - // We use a HWND for the popup so that it may float above any HWNDs in our - // UI (the location bar, for example). + // Use a Widget for the popup so that it floats above all content as well as + // going outside the bounds of the hosting widget. std::unique_ptr<views::Widget> popup_; views::View* base_view_; @@ -149,6 +156,11 @@ // change size immediately, with no hover. bool is_expanded_ = false; + // Used for posting tasks. This is typically + // base::ThreadTaskRunnerHandle::Get(), but may be set to something else for + // tests. + base::SequencedTaskRunner* task_runner_; + // Times expansion of status bubble when URL is too long for standard width. base::WeakPtrFactory<StatusBubbleViews> expand_timer_factory_{this};
diff --git a/chrome/browser/ui/views/status_bubble_views_browsertest.cc b/chrome/browser/ui/views/status_bubble_views_browsertest.cc index 1c97efd2..2972d10 100644 --- a/chrome/browser/ui/views/status_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/status_bubble_views_browsertest.cc
@@ -6,23 +6,39 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/views/status_bubble_views_browsertest_mac.h" #include "chrome/test/base/in_process_browser_test.h" -#include "ui/views/test/widget_test.h" +#include "ui/gfx/animation/animation.h" #include "ui/views/widget/widget.h" class StatusBubbleViewsTest : public InProcessBrowserTest { public: - StatusBubble* GetBubble() { return browser()->window()->GetStatusBubble(); } - views::Widget* GetWidget() { - return static_cast<StatusBubbleViews*>(GetBubble())->popup(); + StatusBubbleViews* GetBubble() { + return static_cast<StatusBubbleViews*>( + browser()->window()->GetStatusBubble()); + } + views::Widget* GetWidget() { return GetBubble()->popup(); } + bool IsDestroyPopupTimerRunning() { + return GetBubble()->IsDestroyPopupTimerRunningForTest(); + } + gfx::Animation* GetShowHideAnimationForTesting() { + return GetBubble()->GetShowHideAnimationForTest(); + } + void SetTaskRunner(base::SequencedTaskRunner* task_runner) { + GetBubble()->task_runner_ = task_runner; } }; IN_PROC_BROWSER_TEST_F(StatusBubbleViewsTest, WidgetLifetime) { + scoped_refptr<base::TestSimpleTaskRunner> task_runner = + base::MakeRefCounted<base::TestSimpleTaskRunner>(); + SetTaskRunner(task_runner.get()); + // The widget does not exist until it needs to be shown. StatusBubble* bubble = GetBubble(); ASSERT_TRUE(bubble); @@ -44,14 +60,77 @@ #if !defined(OS_MACOSX) // Clearing the URL and status closes the widget on platforms other than Mac. - views::test::WidgetClosingObserver widget_closing_observer(widget); + EXPECT_FALSE(IsDestroyPopupTimerRunning()); bubble->SetStatus(base::string16()); bubble->SetURL(GURL()); - widget_closing_observer.Wait(); - EXPECT_TRUE(widget_closing_observer.widget_closed()); + // The widget is not hidden immediately, instead a task is scheduled. Run that + // now. + task_runner->RunPendingTasks(); + // After the task, a timer is created that animates hidden. Advance that. + ASSERT_TRUE(GetShowHideAnimationForTesting()); + // Advance well past the time for the animation to ensure it completes. + static_cast<gfx::AnimationContainerElement*>(GetShowHideAnimationForTesting()) + ->Step(base::TimeTicks::Now() + base::TimeDelta::FromMinutes(1)); + // Widget should still exist. + ASSERT_TRUE(GetWidget()); + EXPECT_FALSE(widget->IsVisible()); + EXPECT_TRUE(IsDestroyPopupTimerRunning()); + + // Run until idle, which should trigger deleting the widget. + task_runner->RunUntilIdle(); + EXPECT_FALSE(IsDestroyPopupTimerRunning()); + EXPECT_FALSE(GetWidget()); #endif + SetTaskRunner(base::ThreadTaskRunnerHandle::Get().get()); } +// Mac does not delete the widget after a delay, so this test only runs on +// non-mac platforms. +#if !defined(OS_MACOSX) +IN_PROC_BROWSER_TEST_F(StatusBubbleViewsTest, ShowHideDestroyShow) { + scoped_refptr<base::TestSimpleTaskRunner> task_runner = + base::MakeRefCounted<base::TestSimpleTaskRunner>(); + SetTaskRunner(task_runner.get()); + + // The widget does not exist until it needs to be shown. + StatusBubble* bubble = GetBubble(); + ASSERT_TRUE(bubble); + + // Setting status text shows the widget. + bubble->SetStatus(base::ASCIIToUTF16("test")); + views::Widget* widget = GetWidget(); + ASSERT_TRUE(widget); + EXPECT_TRUE(widget->IsVisible()); + + bubble->SetStatus(base::string16()); + // The widget is not hidden immediately, instead a task is scheduled. Run that + // now. + task_runner->RunPendingTasks(); + // After the task, a timer is created that animates hidden. Advance that. + ASSERT_TRUE(GetShowHideAnimationForTesting()); + // Advance well past the time for the animation to ensure it completes. + static_cast<gfx::AnimationContainerElement*>(GetShowHideAnimationForTesting()) + ->Step(base::TimeTicks::Now() + base::TimeDelta::FromMinutes(1)); + // Widget should still exist. + ASSERT_TRUE(GetWidget()); + EXPECT_FALSE(widget->IsVisible()); + EXPECT_TRUE(IsDestroyPopupTimerRunning()); + + // Run until idle, which should trigger deleting the widget. + task_runner->RunUntilIdle(); + EXPECT_FALSE(IsDestroyPopupTimerRunning()); + EXPECT_FALSE(GetWidget()); + + // Setting status text shows the widget. + bubble->SetStatus(base::ASCIIToUTF16("test")); + widget = GetWidget(); + ASSERT_TRUE(widget); + EXPECT_TRUE(widget->IsVisible()); + + SetTaskRunner(base::ThreadTaskRunnerHandle::Get().get()); +} +#endif + // Ensure the status bubble does not close itself on Mac. Doing so can trigger // unwanted space switches due to rdar://9037452. See https://crbug.com/866760. IN_PROC_BROWSER_TEST_F(StatusBubbleViewsTest, NeverHideOrCloseOnMac) { @@ -68,10 +147,11 @@ // However, it is fully transparent. EXPECT_TRUE(widget->IsVisible()); EXPECT_EQ(0.f, test::GetNativeWindowAlphaValue(widget->GetNativeWindow())); + EXPECT_FALSE(IsDestroyPopupTimerRunning()); #else - views::test::WidgetClosingObserver widget_closing_observer(widget); + EXPECT_FALSE(IsDestroyPopupTimerRunning()); bubble->Hide(); - widget_closing_observer.Wait(); - EXPECT_TRUE(widget_closing_observer.widget_closed()); + EXPECT_FALSE(widget->IsVisible()); + EXPECT_TRUE(IsDestroyPopupTimerRunning()); #endif }
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 9e686ef..9551dc9c 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
@@ -147,7 +147,7 @@ } void ProfileSigninConfirmationDialogViews::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { views::DialogDelegateView::ViewHierarchyChanged(details); if (!details.is_add || details.child != this) return;
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 e82da04..abd3cc2c 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
@@ -47,7 +47,7 @@ bool Cancel() override; ui::ModalType GetModalType() const override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // views::WidgetDelegate:: void WindowClosing() override;
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc index 878f092..653db3d5 100644 --- a/chrome/browser/ui/views/task_manager_view.cc +++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -27,6 +27,7 @@ #include "ui/base/models/table_model_observer.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/table/table_view.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/view.h" @@ -332,17 +333,18 @@ } // Create the table view. - tab_table_ = - new views::TableView(nullptr, columns_, views::ICON_AND_TEXT, false); + auto tab_table = std::make_unique<views::TableView>( + nullptr, columns_, views::ICON_AND_TEXT, false); + tab_table_ = tab_table.get(); table_model_.reset(new TaskManagerTableModel(this)); - tab_table_->SetModel(table_model_.get()); - tab_table_->SetGrouper(this); - tab_table_->set_observer(this); - tab_table_->set_context_menu_controller(this); + tab_table->SetModel(table_model_.get()); + tab_table->SetGrouper(this); + tab_table->set_observer(this); + tab_table->set_context_menu_controller(this); set_context_menu_controller(this); - tab_table_parent_ = tab_table_->CreateParentIfNecessary(); - AddChildView(tab_table_parent_); + tab_table_parent_ = AddChildView( + views::TableView::CreateScrollViewWithTable(std::move(tab_table))); SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc index f8e1444..9b90128 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -758,7 +758,7 @@ } void BrowserActionsContainer::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (!toolbar_actions_bar_->enabled()) return;
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.h b/chrome/browser/ui/views/toolbar/browser_actions_container.h index e98ac1f..ab8740f 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.h +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.h
@@ -255,7 +255,7 @@ protected: // Overridden from views::View: void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; void OnPaint(gfx::Canvas* canvas) override; private:
diff --git a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc index 3aee72c..e76c5a2c 100644 --- a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc +++ b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc
@@ -39,8 +39,9 @@ SetBackgroundColor(SK_ColorTRANSPARENT); BrowserActionsContainer* main = toolbar_button_provider->GetBrowserActionsContainer(); - container_ = new BrowserActionsContainer(browser_, main, main->delegate()); - SetContents(container_); + auto container = std::make_unique<BrowserActionsContainer>(browser_, main, + main->delegate()); + container_ = SetContents(std::move(container)); // Listen for the drop to finish so we can close the app menu, if necessary. toolbar_actions_bar_observer_.Add(main->toolbar_actions_bar());
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc index f51401b..5599326 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -263,7 +263,7 @@ } void ToolbarActionView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && !called_register_command_ && GetFocusManager()) { view_controller_->RegisterCommand(); called_register_command_ = true;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h index 0e06771e..43a27cf 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -105,7 +105,7 @@ void OnGestureEvent(ui::GestureEvent* event) override; void OnDragDone() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // ToolbarActionViewDelegateViews: views::View* GetAsView() override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h index b86afc3..0f3d1ba 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -117,6 +117,9 @@ // Sets |layout_inset_delta_|, see comment there. void SetLayoutInsetDelta(const gfx::Insets& insets); + static constexpr int kDefaultIconSize = 16; + static constexpr int kDefaultTouchableIconSize = 24; + private: friend test::ToolbarButtonTestApi;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 584aee4..ae164f7 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/media/router/media_router_feature.h" @@ -35,7 +36,7 @@ #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" #include "chrome/browser/ui/views/extensions/extension_popup.h" -#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/location_bar/star_view.h" #include "chrome/browser/ui/views/media_router/cast_toolbar_button.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -229,6 +230,9 @@ browser_actions_ = new BrowserActionsContainer(browser_, main_container, this); + if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) + extensions_button_ = new ExtensionsToolbarButton(browser_); + if (media_router::MediaRouterEnabled(browser_->profile())) cast_ = media_router::CastToolbarButton::Create(browser_).release(); @@ -264,6 +268,10 @@ AddChildView(home_); AddChildView(location_bar_); AddChildView(browser_actions_); + + if (extensions_button_) + AddChildView(extensions_button_); + if (cast_) AddChildView(cast_); @@ -789,6 +797,8 @@ home_->SetImage(views::Button::STATE_NORMAL, gfx::CreateVectorIcon(home_image, normal_color)); + if (extensions_button_) + extensions_button_->UpdateIcon(); if (cast_) cast_->UpdateIcon(); if (avatar_)
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index c1f9574..6ac645f 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -40,6 +40,7 @@ class AvatarToolbarButton; class BrowserAppMenuButton; class Browser; +class ExtensionsToolbarButton; class HomeButton; class ReloadButton; class ToolbarButton; @@ -252,6 +253,7 @@ CustomTabBarView* custom_tab_bar_ = nullptr; LocationBarView* location_bar_ = nullptr; BrowserActionsContainer* browser_actions_ = nullptr; + ExtensionsToolbarButton* extensions_button_ = nullptr; media_router::CastToolbarButton* cast_ = nullptr; ToolbarPageActionIconContainerView* toolbar_page_action_container_ = nullptr; AvatarToolbarButton* avatar_ = nullptr;
diff --git a/chrome/browser/ui/views/webauthn/hover_list_view.cc b/chrome/browser/ui/views/webauthn/hover_list_view.cc index da1d1534..41917f1 100644 --- a/chrome/browser/ui/views/webauthn/hover_list_view.cc +++ b/chrome/browser/ui/views/webauthn/hover_list_view.cc
@@ -100,11 +100,12 @@ DCHECK(model_); SetLayoutManager(std::make_unique<views::FillLayout>()); - item_container_ = new views::View(); - item_container_->SetLayoutManager(std::make_unique<views::BoxLayout>( + auto item_container = std::make_unique<views::View>(); + item_container->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(), 0 /* betweeen_child_spacing */)); + item_container_ = item_container.get(); AddSeparatorAsChild(item_container_); for (const auto item_tag : model_->GetItemTags()) { @@ -118,7 +119,7 @@ } scroll_view_ = new views::ScrollView(); - scroll_view_->SetContents(item_container_); + scroll_view_->SetContents(std::move(item_container)); AddChildView(scroll_view_); scroll_view_->ClipHeightTo(GetPreferredViewHeight(), GetPreferredViewHeight());
diff --git a/chrome/browser/ui/webui/browser_switcher/browser_switch_ui.cc b/chrome/browser/ui/webui/browser_switcher/browser_switch_ui.cc index 9f5fd6a0..55116062 100644 --- a/chrome/browser/ui/webui/browser_switcher/browser_switch_ui.cc +++ b/chrome/browser/ui/webui/browser_switcher/browser_switch_ui.cc
@@ -29,6 +29,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" @@ -71,16 +72,38 @@ auto* service = GetBrowserSwitcherService(web_ui); source->AddInteger("launchDelay", service->prefs().GetDelay()); - source->AddLocalizedString("countdownTitle", - IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE); - source->AddLocalizedString("description", - IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION); - source->AddLocalizedString("errorTitle", - IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE); - source->AddLocalizedString("genericError", - IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR); - source->AddLocalizedString("openingTitle", - IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE); + std::string browser_name = service->driver()->GetBrowserName(); + source->AddString("browserName", browser_name); + + if (browser_name.empty()) { + // Browser name could not be auto-detected. Say "alternative browser" + // instead of naming the browser. + source->AddLocalizedString( + "countdownTitle", + IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_UNKNOWN_BROWSER); + source->AddLocalizedString( + "description", IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_UNKNOWN_BROWSER); + source->AddLocalizedString( + "errorTitle", IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_UNKNOWN_BROWSER); + source->AddLocalizedString( + "genericError", IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_UNKNOWN_BROWSER); + source->AddLocalizedString( + "openingTitle", IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_UNKNOWN_BROWSER); + } else { + // Browser name was auto-detected. Name it in the text. + source->AddLocalizedString( + "countdownTitle", + IDS_ABOUT_BROWSER_SWITCH_COUNTDOWN_TITLE_KNOWN_BROWSER); + source->AddLocalizedString( + "description", IDS_ABOUT_BROWSER_SWITCH_DESCRIPTION_KNOWN_BROWSER); + source->AddLocalizedString( + "errorTitle", IDS_ABOUT_BROWSER_SWITCH_ERROR_TITLE_KNOWN_BROWSER); + source->AddLocalizedString( + "genericError", IDS_ABOUT_BROWSER_SWITCH_GENERIC_ERROR_KNOWN_BROWSER); + source->AddLocalizedString( + "openingTitle", IDS_ABOUT_BROWSER_SWITCH_OPENING_TITLE_KNOWN_BROWSER); + } + source->AddLocalizedString("protocolError", IDS_ABOUT_BROWSER_SWITCH_PROTOCOL_ERROR); source->AddLocalizedString("title", IDS_ABOUT_BROWSER_SWITCH_TITLE);
diff --git a/chrome/browser/ui/webui/chromeos/OWNERS b/chrome/browser/ui/webui/chromeos/OWNERS index 0c7e289..d5176c5 100644 --- a/chrome/browser/ui/webui/chromeos/OWNERS +++ b/chrome/browser/ui/webui/chromeos/OWNERS
@@ -4,5 +4,5 @@ stevenjb@chromium.org xiyuan@chromium.org -per-file network*=stevenjb@chromium.org +per-file network*=file://chromeos/network/OWNERS per-file drive_internals_ui.*=file://ui/file_manager/OWNERS
diff --git a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc index e5a0d66f..9e32b124 100644 --- a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
@@ -114,6 +114,8 @@ AddCallback("eulaOnLearnMore", &EulaScreenHandler::HandleOnLearnMore); AddCallback("eulaOnInstallationSettingsPopupOpened", &EulaScreenHandler::HandleOnInstallationSettingsPopupOpened); + AddCallback("EulaScreen.usageStatsEnabled", + &EulaScreenHandler::HandleUsageStatsEnabled); } void EulaScreenHandler::GetAdditionalParameters(base::DictionaryValue* dict) { @@ -152,6 +154,11 @@ screen_->InitiatePasswordFetch(); } +void EulaScreenHandler::HandleUsageStatsEnabled(bool enabled) { + if (screen_) + screen_->SetUsageStatsEnabled(enabled); +} + void EulaScreenHandler::UpdateLocalizedValues( ::login::SecureModuleUsed secure_module_used) { base::DictionaryValue updated_secure_module_strings;
diff --git a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h index 13092f3..df8d8c8 100644 --- a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
@@ -48,6 +48,7 @@ // JS messages handlers. void HandleOnLearnMore(); void HandleOnInstallationSettingsPopupOpened(); + void HandleUsageStatsEnabled(bool enabled); void UpdateLocalizedValues(::login::SecureModuleUsed secure_module_used);
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc index 1859454..2d85992 100644 --- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -184,4 +184,25 @@ CallJS("login.UserImageScreen.hideCurtain"); } +void UserImageScreenHandler::SetIsCameraPresent(bool value) { + CallJS("login.UserImageScreen.setIsCameraPresent", value); +} + +void UserImageScreenHandler::SetProfilePictureDataURL( + const std::string& value) { + CallJS("login.UserImageScreen.setProfilePictureDataURL", value); +} + +void UserImageScreenHandler::SetIsProfilePictureAvailable(bool value) { + CallJS("login.UserImageScreen.setIsProfilePictureAvailable", value); +} + +void UserImageScreenHandler::SetSelectedImageIndex(int value) { + CallJS("login.UserImageScreen.setSelectedImageIndex", value); +} + +void UserImageScreenHandler::SetSelectedImageURL(const std::string& value) { + CallJS("login.UserImageScreen.setSelectedImageURL", value); +} + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h index 3fea9aa..337a27e2 100644 --- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
@@ -39,6 +39,11 @@ void Show() override; void Hide() override; void HideCurtain() override; + void SetIsCameraPresent(bool value) override; + void SetProfilePictureDataURL(const std::string& value) override; + void SetIsProfilePictureAvailable(bool value) override; + void SetSelectedImageIndex(int value) override; + void SetSelectedImageURL(const std::string& value) override; // Sends image data to the page. void HandleGetImages();
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals.mojom b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom index 351138d..4382879 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals.mojom +++ b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom
@@ -94,6 +94,9 @@ // Feed. ClearCachedDataAndRefreshFeed(); + // Trigger a refresh of the Feed. + RefreshFeed(); + // Get the last known content with metadata. GetCurrentContent() => (array<Suggestion> suggestions);
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc index 3fdb4b9..e210b27 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
@@ -111,6 +111,10 @@ feed::FeedLifecycleBridge::ClearCachedData(); } +void FeedInternalsPageHandler::RefreshFeed() { + feed::TriggerRefreshForDebugging(); +} + void FeedInternalsPageHandler::GetCurrentContent( GetCurrentContentCallback callback) { if (!IsFeedAllowed()) { @@ -142,6 +146,7 @@ std::move(callback).Run(std::move(suggestions)); } + void FeedInternalsPageHandler::GetFeedProcessScopeDump( GetFeedProcessScopeDumpCallback callback) { std::move(callback).Run(feed::GetFeedProcessScopeDumpForDebugging());
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h index 368bfb1..d3070c7 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
@@ -39,6 +39,7 @@ void ClearUserClassifierProperties() override; void GetLastFetchProperties(GetLastFetchPropertiesCallback) override; void ClearCachedDataAndRefreshFeed() override; + void RefreshFeed() override; void GetCurrentContent(GetCurrentContentCallback) override; void GetFeedProcessScopeDump(GetFeedProcessScopeDumpCallback) override;
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index 70f0048..46fe18f2 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -138,10 +138,7 @@ NTPResourceCache::NTPResourceCache(Profile* profile) : profile_(profile), is_swipe_tracking_from_scroll_events_enabled_(false), - dark_mode_observer_( - ui::NativeTheme::GetInstanceForNativeUi(), - base::BindRepeating(&NTPResourceCache::OnDarkModeChanged, - base::Unretained(this))) { + theme_observer_(this) { registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, content::Source<ThemeService>( ThemeServiceFactory::GetForProfile(profile))); @@ -158,7 +155,7 @@ callback); profile_pref_change_registrar_.Add(prefs::kHideWebStoreIcon, callback); - dark_mode_observer_.Start(); + theme_observer_.Add(ui::NativeTheme::GetInstanceForNativeUi()); } NTPResourceCache::~NTPResourceCache() {} @@ -239,7 +236,8 @@ Invalidate(); } -void NTPResourceCache::OnDarkModeChanged(bool /*dark_mode*/) { +void NTPResourceCache::OnNativeThemeUpdated(ui::NativeTheme* updated_theme) { + DCHECK_EQ(updated_theme, ui::NativeTheme::GetInstanceForNativeUi()); Invalidate(); } @@ -594,8 +592,8 @@ void NTPResourceCache::SetDarkKey(base::Value* dict) { DCHECK(dict && dict->is_dict()); - bool enabled = base::FeatureList::IsEnabled(features::kWebUIDarkMode); - dict->SetKey( - "dark", - base::Value(enabled && dark_mode_observer_.InDarkMode() ? "dark" : "")); + bool use_dark = + base::FeatureList::IsEnabled(features::kWebUIDarkMode) && + ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled(); + dict->SetKey("dark", base::Value(use_dark ? "dark" : "")); }
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h index d3a0791..354de3c 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
@@ -8,11 +8,12 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "chrome/browser/ui/dark_mode_observer.h" +#include "base/scoped_observer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "ui/native_theme/native_theme_observer.h" class Profile; @@ -25,12 +26,17 @@ class RenderProcessHost; } +namespace ui { +class NativeTheme; +} + // This class keeps a cache of NTP resources (HTML and CSS) so we don't have to // regenerate them all the time. // Note: This is only used for incognito and guest mode NTPs (NewTabUI), as well // as for (non-incognito) app launcher pages (AppLauncherPageUI). class NTPResourceCache : public content::NotificationObserver, - public KeyedService { + public KeyedService, + public ui::NativeThemeObserver { public: enum WindowType { NORMAL, @@ -44,7 +50,7 @@ base::RefCountedMemory* GetNewTabHTML(WindowType win_type); base::RefCountedMemory* GetNewTabCSS(WindowType win_type); - // content::NotificationObserver interface. + // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; @@ -53,9 +59,10 @@ Profile* profile, content::RenderProcessHost* render_host); private: - void OnPreferenceChanged(); + // ui::NativeThemeObserver: + void OnNativeThemeUpdated(ui::NativeTheme* updated_theme) override; - void OnDarkModeChanged(bool dark_mode); + void OnPreferenceChanged(); // Invalidates the NTPResourceCache. void Invalidate(); @@ -90,7 +97,7 @@ // Set based on platform_util::IsSwipeTrackingFromScrollEventsEnabled. bool is_swipe_tracking_from_scroll_events_enabled_; - DarkModeObserver dark_mode_observer_; + ScopedObserver<ui::NativeTheme, NTPResourceCache> theme_observer_; DISALLOW_COPY_AND_ASSIGN(NTPResourceCache); };
diff --git a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc index 946af1c1..0c17e0c 100644 --- a/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc +++ b/chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc
@@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" @@ -37,6 +38,7 @@ source->AddString("pageHeading", page_heading); source->SetDefaultResource(IDR_PAGE_NOT_AVAILABLE_FOR_GUEST_APP_HTML); + source->SetJsonPath("strings.js"); return source; } @@ -48,5 +50,7 @@ const std::string& host_name) : WebUIController(web_ui) { Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, CreateHTMLSource(profile, host_name)); + auto* source = CreateHTMLSource(profile, host_name); + DarkModeHandler::Initialize(web_ui, source); + content::WebUIDataSource::Add(profile, source); }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 6d373f6..3736fe3 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -240,6 +240,7 @@ case chromeos::PrinterSetupResult::kInvalidPrinterUpdate: case chromeos::PrinterSetupResult::kDbusNoReply: case chromeos::PrinterSetupResult::kDbusTimeout: + case chromeos::PrinterSetupResult::kEditSuccess: LOG(ERROR) << "Unexpected error in printer setup. " << result; break; case chromeos::PrinterSetupResult::kMaxValue:
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc index a0b9428..b1982c6 100644 --- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -124,6 +124,7 @@ crostini::CrostiniSharePath::GetForProfile(profile_)->UnsharePath( crostini::kCrostiniDefaultVmName, base::FilePath(path), + /*unpersist=*/true, base::BindOnce( [](const std::string& path, bool result, std::string failure_reason) { if (!result) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 28b9e86..efc839dc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -359,21 +359,20 @@ PRINTER_LOG(DEBUG) << "HandleAddCupsPrinter() called when " "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. - OnAddedPrinterCommon(printer, - PrinterSetupResult::kNativePrintersNotAllowed, - false); + OnAddedOrEditedPrinterCommon( + printer, PrinterSetupResult::kNativePrintersNotAllowed, false); // Used to fire the web UI listener. - OnAddPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); + OnAddOrEditPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); return; } PRINTER_LOG(USER) << "Comitting printer update"; printers_manager_->UpdateConfiguredPrinter(printer); - // TODO(xdai): Replace "on-add-cups-printer" callback with Promise resolve - // function. - FireWebUIListener("on-add-cups-printer", - base::Value(PrinterSetupResult::kSuccess), + // TODO(xdai): Replace "on-add-or-edit-cups-printer" callback with Promise + // resolve function. + FireWebUIListener("on-add-or-edit-cups-printer", + base::Value(PrinterSetupResult::kEditSuccess), base::Value(printer_name)); } @@ -562,7 +561,7 @@ std::unique_ptr<Printer> printer = DictToPrinter(*printer_dict); if (!printer) { PRINTER_LOG(ERROR) << "Failed to parse printer URI"; - OnAddPrinterError(PrinterSetupResult::kFatalError); + OnAddOrEditPrinterError(PrinterSetupResult::kFatalError); return; } @@ -570,11 +569,10 @@ PRINTER_LOG(DEBUG) << "HandleAddCupsPrinter() called when " "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. - OnAddedPrinterCommon(*printer, - PrinterSetupResult::kNativePrintersNotAllowed, - false); + OnAddedOrEditedPrinterCommon( + *printer, PrinterSetupResult::kNativePrintersNotAllowed, false); // Used to fire the web UI listener. - OnAddPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); + OnAddOrEditPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); return; } @@ -582,19 +580,20 @@ // If the returned optional does not contain a value then it means that the // printer's uri was not able to be parsed successfully. PRINTER_LOG(ERROR) << "Failed to parse printer URI"; - OnAddPrinterError(PrinterSetupResult::kFatalError); + OnAddOrEditPrinterError(PrinterSetupResult::kFatalError); return; } // If the provided printer already exists, grab the existing printer object - // and check that we are not making any changes that will make the printer - // unusable. - if (!printer->id().empty()) { + // and check that we are not making any changes that will make the + // printerexisting_printer unusable. + const bool is_existing_printer = !printer->id().empty(); + if (is_existing_printer) { std::unique_ptr<Printer> existing_printer = printers_manager_->GetPrinter(printer->id()); if (existing_printer) { if (!IsValidUriChange(*existing_printer, *printer)) { - OnAddPrinterError(PrinterSetupResult::kInvalidPrinterUpdate); + OnAddOrEditPrinterError(PrinterSetupResult::kInvalidPrinterUpdate); return; } } @@ -622,7 +621,7 @@ GURL tmp = net::FilePathToFileURL(base::FilePath(printer_ppd_path)); if (!tmp.is_valid()) { LOG(ERROR) << "Invalid ppd path: " << printer_ppd_path; - OnAddPrinterError(PrinterSetupResult::kInvalidPpd); + OnAddOrEditPrinterError(PrinterSetupResult::kInvalidPpd); return; } printer->mutable_ppd_reference()->user_supplied_ppd_url = tmp.spec(); @@ -640,7 +639,7 @@ } if (!found) { LOG(ERROR) << "Failed to get ppd reference"; - OnAddPrinterError(PrinterSetupResult::kPpdNotFound); + OnAddOrEditPrinterError(PrinterSetupResult::kPpdNotFound); return; } @@ -660,13 +659,15 @@ } printer_configurer_->SetUpPrinter( - *printer, base::Bind(&CupsPrintersHandler::OnAddedSpecifiedPrinter, - weak_factory_.GetWeakPtr(), *printer)); + *printer, base::BindOnce( + &CupsPrintersHandler::OnAddedOrEditedSpecifiedPrinter, + weak_factory_.GetWeakPtr(), *printer, is_existing_printer)); } -void CupsPrintersHandler::OnAddedPrinterCommon(const Printer& printer, - PrinterSetupResult result_code, - bool is_automatic) { +void CupsPrintersHandler::OnAddedOrEditedPrinterCommon( + const Printer& printer, + PrinterSetupResult result_code, + bool is_automatic) { UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterSetupResult", result_code, PrinterSetupResult::kMaxValue); switch (result_code) { @@ -675,6 +676,9 @@ printer.GetProtocol(), Printer::kProtocolMax); PRINTER_LOG(USER) << "Performing printer setup"; printers_manager_->PrinterInstalled(printer, is_automatic); + return; + case PrinterSetupResult::kEditSuccess: + PRINTER_LOG(USER) << "Printer updated"; printers_manager_->UpdateConfiguredPrinter(printer); return; case PrinterSetupResult::kPpdNotFound: @@ -725,9 +729,9 @@ void CupsPrintersHandler::OnAddedDiscoveredPrinter( const Printer& printer, PrinterSetupResult result_code) { - OnAddedPrinterCommon(printer, result_code, true); + OnAddedOrEditedPrinterCommon(printer, result_code, true); if (result_code == PrinterSetupResult::kSuccess) { - FireWebUIListener("on-add-cups-printer", base::Value(result_code), + FireWebUIListener("on-add-or-edit-cups-printer", base::Value(result_code), base::Value(printer.display_name())); } else { PRINTER_LOG(EVENT) << "Automatic setup failed for discovered printer. " @@ -737,18 +741,23 @@ } } -void CupsPrintersHandler::OnAddedSpecifiedPrinter( +void CupsPrintersHandler::OnAddedOrEditedSpecifiedPrinter( const Printer& printer, + bool is_printer_edit, PrinterSetupResult result_code) { - PRINTER_LOG(EVENT) << "Add manual printer: " << result_code; - OnAddedPrinterCommon(printer, result_code, false); - FireWebUIListener("on-add-cups-printer", base::Value(result_code), + if (is_printer_edit && result_code == PrinterSetupResult::kSuccess) { + result_code = PrinterSetupResult::kEditSuccess; + } + PRINTER_LOG(EVENT) << "Add/Update manual printer: " << result_code; + OnAddedOrEditedPrinterCommon(printer, result_code, false); + FireWebUIListener("on-add-or-edit-cups-printer", base::Value(result_code), base::Value(printer.display_name())); } -void CupsPrintersHandler::OnAddPrinterError(PrinterSetupResult result_code) { +void CupsPrintersHandler::OnAddOrEditPrinterError( + PrinterSetupResult result_code) { PRINTER_LOG(EVENT) << "Add printer error: " << result_code; - FireWebUIListener("on-add-cups-printer", base::Value(result_code), + FireWebUIListener("on-add-or-edit-cups-printer", base::Value(result_code), base::Value("")); } @@ -960,7 +969,7 @@ PRINTER_LOG(ERROR) << "Discovered printer disappeared"; // Printer disappeared, so we don't have information about it anymore and // can't really do much. Fail the add. - FireWebUIListener("on-add-cups-printer", base::Value(false), + FireWebUIListener("on-add-or-edit-cups-printer", base::Value(false), base::Value(printer_id)); return; } @@ -968,7 +977,7 @@ if (!printer->GetUriComponents().has_value()) { PRINTER_LOG(DEBUG) << "Could not parse uri"; // The printer uri was not parsed successfully. Fail the add. - FireWebUIListener("on-add-cups-printer", base::Value(false), + FireWebUIListener("on-add-or-edit-cups-printer", base::Value(false), base::Value(printer_id)); return; }
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index 0362548..b1cc3107 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -91,12 +91,13 @@ // Handles the result of adding a printer which the user specified the // location of (i.e. a printer that was not 'discovered' automatically). - void OnAddedSpecifiedPrinter(const Printer& printer, - PrinterSetupResult result); + void OnAddedOrEditedSpecifiedPrinter(const Printer& printer, + bool is_existing_printer, + PrinterSetupResult result); // Handles the result of failure to add a printer. |result_code| is used to // determine the reason for the failure. - void OnAddPrinterError(PrinterSetupResult result_code); + void OnAddOrEditPrinterError(PrinterSetupResult result_code); // Get a list of all manufacturers for which we have at least one model of // printer supported. Takes one argument, the callback id for the result. @@ -146,9 +147,9 @@ PrinterSetupResult result_code); // Code common between the discovered and manual add printer code paths. - void OnAddedPrinterCommon(const Printer& printer, - PrinterSetupResult result_code, - bool is_automatic); + void OnAddedOrEditedPrinterCommon(const Printer& printer, + PrinterSetupResult result_code, + bool is_automatic); // CupsPrintersManager::Observer override: void OnPrintersChanged(CupsPrintersManager::PrinterClass printer_class,
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index feeb804..54669195f 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1256,6 +1256,8 @@ IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING}, {"networkAlwaysOnVpn", IDS_SETTINGS_INTERNET_NETWORK_ALWAYS_ON_VPN}, {"networkAutoConnect", IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT}, + {"networkAutoConnectCellular", + IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT_CELLULAR}, {"networkButtonActivate", IDS_SETTINGS_INTERNET_BUTTON_ACTIVATE}, {"networkButtonConfigure", IDS_SETTINGS_INTERNET_BUTTON_CONFIGURE}, {"networkButtonConnect", IDS_SETTINGS_INTERNET_BUTTON_CONNECT}, @@ -2014,6 +2016,8 @@ IDS_SETTINGS_PRINTING_CUPS_PRINTER_INVALID_DRIVER}, {"printerAddedSuccessfulMessage", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_DONE_MESSAGE}, + {"printerEditedSuccessfulMessage", + IDS_SETTINGS_PRINTING_CUPS_PRINTER_EDITED_PRINTER_DONE_MESSAGE}, {"noPrinterNearbyMessage", IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_PRINTER_NEARBY}, {"searchingNearbyPrinters",
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc index efc72f6..5f4916c 100644 --- a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc +++ b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -21,6 +21,8 @@ source->AddResourcePath("usb_internals.js", IDR_USB_INTERNALS_JS); source->AddResourcePath("usb_internals.mojom-lite.js", IDR_USB_INTERNALS_MOJOM_LITE_JS); + source->AddResourcePath("descriptor_panel.js", + IDR_USB_INTERNALS_DESCRIPTOR_PANEL_JS); source->AddResourcePath("devices_page.js", IDR_USB_INTERNALS_DEVICES_PAGE_JS); source->AddResourcePath("device.mojom-lite.js", IDR_USB_DEVICE_MOJOM_LITE_JS); source->AddResourcePath("device_enumeration_options.mojom-lite.js",
diff --git a/chrome/browser/ui/webui/webapks_handler.cc b/chrome/browser/ui/webui/webapks_handler.cc index f7f529a..73e48ff 100644 --- a/chrome/browser/ui/webui/webapks_handler.cc +++ b/chrome/browser/ui/webui/webapks_handler.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/android/color_helpers.h" #include "chrome/browser/android/shortcut_helper.h" #include "content/public/browser/web_ui.h" -#include "content/public/common/manifest_util.h" +#include "third_party/blink/public/common/manifest/manifest_util.h" #include "ui/gfx/color_utils.h" WebApksHandler::WebApksHandler() : weak_ptr_factory_(this) {} @@ -50,10 +50,10 @@ result->SetString("manifestUrl", webapk_info.manifest_url); result->SetString("manifestStartUrl", webapk_info.manifest_start_url); result->SetString("displayMode", - content::WebDisplayModeToString(webapk_info.display)); + blink::WebDisplayModeToString(webapk_info.display)); result->SetString( "orientation", - content::WebScreenOrientationLockTypeToString(webapk_info.orientation)); + blink::WebScreenOrientationLockTypeToString(webapk_info.orientation)); result->SetString("themeColor", OptionalSkColorToString(webapk_info.theme_color)); result->SetString("backgroundColor",
diff --git a/chrome/browser/ui/webui/welcome/nux/constants.cc b/chrome/browser/ui/webui/welcome/nux/constants.cc index 5ed970a..fec9cc9 100644 --- a/chrome/browser/ui/webui/welcome/nux/constants.cc +++ b/chrome/browser/ui/webui/welcome/nux/constants.cc
@@ -9,15 +9,21 @@ namespace nux { const base::Feature kNuxOnboardingFeature{"NuxOnboarding", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; + +// nux-ntp-background should not be added here until we can guarantee that +// kUseGoogleLocalNtp is enabled +const char kDefaultNewUserModules[] = + "nux-google-apps,nux-email,nux-set-as-default,signin-view"; +const char kDefaultReturningUserModules[] = "nux-set-as-default"; // The value of these FeatureParam values should be a comma-delimited list // of element names whitelisted in the MODULES_WHITELIST list, defined in // chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js const base::FeatureParam<std::string> kNuxOnboardingNewUserModules{ - &kNuxOnboardingFeature, "new-user-modules", - "nux-google-apps,nux-email,nux-set-as-default,signin-view"}; + &kNuxOnboardingFeature, "new-user-modules", kDefaultNewUserModules}; const base::FeatureParam<std::string> kNuxOnboardingReturningUserModules{ - &kNuxOnboardingFeature, "returning-user-modules", "nux-set-as-default"}; + &kNuxOnboardingFeature, "returning-user-modules", + kDefaultReturningUserModules}; } // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux/constants.h b/chrome/browser/ui/webui/welcome/nux/constants.h index 0ea4f52d..e79cd970 100644 --- a/chrome/browser/ui/webui/welcome/nux/constants.h +++ b/chrome/browser/ui/webui/welcome/nux/constants.h
@@ -16,6 +16,9 @@ extern const base::Feature kNuxOnboardingFeature; +extern const char kDefaultNewUserModules[]; +extern const char kDefaultReturningUserModules[]; + extern const base::FeatureParam<std::string> kNuxOnboardingNewUserModules; extern const base::FeatureParam<std::string> kNuxOnboardingReturningUserModules; extern const base::FeatureParam<bool> kNuxOnboardingShowEmailInterstitial;
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.cc b/chrome/browser/ui/webui/welcome/nux_helper.cc index 603f113..980426a 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.cc +++ b/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -13,7 +13,10 @@ #include "build/build_config.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/ntp_features.h" +#include "chrome/browser/search/search.h" #include "chrome/browser/ui/webui/welcome/nux/constants.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" @@ -39,10 +42,28 @@ &kNuxOnboardingForceEnabled, "returning-user-modules", "nux-set-as-default"}; +// Our current running experiment of testing the nux-ntp-background module +// depends on the Local NTP feature/experiment being enabled. To avoid polluting +// our data with users who cannot use the nux-ntp-background module, we need +// to check to make sure the Local NTP feature is enabled before running +// any experiment or even reading any feature params from our experiment. +bool CanExperimentWithVariations(Profile* profile) { + return (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceLocalNtp) || + base::FeatureList::IsEnabled(features::kUseGoogleLocalNtp)) && + search::DefaultSearchProviderIsGoogle(profile); +} + // Must match study name in configs. const char kNuxOnboardingStudyName[] = "NaviOnboarding"; -std::string GetOnboardingGroup() { +std::string GetOnboardingGroup(Profile* profile) { + if (!CanExperimentWithVariations(profile)) { + // If we cannot run any variations, we bucket the users into a separate + // synthetic group that we will ignore data for. + return "NaviNoVariationSynthetic"; + } + // We need to use |base::GetFieldTrialParamValue| instead of // |base::FeatureParam| because our control group needs a custom value for // this param. @@ -73,9 +94,14 @@ std::string onboard_group = prefs->GetString(prefs::kNaviOnboardGroup); if (onboard_group.empty()) { + // Users who onboarded before Navi or are part of an enterprise. return false; } + if (!CanExperimentWithVariations(profile)) { + return true; // Default Navi behavior. + } + // User will be tied to their original onboarding group, even after // experiment ends. ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( @@ -102,10 +128,14 @@ kNuxOnboardingForceEnabledNewUserModules.Get()); modules.SetString("returning-user", kNuxOnboardingForceEnabledReturningUserModules.Get()); - } else { // This means |nux::kNuxOnboardingFeature| is enabled. + } else if (CanExperimentWithVariations(profile)) { modules.SetString("new-user", kNuxOnboardingNewUserModules.Get()); modules.SetString("returning-user", kNuxOnboardingReturningUserModules.Get()); + } else { + // Default behavior w/o checking feature flag. + modules.SetString("new-user", kDefaultNewUserModules); + modules.SetString("returning-user", kDefaultReturningUserModules); } return modules;
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.h b/chrome/browser/ui/webui/welcome/nux_helper.h index f0368af0..a56ae37d 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.h +++ b/chrome/browser/ui/webui/welcome/nux_helper.h
@@ -34,7 +34,7 @@ // - Incremented with each new version // - Not reused // - Cleared out when experiment ends -std::string GetOnboardingGroup(); +std::string GetOnboardingGroup(Profile* profile); bool IsNuxOnboardingEnabled(Profile* profile);
diff --git a/chrome/browser/web_applications/components/web_app_helpers.cc b/chrome/browser/web_applications/components/web_app_helpers.cc index fdfc4fd..bd926ff 100644 --- a/chrome/browser/web_applications/components/web_app_helpers.cc +++ b/chrome/browser/web_applications/components/web_app_helpers.cc
@@ -6,15 +6,14 @@ #include "base/base64.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "components/crx_file/id_util.h" #include "crypto/sha2.h" #include "url/gurl.h" namespace web_app { -std::string GenerateApplicationNameFromURL(const GURL& url) { - return base::StrCat({url.host_piece(), "_", url.path_piece()}); -} +namespace { // The following string is used to build the directory name for // shortcuts to chrome applications (the kind which are installed @@ -22,7 +21,16 @@ // for the name of this directory. Hosts can't include an underscore. // By starting this string with an underscore, we ensure that there // are no naming conflicts. -static const char kCrxAppPrefix[] = "_crx_"; +const char kCrxAppPrefix[] = "_crx_"; + +const char kFocusModePrefix[] = "_focus_"; +int64_t focus_mode_counter = 0; + +} // namespace + +std::string GenerateApplicationNameFromURL(const GURL& url) { + return base::StrCat({url.host_piece(), "_", url.path_piece()}); +} std::string GenerateApplicationNameFromAppId(const AppId& app_id) { std::string t(kCrxAppPrefix); @@ -30,6 +38,12 @@ return t; } +// TODO(crbug.com/943194): Move this method to Focus Mode specific file. +// TODO(crbug.com/943653): Use site's manifest scope as window grouping key. +std::string GenerateApplicationNameForFocusMode() { + return kFocusModePrefix + base::Int64ToString(focus_mode_counter++); +} + AppId GetAppIdFromApplicationName(const std::string& app_name) { std::string prefix(kCrxAppPrefix); if (app_name.substr(0, prefix.length()) != prefix)
diff --git a/chrome/browser/web_applications/components/web_app_helpers.h b/chrome/browser/web_applications/components/web_app_helpers.h index 29ebf73..df52a16c 100644 --- a/chrome/browser/web_applications/components/web_app_helpers.h +++ b/chrome/browser/web_applications/components/web_app_helpers.h
@@ -22,6 +22,10 @@ // Compute a deterministic name based on an apps's id. std::string GenerateApplicationNameFromAppId(const AppId& app_id); +// Compute a name for Focus Mode, using counter; +// TODO(crbug.com/943194): Move this method to Focus Mode specific file. +std::string GenerateApplicationNameForFocusMode(); + // Extracts the application id from the app name. AppId GetAppIdFromApplicationName(const std::string& app_name);
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 75bf966..87ef928 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -744,7 +744,7 @@ "//components/content_settings/core/common:mojo_bindings", "//content/public/common:interfaces", "//mojo/public/mojom/base", - "//third_party/blink/public:mojo_bindings", + "//third_party/blink/public/mojom:mojom_platform", "//ui/gfx/geometry/mojo", "//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_origin", @@ -759,7 +759,7 @@ } overridden_deps = [ - "//third_party/blink/public:mojo_bindings", + "//third_party/blink/public/mojom:mojom_platform", "//content/public/common:interfaces", ]
diff --git a/chrome/common/chrome_render_frame.mojom b/chrome/common/chrome_render_frame.mojom index 8a57c12a..a352543d 100644 --- a/chrome/common/chrome_render_frame.mojom +++ b/chrome/common/chrome_render_frame.mojom
@@ -5,7 +5,7 @@ module chrome.mojom; import "mojo/public/mojom/base/string16.mojom"; -import "third_party/blink/public/web/window_features.mojom"; +import "third_party/blink/public/mojom/window_features/window_features.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; enum ImageFormat {
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index f7852fa..775e7716 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -362,6 +362,10 @@ // Causes the browser to launch directly in incognito mode. const char kIncognito[] = "incognito"; +// Installs an autogenerated theme based on the given RGB value. +// The format is "r,g,b", where r, g, b are a numeric values from 0 to 255. +const char kInstallAutogeneratedTheme[] = "install-autogenerated-theme"; + // Causes Chrome to initiate an installation flow for the given app. const char kInstallChromeApp[] = "install-chrome-app";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 04db70f..b5d6a559 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -115,6 +115,7 @@ extern const char kForceStackedTabStripLayout[]; extern const char kHomePage[]; extern const char kIncognito[]; +extern const char kInstallAutogeneratedTheme[]; extern const char kInstallChromeApp[]; extern const char kInstallSupervisedUserWhitelists[]; extern const char kInstantProcess[];
diff --git a/chrome/common/mac/app_mode_common.h b/chrome/common/mac/app_mode_common.h index 91f64402..ade21e3 100644 --- a/chrome/common/mac/app_mode_common.h +++ b/chrome/common/mac/app_mode_common.h
@@ -20,13 +20,6 @@ namespace app_mode { -// These are keys for an Apple Event ping that the app shim process sends to -// Chrome to get confirmation that Chrome is alive. The main Chrome process -// doesn't need to register any handlers for them -- the event is just sent for -// the empty reply that's automatically returned by the system. -const AEEventClass kAEChromeAppClass = 'cApp'; -const AEEventID kAEChromeAppPing = 'ping'; - // The IPC socket used to communicate between app shims and Chrome will be // created under a temporary directory with this name. extern const char kAppShimSocketShortName[]; @@ -34,6 +27,21 @@ // user data dir with this name. extern const char kAppShimSocketSymlinkName[]; +// Mach message ID used by the shim to connect to Chrome. +constexpr mach_msg_id_t kBootstrapMsgId = 'apps'; + +// Name fragment of the Mach server endpoint published in the bootstrap +// namespace. The full name is "<bundle-id>.apps.<profile_path_hash>". +// <bundle-id> is the BaseBundleID() and <profile_path_hash> is an MD5 hash +// of the full profile directory path. +extern const char kAppShimBootstrapNameFragment[]; + +// The name of a file placed in the profile directory to indicate that app +// shims should connect over Mach IPC rather than a UNIX domain socket. If +// a file named this does not exist, app shims will fall back to the UNIX +// domain socket. +extern const char kMojoChannelMacSignalFile[]; + // A symlink used to store the version string of the currently running Chrome. // The shim will read this to determine which version of the framework to load. extern const char kRunningChromeVersionSymlinkName[];
diff --git a/chrome/common/mac/app_mode_common.mm b/chrome/common/mac/app_mode_common.mm index ad6c5441..ca35fc5 100644 --- a/chrome/common/mac/app_mode_common.mm +++ b/chrome/common/mac/app_mode_common.mm
@@ -14,6 +14,9 @@ const char kAppShimSocketShortName[] = "Socket"; const char kAppShimSocketSymlinkName[] = "App Shim Socket"; +const char kAppShimBootstrapNameFragment[] = "apps"; +const char kMojoChannelMacSignalFile[] = "apps_use_mojo_channel_mac"; + const char kRunningChromeVersionSymlinkName[] = "RunningChromeVersion"; const char kAppListModeId[] = "app_list";
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc index 66a72db..447a4829 100644 --- a/chrome/installer/setup/setup_util.cc +++ b/chrome/installer/setup/setup_util.cc
@@ -96,6 +96,43 @@ } } +// Remove the registration of profile statistics. This used to be reported to +// Omaha, but no more. +void RemoveProfileStatistics(const InstallerState& installer_state) { + const HKEY root = installer_state.root_key(); + bool found = false; + bool deleted = true; + if (installer_state.system_install()) { + for (base::string16 key : {L"_NumAccounts", L"_NumSignedIn"}) { + base::string16 path(install_static::GetClientStateMediumKeyPath() + + L"\\" + key); + if (base::win::RegKey(root, path.c_str(), + KEY_QUERY_VALUE | KEY_WOW64_32KEY) + .Valid()) { + found = true; + if (!InstallUtil::DeleteRegistryKey(root, path, KEY_WOW64_32KEY)) + deleted = false; + } + } + } else { + base::win::RegKey client_state; + if (client_state.Open(root, install_static::GetClientStateKeyPath().c_str(), + KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY) == + ERROR_SUCCESS) { + for (const base::char16* value : {STRING16_LITERAL("_NumAccounts"), + STRING16_LITERAL("_NumSignedIn"})) { + if (!client_state.HasValue(value)) + continue; + found = true; + if (client_state.DeleteValue(value) != ERROR_SUCCESS) + deleted = false; + } + } + } + if (found) + UMA_HISTOGRAM_BOOLEAN("Setup.Install.RemoveProfileStatistics", deleted); +} + // "The binaries" once referred to the on-disk footprint of Chrome and/or Chrome // Frame when the products were configured to share such on-disk bits. Support // for this mode of install was dropped from ToT in December 2016. Remove any @@ -769,6 +806,7 @@ // Cleanups that apply to any install mode. RemoveLegacyIExecuteCommandKey(installer_state); + RemoveProfileStatistics(installer_state); // The cleanups below only apply to normal Chrome, not side-by-side (canary). if (!install_static::InstallDetails::Get().is_primary_mode())
diff --git a/chrome/installer/util/google_update_constants.cc b/chrome/installer/util/google_update_constants.cc index f1ce1fb..ba074e1ac 100644 --- a/chrome/installer/util/google_update_constants.cc +++ b/chrome/installer/util/google_update_constants.cc
@@ -54,8 +54,6 @@ const wchar_t kRegOldVersionField[] = L"opv"; const wchar_t kRegOopcrashesField[] = L"oopcrashes"; const wchar_t kRegPathField[] = L"path"; -const wchar_t kRegProfilesActive[] = L"_NumAccounts"; -const wchar_t kRegProfilesSignedIn[] = L"_NumSignedIn"; const wchar_t kRegRLZBrandField[] = L"brand"; const wchar_t kRegRLZReactivationBrandField[] = L"reactivationbrand"; const wchar_t kRegReferralField[] = L"referral";
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc index 4f0ad53..cd16813 100644 --- a/chrome/installer/util/google_update_settings.cc +++ b/chrome/installer/util/google_update_settings.cc
@@ -11,7 +11,6 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" -#include "base/numerics/safe_conversions.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -20,8 +19,6 @@ #include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "base/win/registry.h" -#include "base/win/win_util.h" -#include "chrome/common/chrome_switches.h" #include "chrome/install_static/install_util.h" #include "chrome/installer/util/channel_info.h" #include "chrome/installer/util/install_util.h" @@ -88,35 +85,6 @@ name, value); } -// Writes |value| into a user-specific value in the key |name| under -// |app_reg_data|'s ClientStateMedium key in HKLM along with the aggregation -// method |aggregate|. This function is solely for use by system-level installs. -bool WriteGoogleUpdateAggregateNumKeyInternal(const wchar_t* const name, - uint32_t value, - const wchar_t* const aggregate) { - DCHECK(aggregate); - DCHECK(install_static::IsSystemInstall()); - - // Machine installs require each OS user to write a unique key under a - // named key in HKLM as well as an "aggregation" function that describes - // how the values of multiple users are to be combined. - base::string16 uniquename; - if (!base::win::GetUserSidString(&uniquename)) { - NOTREACHED(); - return false; - } - - base::string16 reg_path(install_static::GetClientStateMediumKeyPath()); - reg_path.append(L"\\").append(name); - RegKey key; - if (key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), - KEY_SET_VALUE | KEY_WOW64_32KEY) != ERROR_SUCCESS) { - return false; - } - key.WriteValue(google_update::kRegAggregateMethod, aggregate); - return key.WriteValue(uniquename.c_str(), value) == ERROR_SUCCESS; -} - // Writes |value| into |name| in the app's ClientState key in HKEY_CURRENT_USER. // This function is only provided for legacy use. New code needing to load/store // per-user data should use install_details::GetRegistryPath(). @@ -129,19 +97,6 @@ key.WriteValue(name, value.c_str()) == ERROR_SUCCESS; } -// Writes the per-user stat |value_name|=|value| either in ClientStateMedium -// using summation as the aggregation function or in ClientState directly, -// depending on whether this is is a per-machine or a per-user install. -void WritePerUserStat(const wchar_t* value_name, uint32_t value) { - if (install_static::IsSystemInstall()) { - // Write |value| as a DWORD in a per-user value of subkey |value_name|. - WriteGoogleUpdateAggregateNumKeyInternal(value_name, value, L"sum()"); - } else { - // Write |value| as a string in value |value_name|. - WriteUserGoogleUpdateStrKey(value_name, base::NumberToString16(value)); - } -} - // Clears |name| in the app's ClientState key by writing an empty string into // it. Returns true if the value does not exist, is already clear, or is // successfully cleared. @@ -547,14 +502,6 @@ return modified; } -void GoogleUpdateSettings::UpdateProfileCounts(size_t profiles_active, - size_t profiles_signedin) { - WritePerUserStat(google_update::kRegProfilesActive, - base::saturated_cast<uint32_t>(profiles_active)); - WritePerUserStat(google_update::kRegProfilesSignedIn, - base::saturated_cast<uint32_t>(profiles_signedin)); -} - GoogleUpdateSettings::UpdatePolicy GoogleUpdateSettings::GetAppUpdatePolicy( base::StringPiece16 app_guid, bool* is_overridden) {
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h index cf3d2b5..41ce26d3 100644 --- a/chrome/installer/util/google_update_settings.h +++ b/chrome/installer/util/google_update_settings.h
@@ -216,11 +216,6 @@ int install_return_code, installer::ChannelInfo* value); - // This method updates the values that report how many profiles are in use - // and how many of those are signed-in. - static void UpdateProfileCounts(size_t profiles_active, - size_t profiles_signedin); - // Returns the effective update policy for |app_guid| as dictated by // Group Policy settings. |is_overridden|, if non-NULL, is populated with // true if an app-specific policy override is in force, or false otherwise.
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc index c22f653..f5087f3 100644 --- a/chrome/installer/util/google_update_settings_unittest.cc +++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -17,7 +17,6 @@ #include "base/test/test_reg_util_win.h" #include "base/win/registry.h" #include "base/win/shlwapi.h" // For SHDeleteKey. -#include "base/win/win_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/install_static/install_util.h" #include "chrome/install_static/test/scoped_install_details.h" @@ -455,108 +454,6 @@ EXPECT_FALSE(is_overridden); } -TEST_F(GoogleUpdateSettingsTest, UpdateProfileCountsSystemInstall) { - // Set up a basic system-level InstallDetails. - install_static::ScopedInstallDetails details(true /* system_level */); - - // No profile count keys present yet. - base::string16 state_key = install_static::GetClientStateMediumKeyPath(); - base::string16 num_profiles_path(state_key); - num_profiles_path.append(L"\\"); - num_profiles_path.append(google_update::kRegProfilesActive); - base::string16 num_signed_in_path(state_key); - num_signed_in_path.append(L"\\"); - num_signed_in_path.append(google_update::kRegProfilesSignedIn); - - EXPECT_EQ(ERROR_FILE_NOT_FOUND, - RegKey().Open(HKEY_LOCAL_MACHINE, - num_profiles_path.c_str(), - KEY_QUERY_VALUE)); - EXPECT_EQ(ERROR_FILE_NOT_FOUND, - RegKey().Open(HKEY_LOCAL_MACHINE, - num_signed_in_path.c_str(), - KEY_QUERY_VALUE)); - - // Show time! Write the values. - GoogleUpdateSettings::UpdateProfileCounts(3, 2); - - // Verify the keys were created. - EXPECT_EQ(ERROR_SUCCESS, - RegKey().Open(HKEY_LOCAL_MACHINE, - num_profiles_path.c_str(), - KEY_QUERY_VALUE)); - EXPECT_EQ(ERROR_SUCCESS, - RegKey().Open(HKEY_LOCAL_MACHINE, - num_signed_in_path.c_str(), - KEY_QUERY_VALUE)); - - base::string16 uniquename; - EXPECT_TRUE(base::win::GetUserSidString(&uniquename)); - - // Verify the values are accessible. - DWORD num_profiles = 0; - DWORD num_signed_in = 0; - base::string16 aggregate; - EXPECT_EQ( - ERROR_SUCCESS, - RegKey(HKEY_LOCAL_MACHINE, num_profiles_path.c_str(), - KEY_QUERY_VALUE).ReadValueDW(uniquename.c_str(), - &num_profiles)); - EXPECT_EQ( - ERROR_SUCCESS, - RegKey(HKEY_LOCAL_MACHINE, num_signed_in_path.c_str(), - KEY_QUERY_VALUE).ReadValueDW(uniquename.c_str(), - &num_signed_in)); - EXPECT_EQ( - ERROR_SUCCESS, - RegKey(HKEY_LOCAL_MACHINE, num_signed_in_path.c_str(), - KEY_QUERY_VALUE).ReadValue(google_update::kRegAggregateMethod, - &aggregate)); - - // Verify the correct values were written. - EXPECT_EQ(3u, num_profiles); - EXPECT_EQ(2u, num_signed_in); - EXPECT_EQ(L"sum()", aggregate); -} - -TEST_F(GoogleUpdateSettingsTest, UpdateProfileCountsUserInstall) { - // Unit tests never operate as an installed application, so will never - // be a system install. - - // No profile count values present yet. - base::string16 state_key = install_static::GetClientStateKeyPath(); - - EXPECT_EQ(ERROR_FILE_NOT_FOUND, - RegKey().Open(HKEY_CURRENT_USER, - state_key.c_str(), - KEY_QUERY_VALUE)); - - // Show time! Write the values. - GoogleUpdateSettings::UpdateProfileCounts(4, 1); - - // Verify the key was created. - EXPECT_EQ(ERROR_SUCCESS, - RegKey().Open(HKEY_CURRENT_USER, - state_key.c_str(), - KEY_QUERY_VALUE)); - - // Verify the values are accessible. - base::string16 num_profiles; - base::string16 num_signed_in; - EXPECT_EQ( - ERROR_SUCCESS, - RegKey(HKEY_CURRENT_USER, state_key.c_str(), KEY_QUERY_VALUE). - ReadValue(google_update::kRegProfilesActive, &num_profiles)); - EXPECT_EQ( - ERROR_SUCCESS, - RegKey(HKEY_CURRENT_USER, state_key.c_str(), KEY_QUERY_VALUE). - ReadValue(google_update::kRegProfilesSignedIn, &num_signed_in)); - - // Verify the correct values were written. - EXPECT_EQ(L"4", num_profiles); - EXPECT_EQ(L"1", num_signed_in); -} - #if defined(GOOGLE_CHROME_BUILD) // Test that the default override is returned if no app-specific override is
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc index 64f5a4d2..498537a 100644 --- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc +++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -324,6 +324,34 @@ : false; } +bool AutomationAXTreeWrapper::IsInFocusChain(int32_t node_id) { + if (tree()->data().focus_id != node_id) + return false; + + if (IsDesktopTree()) + return true; + + AutomationAXTreeWrapper* child_of_ancestor = this; + AutomationAXTreeWrapper* ancestor = nullptr; + while ((ancestor = + GetParentOfTreeId(child_of_ancestor->tree()->data().tree_id))) { + int32_t focus_id = ancestor->tree()->data().focus_id; + ui::AXNode* focus = ancestor->tree()->GetFromId(focus_id); + if (!focus) + return false; + if (ui::AXTreeID::FromString(focus->GetStringAttribute( + ax::mojom::StringAttribute::kChildTreeId)) != + child_of_ancestor->tree()->data().tree_id) + return false; + + if (ancestor->IsDesktopTree()) + return true; + + child_of_ancestor = ancestor; + } + return false; +} + void AutomationAXTreeWrapper::OnNodeDataWillChange( ui::AXTree* tree, const ui::AXNodeData& old_node_data,
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.h b/chrome/renderer/extensions/automation_ax_tree_wrapper.h index cffe2a4..b9af980 100644 --- a/chrome/renderer/extensions/automation_ax_tree_wrapper.h +++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.h
@@ -41,6 +41,11 @@ // Returns true if this is the desktop tree. bool IsDesktopTree() const; + // Returns whether |node_id| is the focused node in this tree. Accounts for + // cases where this tree itself is not focused. Behaves similarly to + // document.activeElement (within the DOM). + bool IsInFocusChain(int32_t node_id); + private: // AXTreeObserver overrides. void OnNodeDataWillChange(ui::AXTree* tree,
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc index 8ab33ba3..4ed724cc 100644 --- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc +++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -1122,6 +1122,16 @@ v8::NewStringType::kNormal) .ToLocalChecked()); }); + RouteNodeIDFunction( + "GetHasPopup", + [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, + AutomationAXTreeWrapper* tree_wrapper, ui::AXNode* node) { + ax::mojom::HasPopup has_popup = node->data().GetHasPopup(); + std::string has_popup_str = ui::ToString(has_popup); + result.Set(v8::String::NewFromUtf8(isolate, has_popup_str.c_str(), + v8::NewStringType::kNormal) + .ToLocalChecked()); + }); RouteNodeIDPlusStringBoolFunction( "GetNextTextMatch", [this](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result, @@ -1481,16 +1491,12 @@ top_tree_wrapper = walker; GetParent(walker->tree()->root(), &walker); } - AutomationAXTreeWrapper* focused_tree_wrapper = nullptr; - ui::AXNode* focused_node = nullptr; - const bool focused = - (GetFocusInternal(top_tree_wrapper, &focused_tree_wrapper, - &focused_node) && - focused_tree_wrapper == tree_wrapper && focused_node == node) || - tree_wrapper->tree()->data().focus_id == node->id(); - if (focused) + + const bool focused = tree_wrapper->IsInFocusChain(node->id()); + if (focused) { state.Set(api::automation::ToString(api::automation::STATE_TYPE_FOCUSED), true); + } bool offscreen = false; ComputeGlobalNodeBounds(tree_wrapper, node, gfx::RectF(), &offscreen);
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js index a86a54a0e..3bfa78e8 100644 --- a/chrome/renderer/resources/extensions/automation/automation_node.js +++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -352,6 +352,14 @@ /** * @param {string} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. + * @return {automation.HasPopup} + */ +var GetHasPopup = natives.GetHasPopup; + + +/** + * @param {string} axTreeID The id of the accessibility tree. + * @param {number} nodeID The id of a node. * @param {string} searchStr * @param {boolean} backward * @return {{treeId: string, nodeId: number}} @@ -599,6 +607,10 @@ return GetDefaultActionVerb(this.treeID, this.id); }, + get hasPopup() { + return GetHasPopup(this.treeID, this.id); + }, + get tableCellColumnHeaders() { var ids = GetTableCellColumnHeaders(this.treeID, this.id); if (ids && this.rootImpl) { @@ -1564,6 +1576,7 @@ 'role', 'checked', 'defaultActionVerb', + 'hasPopup', 'restriction', 'state', 'location',
diff --git a/chrome/services/app_service/README.md b/chrome/services/app_service/README.md index 12a0cdd1..af494d0 100644 --- a/chrome/services/app_service/README.md +++ b/chrome/services/app_service/README.md
@@ -258,18 +258,15 @@ `Publisher` sends an `IconKey`: enough information to load the icon at given resolutions. -The `IconKey` is an `AppType app_type` and a `uint32 icon_effects` bitmask -(whether to apply various image processing effects such as desaturation to -gray), plus additional data (`uint64 u_key` and `string s_key`) whose semantics -depend on the `app_type`. - -For example, some icons are statically built into the Chrome or Chrome OS +An `IconKey` holds an `AppType app_type` and `string app_id`, plus additional +data. For example, some icons are statically built into the Chrome or Chrome OS binary, as PNG-formatted resources, and can be loaded (synchronously, without -sandboxing). They can be loaded from a `u_key` resource ID. Some icons are +sandboxing). They can be loaded from the `IconKey.resource_id`. Other icons are dynamically (and asynchronously) loaded from the extension database on disk. -They can be loaded from the `s_key` app ID, with the `u_key` serving as a -(monotonically increasing) epoch number so that an icon update results in a -different `u_key` and hence a different `IconKey`. +They can be loaded just from the `app_id` alone. + +In either case, the `IconKey.icon_effects` bitmask holds whether to apply +various image processing effects such as desaturation to gray. interface AppService { // App Icon Factory methods. @@ -294,10 +291,27 @@ }; struct IconKey { - AppType app_type; - // The semantics of u_key and s_key depend on the app_type. - uint64 u_key; - string s_key; + AppType app_type, + string app_id, + // A monotonically increasing number so that, after an icon update, a new + // IconKey, one that is different in terms of field-by-field equality, can be + // broadcast by a Publisher. + // + // The exact value of the number isn't important, only that newer IconKey's + // (those that were created more recently) have a larger timeline than older + // IconKey's. + // + // This is, in some sense, *a* version number, but the field is not called + // "version", to avoid any possible confusion that it encodes *the* app's + // version number, e.g. the "2.3.5" in "FooBar version 2.3.5 is installed". + // + // For example, if an app is disabled for some reason (so that its icon is + // grayed out), this would result in a different timeline even though the + // app's version is unchanged. + uint64 timeline; + // If non-zero, the compressed icon is compiled into the Chromium binary + // as a statically available, int-keyed resource. + int32 resource_id; // A bitmask of icon post-processing effects, such as desaturation to // gray and rounding the corners. uint32 icon_effects; @@ -334,10 +348,10 @@ Grouping the `IconKey` with the other `LoadIcon` arguments, the combination identifies a static (unchanging, but possibly obsolete) image: if a new version of an app results in a new icon, or if a change in app state results in a -grayed out icon, this is represented by a different `IconKey`, such as a -different `u_key` or `icon_effects` value. As a consequence, the combined -`LoadIcon` arguments can be used to key a cache or map of `IconValue`s, or to -recognize and coalesce multiple concurrent requests to the same combination. +grayed out icon, this is represented by a different, larger `IconKey.timeline`. +As a consequence, the combined `LoadIcon` arguments can be used to key a cache +or map of `IconValue`s, or to recognize and coalesce multiple concurrent +requests to the same combination. Such optimizations can be implemented as a series of "wrapper" classes (as in the classic "decorator" or "wrapper" design pattern) that all implement the @@ -483,4 +497,4 @@ --- -Updated on 2019-03-15. +Updated on 2019-03-20.
diff --git a/chrome/services/app_service/app_service_impl_unittest.cc b/chrome/services/app_service/app_service_impl_unittest.cc index 437a1af..17c190e 100644 --- a/chrome/services/app_service/app_service_impl_unittest.cc +++ b/chrome/services/app_service/app_service_impl_unittest.cc
@@ -37,7 +37,7 @@ } } - std::string load_icon_s_key; + std::string load_icon_app_id; private: void Connect(apps::mojom::SubscriberPtr subscriber, @@ -51,7 +51,7 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon, LoadIconCallback callback) override { - load_icon_s_key = icon_key->s_key; + load_icon_app_id = icon_key->app_id; std::move(callback).Run(apps::mojom::IconValue::New()); } @@ -193,10 +193,10 @@ : apps::mojom::AppType::kUnknown; bool callback_ran = false; - pub0.load_icon_s_key = "-"; - pub1.load_icon_s_key = "-"; - pub2.load_icon_s_key = "-"; - auto icon_key = apps::mojom::IconKey::New(app_type, 0, "o", 0); + pub0.load_icon_app_id = "-"; + pub1.load_icon_app_id = "-"; + pub2.load_icon_app_id = "-"; + auto icon_key = apps::mojom::IconKey::New(app_type, "o", 0, 0, 0); constexpr bool allow_placeholder_icon = false; impl.LoadIcon( std::move(icon_key), apps::mojom::IconCompression::kUncompressed, @@ -206,9 +206,9 @@ &callback_ran)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(callback_ran); - EXPECT_EQ("-", pub0.load_icon_s_key); - EXPECT_EQ(i == 0 ? "o" : "-", pub1.load_icon_s_key); - EXPECT_EQ("-", pub2.load_icon_s_key); + EXPECT_EQ("-", pub0.load_icon_app_id); + EXPECT_EQ(i == 0 ? "o" : "-", pub1.load_icon_app_id); + EXPECT_EQ("-", pub2.load_icon_app_id); } }
diff --git a/chrome/services/app_service/public/cpp/app_update_unittest.cc b/chrome/services/app_service/public/cpp/app_update_unittest.cc index eb0e290..62e4dc7 100644 --- a/chrome/services/app_service/public/cpp/app_update_unittest.cc +++ b/chrome/services/app_service/public/cpp/app_update_unittest.cc
@@ -241,7 +241,7 @@ // IconKey tests. if (state) { - auto x = apps::mojom::IconKey::New(app_type, 100, std::string(), 0); + auto x = apps::mojom::IconKey::New(app_type, app_id, 100, 0, 0); state->icon_key = x.Clone(); expect_icon_key_ = x.Clone(); expect_icon_key_changed_ = false; @@ -249,7 +249,7 @@ } if (delta) { - auto x = apps::mojom::IconKey::New(app_type, 0, "one hundred", 0); + auto x = apps::mojom::IconKey::New(app_type, app_id, 200, 0, 0); delta->icon_key = x.Clone(); expect_icon_key_ = x.Clone(); expect_icon_key_changed_ = true;
diff --git a/chrome/services/app_service/public/cpp/icon_cache.cc b/chrome/services/app_service/public/cpp/icon_cache.cc index f3b1ac1..4c55201 100644 --- a/chrome/services/app_service/public/cpp/icon_cache.cc +++ b/chrome/services/app_service/public/cpp/icon_cache.cc
@@ -40,8 +40,9 @@ bool allow_placeholder_icon, apps::mojom::Publisher::LoadIconCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + apps::mojom::IconKey null_icon_key; IconLoader::Key key( - *icon_key, icon_compression, size_hint_in_dip, + icon_key ? *icon_key : null_icon_key, icon_compression, size_hint_in_dip, // We pass false instead of allow_placeholder_icon, as the Value // already records placeholder-ness. If the allow_placeholder_icon // arg to this function is true, we can re-use a cache hit regardless
diff --git a/chrome/services/app_service/public/cpp/icon_cache_unittest.cc b/chrome/services/app_service/public/cpp/icon_cache_unittest.cc index bb3ec36..6cb7fd9 100644 --- a/chrome/services/app_service/public/cpp/icon_cache_unittest.cc +++ b/chrome/services/app_service/public/cpp/icon_cache_unittest.cc
@@ -30,7 +30,7 @@ private: apps::mojom::IconKeyPtr GetIconKey(const std::string& app_id) override { - return apps::mojom::IconKey::New(apps::mojom::AppType::kWeb, 0, app_id, + return apps::mojom::IconKey::New(apps::mojom::AppType::kWeb, app_id, 0, 0, 0); }
diff --git a/chrome/services/app_service/public/cpp/icon_loader.cc b/chrome/services/app_service/public/cpp/icon_loader.cc index 94bfb74..b06b875 100644 --- a/chrome/services/app_service/public/cpp/icon_loader.cc +++ b/chrome/services/app_service/public/cpp/icon_loader.cc
@@ -23,19 +23,25 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon) : app_type_(icon_key.app_type), - s_key_(icon_key.s_key), - u_key_(icon_key.u_key), + app_id_(icon_key.app_id), + timeline_(icon_key.timeline), + resource_id_(icon_key.resource_id), icon_effects_(icon_key.icon_effects), icon_compression_(icon_compression), size_hint_in_dip_(size_hint_in_dip), allow_placeholder_icon_(allow_placeholder_icon) {} +IconLoader::Key::Key(const Key& other) = default; + bool IconLoader::Key::operator<(const Key& that) const { if (this->app_type_ != that.app_type_) { return this->app_type_ < that.app_type_; } - if (this->u_key_ != that.u_key_) { - return this->u_key_ < that.u_key_; + if (this->timeline_ != that.timeline_) { + return this->timeline_ < that.timeline_; + } + if (this->resource_id_ != that.resource_id_) { + return this->resource_id_ < that.resource_id_; } if (this->icon_effects_ != that.icon_effects_) { return this->icon_effects_ < that.icon_effects_; @@ -49,7 +55,7 @@ if (this->allow_placeholder_icon_ != that.allow_placeholder_icon_) { return this->allow_placeholder_icon_ < that.allow_placeholder_icon_; } - return this->s_key_ < that.s_key_; + return this->app_id_ < that.app_id_; } std::unique_ptr<IconLoader::Releaser> IconLoader::LoadIcon(
diff --git a/chrome/services/app_service/public/cpp/icon_loader.h b/chrome/services/app_service/public/cpp/icon_loader.h index fa2870d..59f01be 100644 --- a/chrome/services/app_service/public/cpp/icon_loader.h +++ b/chrome/services/app_service/public/cpp/icon_loader.h
@@ -77,8 +77,9 @@ public: // apps::mojom::IconKey fields. apps::mojom::AppType app_type_; - std::string s_key_; - uint64_t u_key_; + std::string app_id_; + uint64_t timeline_; + int32_t resource_id_; uint32_t icon_effects_; // Other fields. apps::mojom::IconCompression icon_compression_; @@ -90,6 +91,8 @@ int32_t size_hint_in_dip, bool allow_placeholder_icon); + Key(const Key& other); + bool operator<(const Key& that) const; }; };
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom index ee2f92c4..a556094 100644 --- a/chrome/services/app_service/public/mojom/types.mojom +++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -85,10 +85,33 @@ }; struct IconKey { + // A timeline value for icons that do not change. + const uint64 kDoesNotChangeOverTime = 0; + + const int32 kInvalidResourceId = 0; + AppType app_type; - // The semantics of u_key and s_key depend on the app_type. - uint64 u_key; - string s_key; + string app_id; + // A monotonically increasing number so that, after an icon update, a new + // IconKey, one that is different in terms of field-by-field equality, can be + // broadcast by a Publisher. + // + // The exact value of the number isn't important, only that newer IconKey's + // (those that were created more recently) have a larger timeline than older + // IconKey's. + // + // This is, in some sense, *a* version number, but the field is not called + // "version", to avoid any possible confusion that it encodes *the* app's + // version number, e.g. the "2.3.5" in "FooBar version 2.3.5 is installed". + // + // For example, if an app is disabled for some reason (so that its icon is + // grayed out), this would result in a different timeline even though the + // app's version is unchanged. + uint64 timeline; + // If non-zero (or equivalently, not equal to kInvalidResourceId), the + // compressed icon is compiled into the Chromium binary as a statically + // available, int-keyed resource. + int32 resource_id; // A bitmask of icon post-processing effects, such as desaturation to gray // and rounding the corners. uint32 icon_effects;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 936fe05..67324f2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -830,10 +830,10 @@ "../browser/prerender/prerender_nostate_prefetch_browsertest.cc", "../browser/prerender/prerender_test_utils.cc", "../browser/prerender/prerender_test_utils.h", + "../browser/previews/hints_fetcher_browsertest.cc", "../browser/previews/lazyload_browsertest.cc", "../browser/previews/previews_browsertest.cc", "../browser/previews/previews_lite_page_browsertest.cc", - "../browser/previews/previews_oneplatform_hints_browsertest.cc", "../browser/previews/previews_service_browser_test.cc", "../browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc", "../browser/process_singleton_browsertest.cc", @@ -960,6 +960,7 @@ "../browser/ui/content_settings/content_setting_image_model_browsertest.cc", "../browser/ui/content_settings/framebust_block_browsertest.cc", "../browser/ui/exclusive_access/fullscreen_controller_browsertest.cc", + "../browser/ui/extensions/application_launch_browsertest.cc", "../browser/ui/extensions/blocked_action_bubble_browsertest.cc", "../browser/ui/extensions/extension_enable_flow_browsertest.cc", "../browser/ui/extensions/extension_installed_bubble_browsertest.cc", @@ -3380,6 +3381,7 @@ "../browser/search/search_suggest/search_suggest_loader_impl_unittest.cc", "../browser/search/search_suggest/search_suggest_service_unittest.cc", "../browser/search/search_unittest.cc", + "../browser/send_tab_to_self/desktop_notification_handler_unittest.cc", "../browser/send_tab_to_self/send_tab_to_self_util_unittest.cc", "../browser/serial/serial_chooser_context_unittest.cc", "../browser/sessions/tab_restore_service_unittest.cc", @@ -3535,6 +3537,7 @@ if (!is_android) { sources += [ + "../browser/apps/app_service/app_service_proxy_unittest.cc", "../browser/devtools/devtools_file_system_indexer_unittest.cc", "../browser/devtools/devtools_file_watcher_unittest.cc", "../browser/devtools/devtools_ui_bindings_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 932b33d..d0cb52a5 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -96,6 +96,7 @@ "//third_party/android_deps:com_android_support_support_compat_java", "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_test_base_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/jsr-305:jsr_305_javalib", "//third_party/junit",
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index 41ca463..418d801 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc
@@ -137,6 +137,8 @@ service_manager::Connector* connector, const chromeos::device_sync::GcmDeviceInfoProvider* gcm_device_info_provider, + chromeos::device_sync::ClientAppMetadataProvider* + client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<base::OneShotTimer> timer) override { return std::make_unique<chromeos::device_sync::FakeDeviceSync>(); @@ -374,8 +376,7 @@ void InProcessBrowserTest::CloseBrowserSynchronously(Browser* browser) { content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_BROWSER_CLOSED, - content::Source<Browser>(browser)); + chrome::NOTIFICATION_BROWSER_CLOSED, content::Source<Browser>(browser)); CloseBrowserAsynchronously(browser); observer.Wait(); #if defined(OS_CHROMEOS) @@ -427,10 +428,9 @@ } } -void InProcessBrowserTest::AddTabAtIndex( - int index, - const GURL& url, - ui::PageTransition transition) { +void InProcessBrowserTest::AddTabAtIndex(int index, + const GURL& url, + ui::PageTransition transition) { AddTabAtIndexToBrowser(browser(), index, url, transition, true); } @@ -491,9 +491,8 @@ return browser; } -Browser* InProcessBrowserTest::CreateBrowserForApp( - const std::string& app_name, - Profile* profile) { +Browser* InProcessBrowserTest::CreateBrowserForApp(const std::string& app_name, + Profile* profile) { Browser* browser = new Browser(Browser::CreateParams::CreateForApp( app_name, false /* trusted_source */, gfx::Rect(), profile, true)); AddBlankTabAndShow(browser); @@ -505,8 +504,7 @@ content::WindowedNotificationObserver observer( content::NOTIFICATION_LOAD_STOP, content::NotificationService::AllSources()); - chrome::AddSelectedTabWithURL(browser, - GURL(url::kAboutBlankURL), + chrome::AddSelectedTabWithURL(browser, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_AUTO_TOPLEVEL); observer.Wait();
diff --git a/chrome/test/data/autofill/captured_sites/cipd.yaml b/chrome/test/data/autofill/captured_sites/cipd.yaml index 505c396..0b561961 100644 --- a/chrome/test/data/autofill/captured_sites/cipd.yaml +++ b/chrome/test/data/autofill/captured_sites/cipd.yaml
@@ -31,18 +31,12 @@ - file: macys.test - file: newegg - file: newegg.test - - file: pottery_barn - - file: pottery_barn.test - file: qvc - file: qvc.test - file: walmart - file: walmart.test - file: wayfair - file: wayfair.test - - file: west_elm - - file: west_elm.test - - file: williams_sonoma - - file: williams_sonoma.test - file: zappos - file: zappos.test - file: zulily
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js index 89357ca..3dcdd25 100644 --- a/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js
@@ -18,9 +18,7 @@ assertEq('Automation Tests', title); var state = RemoveUntestedStates(rootNode.state); - assertEq( - {focusable: true, focused: true}, - state); + assertEq({focusable: true}, state); assertEq(undefined, rootNode.restriction); var children = rootNode.children;
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js index 49b9f922..d416e39 100644 --- a/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js
@@ -3,10 +3,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var originalActiveTab; + function createBackgroundTab(url, callback) { chrome.tabs.query({ active: true }, function(tabs) { chrome.test.assertEq(1, tabs.length); - var originalActiveTab = tabs[0]; + originalActiveTab = tabs[0]; createTab(url, function(tab) { chrome.tabs.update(originalActiveTab.id, { active: true }, function() { callback(tab); @@ -21,22 +23,45 @@ chrome.test.succeed(); } +function getTreeForBackgroundTab(foregroundTabRootNode, backgroundTab) { + // We haven't cheated and loaded the test in the foreground tab. + chrome.test.assertTrue(foregroundTabRootNode.docLoaded); + var foregroundTabTitle = foregroundTabRootNode.docTitle; + chrome.test.assertFalse(foregroundTabTitle == 'Automation Tests'); + +} + var allTests = [ function testGetTabById() { getUrlFromConfig('index.html', function(url) { // Keep the NTP as the active tab so that we know we're requesting the // tab by ID rather than just getting the active tab still. - createBackgroundTab(url, function(tab) { - chrome.automation.getTree(tab.id, function(rootNode) { - if (rootNode.docLoaded) { - assertCorrectTab(rootNode); - return; - } + createBackgroundTab(url, function(backgroundTab) { + // Fetch the current foreground tab to compare with the background tab. + chrome.automation.getTree(originalActiveTab.id, + function(ntpRootNode) { + chrome.test.assertEq(ntpRootNode, undefined, + "Can't get automation tree for NTP"); - rootNode.addEventListener('loadComplete', function() { - assertCorrectTab(rootNode); + chrome.automation.getTree(backgroundTab.id, function(rootNode) { + chrome.test.assertFalse(rootNode === undefined, + "Got automation tree for background tab"); + chrome.test.assertFalse( + rootNode.docLoaded, + "Load complete never fires unless tab is foregrounded"); + + chrome.tabs.update(backgroundTab.id, { active: true }, function() { + if (rootNode.docLoaded) { + assertCorrectTab(rootNode); + return; + } + + rootNode.addEventListener('loadComplete', function() { + assertCorrectTab(rootNode); + }); + }); }); - }) + }); }); }); }
diff --git a/chrome/test/data/webui/bookmarks/command_manager_test.js b/chrome/test/data/webui/bookmarks/command_manager_test.js index 3eb75f3f..44abaae2 100644 --- a/chrome/test/data/webui/bookmarks/command_manager_test.js +++ b/chrome/test/data/webui/bookmarks/command_manager_test.js
@@ -187,6 +187,32 @@ commandManager.assertLastCommand(Command.REDO); }); + test('undo triggered when bookmarks-toolbar element has focus', function() { + const element = document.createElement('bookmarks-toolbar'); + document.body.appendChild(element); + MockInteractions.pressAndReleaseKeyOn( + element, '', cr.isMac ? 'meta' : 'ctrl', 'z'); + commandManager.assertLastCommand(Command.UNDO); + }); + + test('undo not triggered when most other elements have focus', function() { + const element = document.createElement('div'); + document.body.appendChild(element); + MockInteractions.pressAndReleaseKeyOn( + element, '', cr.isMac ? 'meta' : 'ctrl', 'z'); + commandManager.assertLastCommand(null); + }); + + test('undo not triggered when toolbar input has focus', function() { + const toolbar = document.createElement('bookmarks-toolbar'); + const input = document.createElement('input'); + toolbar.appendChild(input); + document.body.appendChild(toolbar); + MockInteractions.pressAndReleaseKeyOn( + input, '', cr.isMac ? 'meta' : 'ctrl', 'z'); + commandManager.assertLastCommand(null); + }); + test('Show In Folder is only available during search', function() { store.data.selection.items = new Set(['12']); store.notifyObservers();
diff --git a/chrome/test/data/webui/welcome/app_chooser_test.js b/chrome/test/data/webui/welcome/app_chooser_test.js new file mode 100644 index 0000000..43412f9d --- /dev/null +++ b/chrome/test/data/webui/welcome/app_chooser_test.js
@@ -0,0 +1,173 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('onboarding_welcome_app_chooser', function() { + suite('AppChooserTest', function() { + const apps = [ + { + id: 0, + name: 'First', + icon: 'first', + url: 'http://first.example.com', + }, + { + id: 1, + name: 'Second', + icon: 'second', + url: 'http://second.example.com', + }, + { + id: 2, + name: 'Third', + icon: 'third', + url: 'http://third.example.com', + }, + { + id: 3, + name: 'Fourth', + icon: 'fourth', + url: 'http://fourth.example.com', + }, + { + id: 4, + name: 'Fifth', + icon: 'fifth', + url: 'http://fifth.example.com', + }, + ]; + + /** @type {nux.NuxAppProxy} */ + let testAppBrowserProxy; + + /** @type {nux.ModuleMetricsProxy} */ + let testAppMetricsProxy; + + /** @type {nux.BookmarkProxy} */ + let testBookmarkBrowserProxy; + + /** @type {AppChooserElement} */ + let testElement; + + setup(async function() { + testAppBrowserProxy = new TestNuxAppProxy(); + testAppMetricsProxy = new TestMetricsProxy(); + testBookmarkBrowserProxy = new TestBookmarkProxy(); + nux.BookmarkProxyImpl.instance_ = testBookmarkBrowserProxy; + // Reset w/ new proxy for test. + nux.BookmarkBarManager.instance_ = new nux.BookmarkBarManager(); + + testAppBrowserProxy.setAppList(apps); + + PolymerTest.clearBody(); + testElement = document.createElement('app-chooser'); + document.body.appendChild(testElement); + testElement.singleSelect = false; // All apps can be selected. + testElement.appProxy = testAppBrowserProxy; + testElement.metricsManager = + new nux.ModuleMetricsManager(testAppMetricsProxy); + // Simulate nux-app's onRouteEnter call. + testElement.onRouteEnter(); + await testAppMetricsProxy.whenCalled('recordPageShown'); + await testAppBrowserProxy.whenCalled('getAppList'); + }); + + teardown(function() { + testElement.remove(); + }); + + function getSelected() { + return Array.from( + testElement.shadowRoot.querySelectorAll('.option[active]')); + } + + test('test app chooser options', async function() { + const options = + Array.from(testElement.shadowRoot.querySelectorAll('.option')); + assertEquals(5, options.length); + + // First three options are selected and action button should be enabled. + assertDeepEquals(options.slice(0, 3), getSelected()); + assertFalse(testElement.$$('.action-button').disabled); + + // Click the first option to deselect it. + testBookmarkBrowserProxy.reset(); + options[0].click(); + + assertEquals( + 1, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertDeepEquals(options.slice(1, 3), getSelected()); + assertFalse(testElement.$$('.action-button').disabled); + + // Click fourth option to select it. + testBookmarkBrowserProxy.reset(); + options[3].click(); + + assertDeepEquals( + { + title: apps[3].name, + url: apps[3].url, + parentId: '1', + }, + await testBookmarkBrowserProxy.whenCalled('addBookmark')); + + assertDeepEquals(options.slice(1, 4), getSelected()); + assertFalse(testElement.$$('.action-button').disabled); + + // Click fourth option again to deselect it. + testBookmarkBrowserProxy.reset(); + options[3].click(); + + assertEquals( + 4, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertDeepEquals(options.slice(1, 3), getSelected()); + assertFalse(testElement.$$('.action-button').disabled); + + // Click second option to deselect it. + testBookmarkBrowserProxy.reset(); + options[1].click(); + + assertEquals( + 2, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertDeepEquals(options.slice(2, 3), getSelected()); + assertFalse(testElement.$$('.action-button').disabled); + + // Click third option to deselect all options. + testBookmarkBrowserProxy.reset(); + options[2].click(); + + assertEquals( + 3, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertEquals(0, getSelected().length); + assertTrue(testElement.$$('.action-button').disabled); + }); + + test('test app chooser skip button', async function() { + const options = testElement.shadowRoot.querySelectorAll('.option'); + testElement.wasBookmarkBarShownOnInit_ = true; + + // First option should be selected and action button should be enabled. + testElement.$.noThanksButton.click(); + assertEquals( + 1, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertEquals( + true, await testBookmarkBrowserProxy.whenCalled('toggleBookmarkBar')); + await testAppMetricsProxy.whenCalled('recordDidNothingAndChoseSkip'); + }); + + test('test app chooser next button', async function() { + const options = testElement.shadowRoot.querySelectorAll('.option'); + testElement.wasBookmarkBarShownOnInit_ = true; + + // First option should be selected and action button should be enabled. + testElement.$$('.action-button').click(); + + await testAppMetricsProxy.whenCalled('recordDidNothingAndChoseNext'); + + // Test framework only records first result, but should be called 3 times. + assertEquals( + 0, await testAppBrowserProxy.whenCalled('recordProviderSelected')); + assertEquals(3, testAppBrowserProxy.providerSelectedCount); + }); + }); +});
diff --git a/chrome/test/data/webui/welcome/email_chooser_test.js b/chrome/test/data/webui/welcome/email_chooser_test.js index a14be67..4f4daa1 100644 --- a/chrome/test/data/webui/welcome/email_chooser_test.js +++ b/chrome/test/data/webui/welcome/email_chooser_test.js
@@ -4,7 +4,7 @@ cr.define('onboarding_welcome_email_chooser', function() { suite('EmailChooserTest', function() { - let emails = [ + const emails = [ { id: 0, name: 'Gmail', @@ -31,7 +31,7 @@ /** @type {EmailChooserElement} */ let testElement; - setup(function() { + setup(async function() { testEmailBrowserProxy = new TestNuxEmailProxy(); testEmailMetricsProxy = new TestMetricsProxy(); testBookmarkBrowserProxy = new TestBookmarkProxy(); @@ -44,24 +44,22 @@ PolymerTest.clearBody(); testElement = document.createElement('app-chooser'); document.body.appendChild(testElement); - testElement.singleSelect = true; + testElement.singleSelect = true; // Only allow selecting one email. testElement.appProxy = testEmailBrowserProxy; testElement.metricsManager = new nux.ModuleMetricsManager(testEmailMetricsProxy); // Simulate nux-email's onRouteEnter call. testElement.onRouteEnter(); - return Promise.all([ - testEmailMetricsProxy.whenCalled('recordPageShown'), - testEmailBrowserProxy.whenCalled('getAppList'), - ]); + await testEmailMetricsProxy.whenCalled('recordPageShown'); + await testEmailBrowserProxy.whenCalled('getAppList'); }); teardown(function() { testElement.remove(); }); - test('test email chooser options', function() { - let options = testElement.shadowRoot.querySelectorAll('.option'); + test('test email chooser options', async function() { + const options = testElement.shadowRoot.querySelectorAll('.option'); assertEquals(2, options.length); // First option is default selected and action button should be enabled. @@ -69,80 +67,64 @@ assertFalse(testElement.$$('.action-button').disabled); options[0].click(); - return testBookmarkBrowserProxy.whenCalled('removeBookmark') - .then(removedId => { - assertEquals(removedId, 1); - assertFalse(!!testElement.$$('.option[active]')); - assertTrue(testElement.$$('.action-button').disabled); - // Click second option, it should be selected. - testBookmarkBrowserProxy.reset(); - options[1].click(); - return Promise.all([ - testBookmarkBrowserProxy.whenCalled('addBookmark'), - ]); - }) - .then(responses => { - let addResponse = responses[0]; + assertEquals( + 1, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); - assertEquals(addResponse.title, emails[1].name); - assertEquals(addResponse.url, emails[1].url); - assertEquals(addResponse.parentId, '1'); - assertEquals(testElement.$$('.option[active]'), options[1]); - assertFalse(testElement.$$('.action-button').disabled); + assertFalse(!!testElement.$$('.option[active]')); + assertTrue(testElement.$$('.action-button').disabled); - // Click second option again, it should be deselected and action - // button should be disabled. - testBookmarkBrowserProxy.reset(); - options[1].click(); - return testBookmarkBrowserProxy.whenCalled('removeBookmark'); - }) - .then(removedId => { - assertEquals(removedId, 2); + // Click second option, it should be selected. + testBookmarkBrowserProxy.reset(); + options[1].click(); - assertFalse(!!testElement.$$('.option[active]')); - assertTrue(testElement.$$('.action-button').disabled); - }); + assertDeepEquals( + { + title: emails[1].name, + url: emails[1].url, + parentId: '1', + }, + await testBookmarkBrowserProxy.whenCalled('addBookmark')); + + assertEquals(testElement.$$('.option[active]'), options[1]); + assertFalse(testElement.$$('.action-button').disabled); + + // Click second option again, it should be deselected and action + // button should be disabled. + testBookmarkBrowserProxy.reset(); + options[1].click(); + + assertEquals( + 2, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + + assertFalse(!!testElement.$$('.option[active]')); + assertTrue(testElement.$$('.action-button').disabled); }); - test('test email chooser skip button', function() { - let options = testElement.shadowRoot.querySelectorAll('.option'); + test('test email chooser skip button', async function() { + const options = testElement.shadowRoot.querySelectorAll('.option'); testElement.wasBookmarkBarShownOnInit_ = true; // First option should be selected and action button should be enabled. testElement.$.noThanksButton.click(); - return Promise - .all([ - testBookmarkBrowserProxy.whenCalled('removeBookmark'), - testBookmarkBrowserProxy.whenCalled('toggleBookmarkBar'), - testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseSkip'), - ]) - .then(responses => { - let removeBookmarkResponse = responses[0]; - let toggleBookmarkBarResponse = responses[1]; - assertEquals(1, removeBookmarkResponse); - assertEquals(true, toggleBookmarkBarResponse); - }); + await testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseSkip'); + assertEquals( + 1, await testBookmarkBrowserProxy.whenCalled('removeBookmark')); + assertEquals( + true, await testBookmarkBrowserProxy.whenCalled('toggleBookmarkBar')); }); - test('test email chooser next button', function() { - let options = testElement.shadowRoot.querySelectorAll('.option'); + test('test email chooser next button', async function() { + const options = testElement.shadowRoot.querySelectorAll('.option'); testElement.wasBookmarkBarShownOnInit_ = true; // First option should be selected and action button should be enabled. testElement.$$('.action-button').click(); - return Promise - .all([ - testEmailBrowserProxy.whenCalled('recordProviderSelected'), - testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseNext'), - ]) - .then(responses => { - let recordProviderSelectedResponse = responses[0]; - // Id for the provider that was selected. - assertEquals(0, recordProviderSelectedResponse[0]); - }); + await testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseNext'); + assertEquals( + 0, await testEmailBrowserProxy.whenCalled('recordProviderSelected')); }); }); });
diff --git a/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js index 75f4376..cbb3b65 100644 --- a/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js +++ b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js
@@ -33,6 +33,27 @@ } }; +OnboardingWelcomeAppChooserTest = class extends OnboardingWelcomeBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://welcome/shared/app_chooser.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + 'app_chooser_test.js', + 'test_nux_app_proxy.js', + 'test_metrics_proxy.js', + 'test_bookmark_proxy.js', + ]); + } +}; + +TEST_F('OnboardingWelcomeAppChooserTest', 'All', function() { + mocha.run(); +}); + OnboardingWelcomeEmailChooserTest = class extends OnboardingWelcomeBrowserTest { /** @override */ get browsePreload() {
diff --git a/chrome/test/data/webui/welcome/test_nux_app_proxy.js b/chrome/test/data/webui/welcome/test_nux_app_proxy.js new file mode 100644 index 0000000..d77c0d5 --- /dev/null +++ b/chrome/test/data/webui/welcome/test_nux_app_proxy.js
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @implements {nux.AppProxy} */ +class TestNuxAppProxy extends TestBrowserProxy { + constructor() { + super([ + 'cacheBookmarkIcon', + 'getAppList', + 'recordProviderSelected', + ]); + + this.providerSelectedCount = 0; + + /** @private {!Array<!nux.BookmarkListItem>} */ + this.appList_ = []; + } + + /** @override */ + getAppList() { + this.methodCalled('getAppList'); + return Promise.resolve(this.appList_); + } + + /** @override */ + cacheBookmarkIcon() { + this.methodCalled('cacheBookmarkIcon'); + } + + /** @override */ + recordProviderSelected(providerId) { + this.methodCalled('recordProviderSelected', providerId); + this.providerSelectedCount++; + } + + /** @param {!Array<!nux.BookmarkListItem>} appList */ + setAppList(appList) { + this.appList_ = appList; + } +}
diff --git a/chrome/test/data/webui/welcome/test_nux_email_proxy.js b/chrome/test/data/webui/welcome/test_nux_email_proxy.js index 2a41e7b2..c72ded3 100644 --- a/chrome/test/data/webui/welcome/test_nux_email_proxy.js +++ b/chrome/test/data/webui/welcome/test_nux_email_proxy.js
@@ -2,81 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -/** @implements {nux.ModuleMetricsProxy} */ -class TestEmailMetricsProxy extends TestBrowserProxy { - constructor() { - super([ - 'recordChoseAnOptionAndChoseNext', - 'recordChoseAnOptionAndChoseSkip', - 'recordChoseAnOptionAndNavigatedAway', - 'recordClickedDisabledNextButtonAndChoseNext', - 'recordClickedDisabledNextButtonAndChoseSkip', - 'recordClickedDisabledNextButtonAndNavigatedAway', - 'recordDidNothingAndChoseNext', - 'recordDidNothingAndChoseSkip', - 'recordDidNothingAndNavigatedAway', - 'recordNavigatedAwayThroughBrowserHistory', - 'recordPageShown', - ]); - } - - /** @override */ - recordChoseAnOptionAndChoseNext() { - this.methodCalled('recordChoseAnOptionAndChoseNext'); - } - - /** @override */ - recordChoseAnOptionAndChoseSkip() { - this.methodCalled('recordChoseAnOptionAndChoseSkip'); - } - - /** @override */ - recordChoseAnOptionAndNavigatedAway() { - this.methodCalled('recordChoseAnOptionAndNavigatedAway'); - } - - /** @override */ - recordClickedDisabledNextButtonAndChoseNext() { - this.methodCalled('recordClickedDisabledNextButtonAndChoseNext'); - } - - /** @override */ - recordClickedDisabledNextButtonAndChoseSkip() { - this.methodCalled('recordClickedDisabledNextButtonAndChoseSkip'); - } - - /** @override */ - recordClickedDisabledNextButtonAndNavigatedAway() { - this.methodCalled('recordClickedDisabledNextButtonAndNavigatedAway'); - } - - /** @override */ - recordDidNothingAndChoseNext() { - this.methodCalled('recordDidNothingAndChoseNext'); - } - - /** @override */ - recordDidNothingAndChoseSkip() { - this.methodCalled('recordDidNothingAndChoseSkip'); - } - - /** @override */ - recordDidNothingAndNavigatedAway() { - this.methodCalled('recordDidNothingAndNavigatedAway'); - } - - /** @override */ - recordNavigatedAwayThroughBrowserHistory() { - this.methodCalled('recordNavigatedAwayThroughBrowserHistory'); - } - - /** @override */ - recordPageShown() { - this.methodCalled('recordPageShown'); - } -} - /** @implements {nux.AppProxy} */ class TestNuxEmailProxy extends TestBrowserProxy { constructor() { @@ -102,8 +27,8 @@ } /** @override */ - recordProviderSelected() { - this.methodCalled('recordProviderSelected', arguments); + recordProviderSelected(providerId) { + this.methodCalled('recordProviderSelected', providerId); } /** @param {!Array<!nux.BookmarkListItem>} emailList */
diff --git a/chrome/test/media_router/resources/presentation_receiver.html b/chrome/test/media_router/resources/presentation_receiver.html index 9508056..1c41be5 100644 --- a/chrome/test/media_router/resources/presentation_receiver.html +++ b/chrome/test/media_router/resources/presentation_receiver.html
@@ -4,13 +4,11 @@ <title>Media Router Integration Test - Receiver Page</title> <script> const addConnection = connection => { - connection.onconnect = () => { - connection.onmessage = event => { - if (event.data == 'close') { - connection.close(); - } else { - connection.send('Pong: ' + event.data); - } + connection.onmessage = event => { + if (event.data == 'close') { + connection.close(); + } else { + connection.send('Pong: ' + event.data); } }; };
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 4fffe1c..1d5ad87 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -276,8 +276,8 @@ "cast_extension_message_filter.h", "cast_extension_url_loader_factory.cc", "cast_extension_url_loader_factory.h", - "cast_web_view_extension.cc", - "cast_web_view_extension.h", + "extension_page.cc", + "extension_page.h", "extension_request_protocol_handler.cc", "extension_request_protocol_handler.h", "extensions/api/accessibility_private/accessibility_extension_api.cc", @@ -340,8 +340,6 @@ "accessibility/touch_exploration_controller.h", "accessibility/touch_exploration_manager.cc", "accessibility/touch_exploration_manager.h", - "cast_web_view_extension.h", - "cast_web_view_extension.h", "ui/aura/accessibility/automation_manager_aura.cc", "ui/aura/accessibility/automation_manager_aura.h", "ui/aura/accessibility/ax_tree_source_aura.cc",
diff --git a/chromecast/browser/cast_content_window_aura.h b/chromecast/browser/cast_content_window_aura.h index 7ce1a23..c552cbf6 100644 --- a/chromecast/browser/cast_content_window_aura.h +++ b/chromecast/browser/cast_content_window_aura.h
@@ -26,6 +26,7 @@ class CastContentWindowAura : public CastContentWindow, public aura::WindowObserver { public: + explicit CastContentWindowAura(const CastContentWindow::CreateParams& params); ~CastContentWindowAura() override; // CastContentWindow implementation: @@ -48,11 +49,6 @@ void OnWindowDestroyed(aura::Window* window) override; private: - friend class CastContentWindow; - - // This class should only be instantiated by CastContentWindow::Create. - CastContentWindowAura(const CastContentWindow::CreateParams& params); - CastContentWindow::Delegate* const delegate_; // Utility class for detecting and dispatching gestures to delegates.
diff --git a/chromecast/browser/cast_extension_host.cc b/chromecast/browser/cast_extension_host.cc index c5a360a..53eef80 100644 --- a/chromecast/browser/cast_extension_host.cc +++ b/chromecast/browser/cast_extension_host.cc
@@ -4,11 +4,15 @@ #include "chromecast/browser/cast_extension_host.h" +#include <string> + +#include "base/strings/utf_string_conversions.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/notification_types.h" #include "extensions/browser/runtime_data.h" @@ -23,20 +27,17 @@ namespace chromecast { -CastExtensionHost::CastExtensionHost(content::BrowserContext* browser_context, - CastWebView::Delegate* delegate, - const extensions::Extension* extension, - const GURL& initial_url, - content::SiteInstance* site_instance, - extensions::ViewType host_type) +CastExtensionHost::CastExtensionHost( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + const GURL& initial_url, + scoped_refptr<content::SiteInstance> site_instance) : extensions::ExtensionHost(extension, - site_instance, + site_instance.get(), initial_url, - host_type), - browser_context_(browser_context), - delegate_(delegate) { + extensions::VIEW_TYPE_EXTENSION_POPUP), + browser_context_(browser_context) { DCHECK(browser_context_); - DCHECK(delegate_); } CastExtensionHost::~CastExtensionHost() {} @@ -83,8 +84,15 @@ const base::string16& message, int32_t line_no, const base::string16& source_id) { - return delegate_->OnAddMessageToConsoleReceived(level, message, line_no, - source_id); + std::string context = "Cast Extension:"; + base::string16 single_line_message; + // Mult-line message is not friendly to dumpstate redact. + base::ReplaceChars(message, base::ASCIIToUTF16("\n"), + base::ASCIIToUTF16("\\n "), &single_line_message); + logging::LogMessage("CONSOLE", line_no, ::logging::LOG_INFO).stream() + << context << " \"" << single_line_message << "\", source: " << source_id + << " (" << line_no << ")"; + return true; } void CastExtensionHost::Observe(int type,
diff --git a/chromecast/browser/cast_extension_host.h b/chromecast/browser/cast_extension_host.h index b4cb6f3..b33b0d3 100644 --- a/chromecast/browser/cast_extension_host.h +++ b/chromecast/browser/cast_extension_host.h
@@ -7,13 +7,12 @@ #include "base/macros.h" #include "base/strings/string16.h" -#include "chromecast/browser/cast_web_view.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -#include "content/public/browser/web_contents.h" #include "extensions/browser/extension_host.h" namespace content { +class BrowserContext; class NotificationSource; } @@ -29,11 +28,9 @@ public content::NotificationObserver { public: CastExtensionHost(content::BrowserContext* browser_context, - CastWebView::Delegate* delegate, const extensions::Extension* extension, const GURL& initial_url, - content::SiteInstance* site_instance, - extensions::ViewType host_type); + scoped_refptr<content::SiteInstance> site_instance); ~CastExtensionHost() override; // extensions::ExtensionHost implementation: @@ -57,7 +54,6 @@ content::NotificationRegistrar registrar_; content::BrowserContext* const browser_context_; - CastWebView::Delegate* const delegate_; DISALLOW_COPY_AND_ASSIGN(CastExtensionHost); };
diff --git a/chromecast/browser/cast_web_contents.h b/chromecast/browser/cast_web_contents.h index 32b2ed4..d60a174 100644 --- a/chromecast/browser/cast_web_contents.h +++ b/chromecast/browser/cast_web_contents.h
@@ -87,6 +87,7 @@ Delegate* delegate; bool enabled_for_dev; bool use_cma_renderer; + bool is_root_window = false; }; // Page state for the main frame. @@ -99,9 +100,16 @@ ERROR, // Main frame is in an error state. }; + static std::vector<CastWebContents*>& GetAll(); + CastWebContents() = default; virtual ~CastWebContents() = default; + // Tab identifier for the WebContents, mainly used by the tabs extension API. + // Tab IDs may be re-used, but no two live CastWebContents should have the + // same tab ID at any given time. + virtual int tab_id() const = 0; + // TODO(seantopping): Hide this, clients shouldn't use WebContents directly. virtual content::WebContents* web_contents() const = 0; virtual PageState page_state() const = 0;
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc index 41c27e6..e28d1ed 100644 --- a/chromecast/browser/cast_web_contents_impl.cc +++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/no_destructor.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chromecast/base/chromecast_switches.h" #include "chromecast/browser/cast_browser_process.h" @@ -26,6 +27,19 @@ namespace chromecast { +namespace { + +// IDs start at 1, since 0 is reserved for the root content window. +size_t next_tab_id = 1; + +} // namespace + +// static +std::vector<CastWebContents*>& CastWebContents::GetAll() { + static base::NoDestructor<std::vector<CastWebContents*>> instance; + return *instance; +} + CastWebContentsImpl::CastWebContentsImpl(content::WebContents* web_contents, const InitParams& init_params) : web_contents_(web_contents), @@ -36,6 +50,7 @@ use_cma_renderer_(init_params.use_cma_renderer), remote_debugging_server_( shell::CastBrowserProcess::GetInstance()->remote_debugging_server()), + tab_id_(init_params.is_root_window ? 0 : next_tab_id++), closing_(false), stopped_(false), stop_notified_(false), @@ -46,6 +61,7 @@ DCHECK(web_contents_); DCHECK(web_contents_->GetController().IsInitialNavigation()); DCHECK(!web_contents_->IsLoading()); + CastWebContents::GetAll().push_back(this); content::WebContentsObserver::Observe(web_contents_); if (enabled_for_dev_) { LOG(INFO) << "Enabling dev console for CastWebContentsImpl"; @@ -67,6 +83,16 @@ for (auto& observer : observer_list_) { observer.ResetCastWebContents(); } + auto& all_cast_web_contents = CastWebContents::GetAll(); + auto it = std::find(all_cast_web_contents.begin(), + all_cast_web_contents.end(), this); + if (it != all_cast_web_contents.end()) { + all_cast_web_contents.erase(it); + } +} + +int CastWebContentsImpl::tab_id() const { + return tab_id_; } content::WebContents* CastWebContentsImpl::web_contents() const {
diff --git a/chromecast/browser/cast_web_contents_impl.h b/chromecast/browser/cast_web_contents_impl.h index 68fb0a7..e4cd03f 100644 --- a/chromecast/browser/cast_web_contents_impl.h +++ b/chromecast/browser/cast_web_contents_impl.h
@@ -40,6 +40,7 @@ PageState page_state() const override; // CastWebContents implementation: + int tab_id() const override; void SetDelegate(Delegate* delegate) override; void AddRendererFeatures(std::vector<RendererFeature> features) override; void AllowWebAndMojoWebUiBindings() override; @@ -95,6 +96,7 @@ base::flat_set<std::unique_ptr<CastWebContents>> inner_contents_; std::vector<RendererFeature> renderer_features_; + const int tab_id_; base::TimeTicks start_loading_ticks_; bool closing_; bool stopped_;
diff --git a/chromecast/browser/cast_web_contents_manager.cc b/chromecast/browser/cast_web_contents_manager.cc index 6f29ba8..89e9664a 100644 --- a/chromecast/browser/cast_web_contents_manager.cc +++ b/chromecast/browser/cast_web_contents_manager.cc
@@ -21,10 +21,6 @@ #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" -#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) -#include "chromecast/browser/cast_web_view_extension.h" -#endif - namespace chromecast { CastWebContentsManager::CastWebContentsManager( @@ -44,22 +40,20 @@ std::unique_ptr<CastWebView> CastWebContentsManager::CreateWebView( const CastWebView::CreateParams& params, scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, const GURL& initial_url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return web_view_factory_->CreateWebView( - params, this, std::move(site_instance), extension, initial_url); + params, this, std::move(site_instance), initial_url); } std::unique_ptr<CastWebView> CastWebContentsManager::CreateWebView( const CastWebView::CreateParams& params, - const extensions::Extension* extension, const GURL& initial_url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return web_view_factory_->CreateWebView( params, this, content::SiteInstance::CreateForURL(browser_context_, initial_url), - extension, initial_url); + initial_url); } void CastWebContentsManager::DelayWebContentsDeletion(
diff --git a/chromecast/browser/cast_web_contents_manager.h b/chromecast/browser/cast_web_contents_manager.h index ec96dcf..85af3f80 100644 --- a/chromecast/browser/cast_web_contents_manager.h +++ b/chromecast/browser/cast_web_contents_manager.h
@@ -23,10 +23,6 @@ class WebContents; } // namespace content -namespace extensions { -class Extension; -} // namespace extensions - namespace chromecast { class CastWebViewFactory; @@ -45,12 +41,10 @@ std::unique_ptr<CastWebView> CreateWebView( const CastWebView::CreateParams& params, scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, const GURL& initial_url); std::unique_ptr<CastWebView> CreateWebView( const CastWebView::CreateParams& params, - const extensions::Extension* extension, const GURL& initial_url); // Take ownership of |web_contents| and delete after |time_delta|, or sooner
diff --git a/chromecast/browser/cast_web_view_extension.cc b/chromecast/browser/cast_web_view_extension.cc deleted file mode 100644 index 2411c05..0000000 --- a/chromecast/browser/cast_web_view_extension.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromecast/browser/cast_web_view_extension.h" - -#include "base/logging.h" -#include "chromecast/browser/cast_browser_process.h" -#include "chromecast/browser/cast_extension_host.h" -#include "chromecast/browser/devtools/remote_debugging_server.h" -#include "content/public/browser/web_contents_observer.h" -#include "extensions/browser/extension_system.h" -#include "net/base/net_errors.h" -#include "ui/aura/window.h" - -namespace chromecast { - -CastWebViewExtension::CastWebViewExtension( - const CreateParams& params, - content::BrowserContext* browser_context, - scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, - const GURL& initial_url) - : delegate_(params.delegate), - window_(shell::CastContentWindow::Create(params.window_params)), - extension_host_(std::make_unique<CastExtensionHost>( - browser_context, - params.delegate, - extension, - initial_url, - site_instance.get(), - extensions::VIEW_TYPE_EXTENSION_POPUP)), - cast_web_contents_( - extension_host_->host_contents(), - {delegate_, params.enabled_for_dev, params.use_cma_renderer}) { - DCHECK(delegate_); - content::WebContentsObserver::Observe(web_contents()); - web_contents()->GetNativeView()->SetName(params.activity_id); -} - -CastWebViewExtension::~CastWebViewExtension() { - content::WebContentsObserver::Observe(nullptr); -} - -shell::CastContentWindow* CastWebViewExtension::window() const { - return window_.get(); -} - -content::WebContents* CastWebViewExtension::web_contents() const { - return extension_host_->host_contents(); -} - -CastWebContents* CastWebViewExtension::cast_web_contents() { - return &cast_web_contents_; -} - -void CastWebViewExtension::LoadUrl(GURL url) { - extension_host_->CreateRenderViewSoon(); -} - -// Extension web view cannot be closed deliberately. -void CastWebViewExtension::ClosePage(const base::TimeDelta& shutdown_delay) {} - -void CastWebViewExtension::InitializeWindow( - CastWindowManager* window_manager, - CastWindowManager::WindowId z_order, - VisibilityPriority initial_priority) { - window_->CreateWindowForWebContents(web_contents(), window_manager, z_order, - initial_priority); - web_contents()->Focus(); -} - -void CastWebViewExtension::GrantScreenAccess() { - window_->GrantScreenAccess(); -} - -void CastWebViewExtension::RevokeScreenAccess() { - window_->RevokeScreenAccess(); -} - -void CastWebViewExtension::RenderViewCreated( - content::RenderViewHost* render_view_host) { - content::RenderWidgetHostView* view = - render_view_host->GetWidget()->GetView(); - if (view) { - view->SetBackgroundColor(SK_ColorTRANSPARENT); - } -} - -} // namespace chromecast
diff --git a/chromecast/browser/cast_web_view_extension.h b/chromecast/browser/cast_web_view_extension.h deleted file mode 100644 index ff4c14d..0000000 --- a/chromecast/browser/cast_web_view_extension.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMECAST_BROWSER_CAST_WEB_VIEW_EXTENSION_H_ -#define CHROMECAST_BROWSER_CAST_WEB_VIEW_EXTENSION_H_ - -#include <memory> - -#include "chromecast/browser/cast_web_contents_impl.h" -#include "chromecast/browser/cast_web_view.h" -#include "content/public/browser/media_capture_devices.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host.h" -#include "content/public/browser/render_widget_host_view.h" -#include "extensions/browser/extension_host.h" -#include "extensions/browser/notification_types.h" -#include "extensions/common/extension.h" -#include "url/gurl.h" - -namespace chromecast { - -class CastExtensionHost; - -// A simplified interface for loading and displaying WebContents in cast_shell. -class CastWebViewExtension : public CastWebView, - public content::WebContentsObserver { - public: - // |delegate| and |browser_context| should outlive the lifetime of this - // object. - CastWebViewExtension(const CreateParams& params, - content::BrowserContext* browser_context, - scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, - const GURL& initial_url); - ~CastWebViewExtension() override; - - shell::CastContentWindow* window() const override; - - content::WebContents* web_contents() const override; - CastWebContents* cast_web_contents() override; - - // CastWebView implementation: - void LoadUrl(GURL url) override; - void ClosePage(const base::TimeDelta& shutdown_delay) override; - void InitializeWindow(CastWindowManager* window_manager, - CastWindowManager::WindowId z_order, - VisibilityPriority initial_priority) override; - void GrantScreenAccess() override; - void RevokeScreenAccess() override; - - private: - // WebContentsObserver implementation: - void RenderViewCreated(content::RenderViewHost* render_view_host) override; - - Delegate* const delegate_; - const std::unique_ptr<shell::CastContentWindow> window_; - const std::unique_ptr<CastExtensionHost> extension_host_; - CastWebContentsImpl cast_web_contents_; - scoped_refptr<content::SiteInstance> site_instance_; - - DISALLOW_COPY_AND_ASSIGN(CastWebViewExtension); -}; - -} // namespace chromecast - -#endif // CHROMECAST_BROWSER_CAST_WEB_VIEW_EXTENSION_H_
diff --git a/chromecast/browser/cast_web_view_factory.cc b/chromecast/browser/cast_web_view_factory.cc index f678811..1bc5c74 100644 --- a/chromecast/browser/cast_web_view_factory.cc +++ b/chromecast/browser/cast_web_view_factory.cc
@@ -7,10 +7,6 @@ #include "chromecast/browser/cast_web_view_default.h" #include "chromecast/chromecast_buildflags.h" -#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) -#include "chromecast/browser/cast_web_view_extension.h" -#endif - namespace chromecast { CastWebViewFactory::CastWebViewFactory(content::BrowserContext* browser_context) @@ -25,29 +21,17 @@ observer.OnCastWebViewDestroyed(web_view); } web_view->RemoveObserver(this); - active_webviews_.erase(std::find_if( - active_webviews_.begin(), active_webviews_.end(), - [web_view](const ActiveWebview& w) { return w.web_view == web_view; })); } std::unique_ptr<CastWebView> CastWebViewFactory::CreateWebView( const CastWebView::CreateParams& params, CastWebContentsManager* web_contents_manager, scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, const GURL& initial_url) { std::unique_ptr<CastWebView> webview; - if (extension) { -#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) - webview = std::make_unique<CastWebViewExtension>( - params, browser_context_, site_instance, extension, initial_url); -#endif - } else { - webview = std::make_unique<CastWebViewDefault>( - params, web_contents_manager, browser_context_, site_instance); - } + webview = std::make_unique<CastWebViewDefault>( + params, web_contents_manager, browser_context_, site_instance); if (webview) { - active_webviews_.push_back({webview.get(), next_id_++}); webview->AddObserver(this); } for (auto& observer : observer_list_) {
diff --git a/chromecast/browser/cast_web_view_factory.h b/chromecast/browser/cast_web_view_factory.h index b556a8b..9c73451b 100644 --- a/chromecast/browser/cast_web_view_factory.h +++ b/chromecast/browser/cast_web_view_factory.h
@@ -21,19 +21,10 @@ class SiteInstance; } // namespace content -namespace extensions { -class Extension; -} // namespace extensions - namespace chromecast { class CastWebContentsManager; -struct ActiveWebview { - CastWebView* web_view; - int id; -}; - class CastWebViewFactory : public CastWebView::Observer { public: class Observer : public base::CheckedObserver { @@ -52,15 +43,11 @@ const CastWebView::CreateParams& params, CastWebContentsManager* web_contents_manager, scoped_refptr<content::SiteInstance> site_instance, - const extensions::Extension* extension, const GURL& initial_url); void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - const std::vector<ActiveWebview>& active_webviews() const { - return active_webviews_; - } content::BrowserContext* browser_context() const { return browser_context_; } protected: @@ -71,9 +58,6 @@ base::RepeatingCallback<void(CastWebView*, int)> register_callback_; base::ObserverList<Observer> observer_list_; - std::vector<ActiveWebview> active_webviews_; - int next_id_ = 1; - DISALLOW_COPY_AND_ASSIGN(CastWebViewFactory); };
diff --git a/chromecast/browser/extension_page.cc b/chromecast/browser/extension_page.cc new file mode 100644 index 0000000..d72bf754 --- /dev/null +++ b/chromecast/browser/extension_page.cc
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/extension_page.h" + +#include <utility> + +#include "base/logging.h" +#include "chromecast/browser/cast_content_window_aura.h" +#include "chromecast/browser/cast_extension_host.h" +#include "chromecast/graphics/cast_window_manager.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "ui/aura/window.h" + +namespace chromecast { + +ExtensionPage::ExtensionPage( + const CastWebContents::InitParams& init_params, + const shell::CastContentWindow::CreateParams& window_params, + std::unique_ptr<CastExtensionHost> extension_host, + CastWindowManager* window_manager) + : window_(std::make_unique<shell::CastContentWindowAura>(window_params)), + extension_host_(std::move(extension_host)), + window_manager_(window_manager), + cast_web_contents_(extension_host_->host_contents(), init_params) { + content::WebContentsObserver::Observe(web_contents()); +} + +ExtensionPage::~ExtensionPage() { + content::WebContentsObserver::Observe(nullptr); +} + +content::WebContents* ExtensionPage::web_contents() const { + return extension_host_->host_contents(); +} + +CastWebContents* ExtensionPage::cast_web_contents() { + return &cast_web_contents_; +} + +void ExtensionPage::Launch() { + extension_host_->CreateRenderViewSoon(); +} + +void ExtensionPage::InitializeWindow() { + window_->GrantScreenAccess(); + window_->CreateWindowForWebContents( + web_contents(), window_manager_, CastWindowManager::APP, + chromecast::shell::VisibilityPriority::STICKY_ACTIVITY); + web_contents()->Focus(); +} + +void ExtensionPage::RenderViewCreated( + content::RenderViewHost* render_view_host) { + content::RenderWidgetHostView* view = + render_view_host->GetWidget()->GetView(); + if (view) { + view->SetBackgroundColor(SK_ColorTRANSPARENT); + } +} + +} // namespace chromecast
diff --git a/chromecast/browser/extension_page.h b/chromecast/browser/extension_page.h new file mode 100644 index 0000000..1e9bbee --- /dev/null +++ b/chromecast/browser/extension_page.h
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_BROWSER_EXTENSION_PAGE_H_ +#define CHROMECAST_BROWSER_EXTENSION_PAGE_H_ + +#include <memory> + +#include "chromecast/browser/cast_content_window.h" +#include "chromecast/browser/cast_web_contents_impl.h" +#include "content/public/browser/web_contents_observer.h" + +namespace chromecast { +namespace shell { +class CastContentWindowAura; +} // namespace shell + +class CastExtensionHost; +class CastWindowManager; + +// A simplified interface for loading and displaying WebContents in cast_shell. +class ExtensionPage : public content::WebContentsObserver { + public: + ExtensionPage(const CastWebContents::InitParams& init_params, + const shell::CastContentWindow::CreateParams& window_params, + std::unique_ptr<CastExtensionHost> extension_host, + CastWindowManager* window_manager); + + ~ExtensionPage() override; + + content::WebContents* web_contents() const; + CastWebContents* cast_web_contents(); + + void Launch(); + void InitializeWindow(); + + private: + // WebContentsObserver implementation: + void RenderViewCreated(content::RenderViewHost* render_view_host) override; + + const std::unique_ptr<shell::CastContentWindowAura> window_; + const std::unique_ptr<CastExtensionHost> extension_host_; + CastWindowManager* window_manager_; + CastWebContentsImpl cast_web_contents_; + scoped_refptr<content::SiteInstance> site_instance_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionPage); +}; + +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_EXTENSION_PAGE_H_
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.cc b/chromecast/browser/extensions/api/tabs/tabs_api.cc index 19fce6b6..46ee1f5 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_api.cc +++ b/chromecast/browser/extensions/api/tabs/tabs_api.cc
@@ -25,8 +25,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chromecast/browser/cast_browser_process.h" -#include "chromecast/browser/cast_web_view.h" -#include "chromecast/browser/cast_web_view_factory.h" +#include "chromecast/browser/cast_web_contents.h" #include "chromecast/browser/extensions/api/tabs/tabs_constants.h" #include "chromecast/service/cast_service.h" #include "content/public/browser/browser_context.h" @@ -54,8 +53,7 @@ using content::WebContents; using zoom::ZoomController; -using chromecast::ActiveWebview; -using chromecast::CastWebView; +using chromecast::CastWebContents; namespace extensions { @@ -110,13 +108,14 @@ return info; } -std::unique_ptr<api::tabs::Tab> CreateTabObject(const ActiveWebview* webview, - const Extension* extension, - int tab_index) { - WebContents* contents = webview->web_view->web_contents(); +std::unique_ptr<api::tabs::Tab> CreateTabObject( + const CastWebContents* cast_web_contents, + const Extension* extension, + int tab_index) { + WebContents* contents = cast_web_contents->web_contents(); bool is_loading = contents->IsLoading(); auto tab_object = std::make_unique<api::tabs::Tab>(); - tab_object->id = std::make_unique<int>(webview->id); + tab_object->id = std::make_unique<int>(cast_web_contents->tab_id()); tab_object->index = tab_index; tab_object->window_id = kCastWindowId; tab_object->status = std::make_unique<std::string>( @@ -142,33 +141,31 @@ } std::unique_ptr<base::ListValue> CreateTabList( - const std::vector<ActiveWebview>& webviews, + const std::vector<CastWebContents*>& webviews, const Extension* extension) { std::unique_ptr<base::ListValue> tab_list(new base::ListValue()); for (size_t i = 0; i < webviews.size(); i++) { - tab_list->Append(CreateTabObject(&webviews[i], extension, i)->ToValue()); + tab_list->Append(CreateTabObject(webviews[i], extension, i)->ToValue()); } return tab_list; } -const std::vector<ActiveWebview>& GetTabList() { - return chromecast::shell::CastBrowserProcess::GetInstance() - ->web_view_factory() - ->active_webviews(); +const std::vector<CastWebContents*>& GetTabList() { + return chromecast::CastWebContents::GetAll(); } int GetActiveWebContentsIndex() { return 0; } -const ActiveWebview* GetWebViewForIndex(int index) { +const CastWebContents* GetWebViewForIndex(int index) { auto& tabs = GetTabList(); if (index >= 0 && index < static_cast<int>(tabs.size())) - return &tabs[index]; + return tabs[index]; return nullptr; } -const ActiveWebview* GetWebViewForTab(int tab_id, int* tab_index = nullptr) { +const CastWebContents* GetWebViewForTab(int tab_id, int* tab_index = nullptr) { if (tab_id == -1) { // Return the active tab int index = GetActiveWebContentsIndex(); @@ -179,10 +176,10 @@ auto& tabs = GetTabList(); for (size_t i = 0; i < tabs.size(); i++) { - if (tabs[i].id == tab_id) { + if (tabs[i]->tab_id() == tab_id) { if (tab_index) *tab_index = static_cast<int>(i); - return &tabs[i]; + return tabs[i]; } } return nullptr; @@ -192,8 +189,8 @@ const Extension* extension) { auto& tabs = GetTabList(); for (size_t i = 0; i < tabs.size(); i++) { - if (tabs[i].web_view->web_contents() == contents) { - return CreateTabObject(&tabs[i], extension, static_cast<int>(i)); + if (tabs[i]->web_contents() == contents) { + return CreateTabObject(tabs[i], extension, static_cast<int>(i)); } } @@ -201,9 +198,9 @@ } int GetActiveWebContentsID() { - const ActiveWebview* webview = + const CastWebContents* contents = GetWebViewForIndex(GetActiveWebContentsIndex()); - return webview ? webview->id : -1; + return contents ? contents->tab_id() : -1; } int GetID(const std::unique_ptr<int>& id) { @@ -378,7 +375,7 @@ } int index = GetActiveWebContentsIndex(); - const ActiveWebview* contents = GetWebViewForIndex(index); + const CastWebContents* contents = GetWebViewForIndex(index); if (!contents) return RespondNow(Error(keys::kNoSelectedTabError)); return RespondNow(ArgumentList(tabs::Get::Results::Create( @@ -463,7 +460,7 @@ int tab_id = params->tab_id; int tab_index; - const ActiveWebview* contents = GetWebViewForTab(tab_id, &tab_index); + const CastWebContents* contents = GetWebViewForTab(tab_id, &tab_index); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); @@ -479,10 +476,10 @@ // Return the caller, if it's a tab. If not the result isn't an error but an // empty tab (hence returning true). int index = GetActiveWebContentsIndex(); - const ActiveWebview* active = GetWebViewForIndex(index); + const CastWebContents* active = GetWebViewForIndex(index); WebContents* caller_contents = GetSenderWebContents(); std::unique_ptr<base::ListValue> results; - if (caller_contents && caller_contents == active->web_view->web_contents()) { + if (caller_contents && caller_contents == active->web_contents()) { results = tabs::Get::Results::Create( *CreateTabObject(active, extension(), index)); } @@ -508,7 +505,7 @@ ui::ListSelectionModel selection; std::string error; - const std::vector<ActiveWebview>& tabs = GetTabList(); + const std::vector<CastWebContents*>& tabs = GetTabList(); if (params->highlight_info.tabs.as_integers) { std::vector<int>& tab_indices = *params->highlight_info.tabs.as_integers; @@ -538,11 +535,12 @@ browser_context(), extension(), ExtensionTabUtil::kPopulateTabs))); } -bool TabsHighlightFunction::HighlightTab(const std::vector<ActiveWebview>& tabs, - ui::ListSelectionModel* selection, - int* active_index, - int index, - std::string* error) { +bool TabsHighlightFunction::HighlightTab( + const std::vector<CastWebContents*>& tabs, + ui::ListSelectionModel* selection, + int* active_index, + int index, + std::string* error) { // Make sure the index is in range. if (index >= 0 && index < static_cast<int>(tabs.size())) { *error = ErrorUtils::FormatErrorMessage(keys::kTabIndexNotFoundError, @@ -566,12 +564,12 @@ EXTENSION_FUNCTION_VALIDATE(params.get()); int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); } - web_contents_ = contents->web_view->web_contents(); + web_contents_ = contents->web_contents(); // Navigate the tab to a new location if the url is different. bool is_async = false; @@ -694,13 +692,13 @@ } int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); } - contents->web_view->web_contents()->GetController().Reload( + contents->web_contents()->GetController().Reload( bypass_cache ? content::ReloadType::BYPASSING_CACHE : content::ReloadType::NORMAL, true); @@ -763,10 +761,10 @@ } bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage(std::string* error) { - const ActiveWebview* webview = GetWebViewForTab(execute_tab_id_); + const CastWebContents* webview = GetWebViewForTab(execute_tab_id_); CHECK(webview); - content::WebContents* contents = webview->web_view->web_contents(); + content::WebContents* contents = webview->web_contents(); int frame_id = details_->frame_id ? *details_->frame_id : ExtensionApiFrameIdMap::kTopFrameId; @@ -815,7 +813,7 @@ ScriptExecutor* ExecuteCodeInTabFunction::GetScriptExecutor( std::string* error) { - const ActiveWebview* contents = GetWebViewForTab(execute_tab_id_); + const CastWebContents* contents = GetWebViewForTab(execute_tab_id_); if (!contents) return nullptr; @@ -847,14 +845,14 @@ std::string error; int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { error = ErrorUtils::FormatErrorMessage(keys::kTabNotFoundError, base::NumberToString(tab_id)); return RespondNow(Error(error)); } - WebContents* web_contents = contents->web_view->web_contents(); + WebContents* web_contents = contents->web_contents(); GURL url(web_contents->GetVisibleURL()); if (extension()->permissions_data()->IsRestrictedUrl(url, &error)) return RespondNow(Error(error)); @@ -881,13 +879,13 @@ EXTENSION_FUNCTION_VALIDATE(params); int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); } - WebContents* web_contents = contents->web_view->web_contents(); + WebContents* web_contents = contents->web_contents(); double zoom_level = ZoomController::FromWebContents(web_contents)->GetZoomLevel(); double zoom_factor = content::ZoomLevelToZoomFactor(zoom_level); @@ -902,13 +900,13 @@ EXTENSION_FUNCTION_VALIDATE(params); int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); } - WebContents* web_contents = contents->web_view->web_contents(); + WebContents* web_contents = contents->web_contents(); GURL url(web_contents->GetVisibleURL()); std::string error; if (extension()->permissions_data()->IsRestrictedUrl(url, &error)) @@ -955,13 +953,13 @@ std::string error; int tab_id = GetID(params->tab_id); - const ActiveWebview* contents = GetWebViewForTab(tab_id); + const CastWebContents* contents = GetWebViewForTab(tab_id); if (!contents) { return RespondNow(Error(ErrorUtils::FormatErrorMessage( keys::kTabNotFoundError, base::NumberToString(tab_id)))); } - WebContents* web_contents = contents->web_view->web_contents(); + WebContents* web_contents = contents->web_contents(); ZoomController* zoom_controller = ZoomController::FromWebContents(web_contents);
diff --git a/chromecast/browser/extensions/api/tabs/tabs_api.h b/chromecast/browser/extensions/api/tabs/tabs_api.h index da0233c5..ccc0ac1f 100644 --- a/chromecast/browser/extensions/api/tabs/tabs_api.h +++ b/chromecast/browser/extensions/api/tabs/tabs_api.h
@@ -17,7 +17,7 @@ #include "url/gurl.h" namespace chromecast { -struct ActiveWebview; +class CastWebContents; } namespace content { @@ -112,7 +112,7 @@ class TabsHighlightFunction : public UIThreadExtensionFunction { ~TabsHighlightFunction() override {} ResponseAction Run() override; - bool HighlightTab(const std::vector<chromecast::ActiveWebview>& tabs, + bool HighlightTab(const std::vector<chromecast::CastWebContents*>& tabs, ui::ListSelectionModel* selection, int* active_index, int index,
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc index 04037b0..6253404 100644 --- a/chromecast/browser/service/cast_service_simple.cc +++ b/chromecast/browser/service/cast_service_simple.cc
@@ -74,7 +74,6 @@ params.window_params.delegate = this; cast_web_view_ = web_contents_manager_->CreateWebView(params, nullptr, /* site_instance */ - nullptr, /* extension */ GURL() /* initial_url */); cast_web_view_->LoadUrl(startup_url_); cast_web_view_->GrantScreenAccess();
diff --git a/chromecast/browser/test/cast_browser_test.cc b/chromecast/browser/test/cast_browser_test.cc index 72c4101..c8df877 100644 --- a/chromecast/browser/test/cast_browser_test.cc +++ b/chromecast/browser/test/cast_browser_test.cc
@@ -63,7 +63,6 @@ params.window_params.delegate = this; cast_web_view_ = web_contents_manager_->CreateWebView(params, nullptr, /* site_instance */ - nullptr, /* extension */ GURL() /* initial_url */); return cast_web_view_->web_contents();
diff --git a/chromecast/media/cma/backend/cplay/cplay.cc b/chromecast/media/cma/backend/cplay/cplay.cc index 386386a..5f319cf 100644 --- a/chromecast/media/cma/backend/cplay/cplay.cc +++ b/chromecast/media/cma/backend/cplay/cplay.cc
@@ -20,6 +20,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/no_destructor.h" +#include "base/numerics/range.h" #include "chromecast/media/cma/backend/cast_audio_json.h" #include "chromecast/media/cma/backend/cplay/wav_header.h" #include "chromecast/media/cma/backend/mixer_input.h" @@ -55,6 +56,7 @@ LOG(INFO) << "Usage: " << command; LOG(INFO) << " -i input .wav file"; LOG(INFO) << " -o output .wav file"; + LOG(INFO) << " -r output samples per second"; LOG(INFO) << " [-c cast_audio.json path]"; LOG(INFO) << " [-v cast volume as fraction of 1 (0.0-1.0)]"; LOG(INFO) << " [-d max duration (s)]"; @@ -141,26 +143,6 @@ DISALLOW_COPY_AND_ASSIGN(WavMixerInputSource); }; -// Implementation of CastAudioJsonProvider that reads from a specified path. -class FixedCastAudioJsonProvider : public CastAudioJsonProvider { - public: - FixedCastAudioJsonProvider(const base::FilePath& path) : file_path_(path) {} - ~FixedCastAudioJsonProvider() override = default; - - std::unique_ptr<base::Value> GetCastAudioConfig() override { - std::string contents; - base::ReadFileToString(file_path_, &contents); - return base::JSONReader::Read(contents); - } - - void SetTuningChangedCallback(TuningChangedCallback callback) override {} - - private: - const base::FilePath file_path_; - - DISALLOW_COPY_AND_ASSIGN(FixedCastAudioJsonProvider); -}; - // OutputHandler interface to allow switching between alsa and file output. // TODO(bshaya): Add option to play directly to an output device! class OutputHandler { @@ -179,7 +161,6 @@ num_channels_(num_channels) { header_.SetNumChannels(num_channels); header_.SetSampleRate(sample_rate); - header_.SetBitsPerSample(sizeof(int16_t) * 8); // Write wav file header to fill space. We'll need to go back and fill in // the size later. @@ -198,13 +179,14 @@ } void WriteData(float* data, int num_frames) override { - std::vector<int16_t> fixed_data(num_frames * num_channels_); - for (size_t i = 0; i < fixed_data.size(); ++i) { - fixed_data[i] = - ::media::FixedSampleTypeTraits<int16_t>::FromFloat(data[i]); + std::vector<float> clipped_data(num_frames * num_channels_); + std::memcpy(clipped_data.data(), data, + clipped_data.size() * sizeof(clipped_data[0])); + for (size_t i = 0; i < clipped_data.size(); ++i) { + clipped_data[i] = base::ClampToRange(clipped_data[i], -1.0f, 1.0f); } - wav_file_.WriteAtCurrentPos(reinterpret_cast<char*>(fixed_data.data()), - sizeof(fixed_data[0]) * fixed_data.size()); + wav_file_.WriteAtCurrentPos(reinterpret_cast<char*>(clipped_data.data()), + sizeof(clipped_data[0]) * clipped_data.size()); } private: @@ -215,13 +197,14 @@ DISALLOW_COPY_AND_ASSIGN(WavOutputHandler); }; -class ClippingDetector { +class AudioMetrics { public: - ClippingDetector(int num_channels) : num_channels_(num_channels) {} - ~ClippingDetector() = default; + AudioMetrics(int num_channels) : num_channels_(num_channels) {} + ~AudioMetrics() = default; void ProcessFrames(float* data, int num_frames) { for (int i = 0; i < num_frames * num_channels_; ++i) { + squared_sum_ += std::pow(data[i], 2); if (std::fabs(data[i]) > 1.0) { ++clipped_samples_; largest_sample_ = std::max(largest_sample_, std::fabs(data[i])); @@ -231,6 +214,8 @@ } void PrintReport() { + LOG(INFO) << "RMS magnitude: " + << 20 * log10(std::sqrt(squared_sum_ / total_samples_)) << "dB"; if (clipped_samples_ == 0) { return; } @@ -244,15 +229,16 @@ int clipped_samples_ = 0; int total_samples_ = 0; float largest_sample_ = 0.0f; + double squared_sum_ = 0.0; - DISALLOW_COPY_AND_ASSIGN(ClippingDetector); + DISALLOW_COPY_AND_ASSIGN(AudioMetrics); }; Parameters ReadArgs(int argc, char* argv[]) { Parameters params; params.cast_audio_json_path = CastAudioJson::GetFilePath(); int opt; - while ((opt = getopt(argc, argv, "i:o:c:v:d:")) != -1) { + while ((opt = getopt(argc, argv, "i:o:c:v:d:r:")) != -1) { switch (opt) { case 'i': params.input_file_path = base::FilePath(optarg); @@ -271,6 +257,9 @@ case 'd': params.duration_s = strtod(optarg, nullptr); break; + case 'r': + params.output_samples_per_second = strtod(optarg, nullptr); + break; default: PrintHelp(argv[0]); exit(1); @@ -293,7 +282,16 @@ // Read input file. WavMixerInputSource input_source(params); - params.output_samples_per_second = input_source.input_samples_per_second(); + if (params.output_samples_per_second <= 0) { + params.output_samples_per_second = input_source.input_samples_per_second(); + } + if (params.output_samples_per_second != + input_source.input_samples_per_second()) { + LOG(INFO) << "Resampling from " << input_source.input_samples_per_second() + << " to " << params.output_samples_per_second; + } else { + LOG(INFO) << "Sample rate: " << params.output_samples_per_second; + } // Build Processing Pipeline. PostProcessingPipelineParser parser(params.cast_audio_json_path); @@ -313,7 +311,7 @@ // Set volume. std::string contents; base::ReadFileToString(params.cast_audio_json_path, &contents); - GetVolumeMap().LoadVolumeMap(base::JSONReader::Read(contents)); + GetVolumeMap().LoadVolumeMap(base::JSONReader::ReadDeprecated(contents)); float volume_dbfs = GetVolumeMap().VolumeToDbFS(params.cast_volume); float volume_multiplier = std::pow(10.0, volume_dbfs / 20.0); mixer_input.SetVolumeMultiplier(1.0); @@ -326,7 +324,7 @@ std::make_unique<WavOutputHandler>(params.output_file_path, pipeline->GetOutputChannelCount(), params.output_samples_per_second); - ClippingDetector clip_detector(pipeline->GetOutputChannelCount()); + AudioMetrics audio_metrics(pipeline->GetOutputChannelCount()); // Play! int frames_written = 0; @@ -334,11 +332,12 @@ frames_written / params.output_samples_per_second < params.duration_s) { pipeline->MixAndFilter(kReadSize, MixerInput::RenderingDelay()); - clip_detector.ProcessFrames(pipeline->GetOutput(), kReadSize); + audio_metrics.ProcessFrames(pipeline->GetOutput(), kReadSize); output_handler_->WriteData(pipeline->GetOutput(), kReadSize); + frames_written += kReadSize; } - clip_detector.PrintReport(); + audio_metrics.PrintReport(); return 0; }
diff --git a/chromecast/media/cma/backend/cplay/wav_header.h b/chromecast/media/cma/backend/cplay/wav_header.h index d081b6ee..432a7fa5 100644 --- a/chromecast/media/cma/backend/cplay/wav_header.h +++ b/chromecast/media/cma/backend/cplay/wav_header.h
@@ -10,19 +10,24 @@ namespace chromecast { namespace media { -// From http://soundfile.sapp.org/doc/WaveFormat/ +// This is a header for a .wav file with floating point data. It can be written +// directly to file (e.g. with reinterpret_cast<char*>) after SetDataSize(), +// SetNumChannels(), and SetSampleRate() have been called. +// From http://soundfile.sapp.org/doc/WaveFormat/ and +// http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html struct __attribute__((packed)) WavHeader { const char riff[4] = {'R', 'I', 'F', 'F'}; uint32_t chunk_size; // size of file - 8 const char wave[4] = {'W', 'A', 'V', 'E'}; const char fmt[4] = {'f', 'm', 't', ' '}; - const uint32_t subchunk_size = 16; - const uint16_t audio_format = 1; // PCM + const uint32_t subchunk_size = 18; + const uint16_t audio_format = 3; // FLOAT uint16_t num_channels; uint32_t sample_rate; uint32_t byte_rate; // sample_rate * num_channels * bytes per sample uint16_t block_align; // num_channels * bytes per sample - uint16_t bits_per_sample; + uint16_t bits_per_sample = 32; + uint16_t extension_size = 0; const char data[4] = {'d', 'a', 't', 'a'}; uint32_t subchunk_2_size; // bytes in the data @@ -44,12 +49,6 @@ sample_rate = sample_rate_in; byte_rate = sample_rate * num_channels * bits_per_sample / 8; } - - void SetBitsPerSample(int bits_per_sample_in) { - bits_per_sample = bits_per_sample_in; - byte_rate = sample_rate * num_channels * bits_per_sample / 8; - block_align = num_channels * bits_per_sample / 8; - } }; WavHeader::WavHeader() = default;
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc index 02effba4..e4f71bd 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc +++ b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc
@@ -37,9 +37,13 @@ MediaPipelineBackendForMixer::MediaPipelineBackendForMixer( const MediaPipelineDeviceParams& params) - : state_(kStateUninitialized), params_(params) {} + : state_(kStateUninitialized), params_(params), weak_factory_(this) { + weak_this_ = weak_factory_.GetWeakPtr(); +} -MediaPipelineBackendForMixer::~MediaPipelineBackendForMixer() {} +MediaPipelineBackendForMixer::~MediaPipelineBackendForMixer() { + DCHECK(GetTaskRunner()->RunsTasksInCurrentSequence()); +} MediaPipelineBackendForMixer::AudioDecoder* MediaPipelineBackendForMixer::CreateAudioDecoder() { @@ -262,7 +266,7 @@ GetTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&MediaPipelineBackendForMixer::OnVideoReadyToPlay, - base::Unretained(this))); + weak_this_)); } void MediaPipelineBackendForMixer::OnVideoReadyToPlay() {
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.h b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.h index e66f3e4..8c58f7f 100644 --- a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.h +++ b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "chromecast/media/cma/backend/video_decoder_for_mixer.h" #include "chromecast/public/media/media_pipeline_backend.h" #include "chromecast/public/media/media_pipeline_device_params.h" @@ -99,6 +100,9 @@ bool playback_started_ = false; float starting_playback_rate_ = 1.0; + base::WeakPtr<MediaPipelineBackendForMixer> weak_this_; + base::WeakPtrFactory<MediaPipelineBackendForMixer> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendForMixer); };
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 95d66b85..eb51d95 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -11951.0.0 \ No newline at end of file +11958.0.0 \ No newline at end of file
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index e61b3a1..309999a 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -51,8 +51,10 @@ "arc_oemcrypto_client.h", "audio_node.cc", "audio_node.h", - "auth_policy_client.cc", - "auth_policy_client.h", + "auth_policy/auth_policy_client.cc", + "auth_policy/auth_policy_client.h", + "auth_policy/fake_auth_policy_client.cc", + "auth_policy/fake_auth_policy_client.h", "cec_service_client.cc", "cec_service_client.h", "cicerone_client.cc", @@ -89,8 +91,6 @@ "fake_arc_obb_mounter_client.h", "fake_arc_oemcrypto_client.cc", "fake_arc_oemcrypto_client.h", - "fake_auth_policy_client.cc", - "fake_auth_policy_client.h", "fake_cec_service_client.cc", "fake_cec_service_client.h", "fake_cicerone_client.cc", @@ -284,6 +284,7 @@ "//third_party/icu", ] sources = [ + "auth_policy/fake_auth_policy_client_unittest.cc", "biod/biod_client_unittest.cc", "biod/fake_biod_client_unittest.cc", "blocking_method_caller_unittest.cc", @@ -292,7 +293,6 @@ "cros_disks_client_unittest.cc", "cryptohome/fake_cryptohome_client_unittest.cc", "dbus_thread_manager_unittest.cc", - "fake_auth_policy_client_unittest.cc", "fake_easy_unlock_client_unittest.cc", "gsm_sms_client_unittest.cc", "modem_messaging_client_unittest.cc",
diff --git a/chromeos/dbus/OWNERS b/chromeos/dbus/OWNERS index 97637bf0..da7080c 100644 --- a/chromeos/dbus/OWNERS +++ b/chromeos/dbus/OWNERS
@@ -4,8 +4,6 @@ per-file *audio*=jennyz@chromium.org per-file *audio*=hychao@chromium.org -per-file *auth_policy*=rsorokin@chromium.org -per-file *auth_policy*=tnagel@chromium.org per-file *cryptohome*=dkrahn@chromium.org per-file *diagnosticsd*=emaxx@chromium.org per-file *diagnosticsd*=pmarko@chromium.org
diff --git a/chromeos/dbus/auth_policy/OWNERS b/chromeos/dbus/auth_policy/OWNERS new file mode 100644 index 0000000..fa56222 --- /dev/null +++ b/chromeos/dbus/auth_policy/OWNERS
@@ -0,0 +1,2 @@ +rsorokin@chromium.org +tnagel@chromium.org
diff --git a/chromeos/dbus/auth_policy_client.cc b/chromeos/dbus/auth_policy/auth_policy_client.cc similarity index 99% rename from chromeos/dbus/auth_policy_client.cc rename to chromeos/dbus/auth_policy/auth_policy_client.cc index cd268ac5..6656d78 100644 --- a/chromeos/dbus/auth_policy_client.cc +++ b/chromeos/dbus/auth_policy/auth_policy_client.cc
@@ -1,7 +1,7 @@ // Copyright 2016 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/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include <utility>
diff --git a/chromeos/dbus/auth_policy_client.h b/chromeos/dbus/auth_policy/auth_policy_client.h similarity index 95% rename from chromeos/dbus/auth_policy_client.h rename to chromeos/dbus/auth_policy/auth_policy_client.h index 8bdfed6..1b4f94b 100644 --- a/chromeos/dbus/auth_policy_client.h +++ b/chromeos/dbus/auth_policy/auth_policy_client.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 CHROMEOS_DBUS_AUTH_POLICY_CLIENT_H_ -#define CHROMEOS_DBUS_AUTH_POLICY_CLIENT_H_ +#ifndef CHROMEOS_DBUS_AUTH_POLICY_AUTH_POLICY_CLIENT_H_ +#define CHROMEOS_DBUS_AUTH_POLICY_AUTH_POLICY_CLIENT_H_ #include <string> @@ -100,4 +100,4 @@ } // namespace chromeos -#endif // CHROMEOS_DBUS_AUTH_POLICY_CLIENT_H_ +#endif // CHROMEOS_DBUS_AUTH_POLICY_AUTH_POLICY_CLIENT_H_
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/auth_policy/fake_auth_policy_client.cc similarity index 99% rename from chromeos/dbus/fake_auth_policy_client.cc rename to chromeos/dbus/auth_policy/fake_auth_policy_client.cc index 2b000da..8554c19 100644 --- a/chromeos/dbus/fake_auth_policy_client.cc +++ b/chromeos/dbus/auth_policy/fake_auth_policy_client.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 "chromeos/dbus/fake_auth_policy_client.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include <memory> #include <vector>
diff --git a/chromeos/dbus/fake_auth_policy_client.h b/chromeos/dbus/auth_policy/fake_auth_policy_client.h similarity index 95% rename from chromeos/dbus/fake_auth_policy_client.h rename to chromeos/dbus/auth_policy/fake_auth_policy_client.h index 882c440..f23fb6a2 100644 --- a/chromeos/dbus/fake_auth_policy_client.h +++ b/chromeos/dbus/auth_policy/fake_auth_policy_client.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 CHROMEOS_DBUS_FAKE_AUTH_POLICY_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_AUTH_POLICY_CLIENT_H_ +#ifndef CHROMEOS_DBUS_AUTH_POLICY_FAKE_AUTH_POLICY_CLIENT_H_ +#define CHROMEOS_DBUS_AUTH_POLICY_FAKE_AUTH_POLICY_CLIENT_H_ #include <set> #include <string> @@ -13,7 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" @@ -177,4 +177,4 @@ } // namespace chromeos -#endif // CHROMEOS_DBUS_FAKE_AUTH_POLICY_CLIENT_H_ +#endif // CHROMEOS_DBUS_AUTH_POLICY_FAKE_AUTH_POLICY_CLIENT_H_
diff --git a/chromeos/dbus/fake_auth_policy_client_unittest.cc b/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc similarity index 98% rename from chromeos/dbus/fake_auth_policy_client_unittest.cc rename to chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.cc index 550857e0..6d8dab7e 100644 --- a/chromeos/dbus/fake_auth_policy_client_unittest.cc +++ b/chromeos/dbus/auth_policy/fake_auth_policy_client_unittest.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 "chromeos/dbus/fake_auth_policy_client.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" @@ -102,7 +102,7 @@ int service_is_available_called_num_ = 0; private: - FakeAuthPolicyClient* auth_policy_client_ptr_; // not owned. + FakeAuthPolicyClient* auth_policy_client_ptr_; // not owned. FakeSessionManagerClient* session_manager_client_ptr_; // not owned. base::MessageLoop loop_;
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc index a4f12e43..5e4f4170 100644 --- a/chromeos/dbus/dbus_clients_browser.cc +++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -9,7 +9,8 @@ #include "chromeos/dbus/arc_midis_client.h" #include "chromeos/dbus/arc_obb_mounter_client.h" #include "chromeos/dbus/arc_oemcrypto_client.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/cec_service_client.h" #include "chromeos/dbus/cicerone_client.h" #include "chromeos/dbus/concierge_client.h" @@ -23,7 +24,6 @@ #include "chromeos/dbus/fake_arc_midis_client.h" #include "chromeos/dbus/fake_arc_obb_mounter_client.h" #include "chromeos/dbus/fake_arc_oemcrypto_client.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/fake_cicerone_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "chromeos/dbus/fake_debug_daemon_client.h"
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index fecfa157..946f48ee9 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -14,7 +14,7 @@ #include "chromeos/dbus/arc_midis_client.h" #include "chromeos/dbus/arc_obb_mounter_client.h" #include "chromeos/dbus/arc_oemcrypto_client.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/cec_service_client.h" #include "chromeos/dbus/cicerone_client.h" #include "chromeos/dbus/concierge_client.h"
diff --git a/chromeos/dbus/upstart/fake_upstart_client.cc b/chromeos/dbus/upstart/fake_upstart_client.cc index 43bebce..1672e4d 100644 --- a/chromeos/dbus/upstart/fake_upstart_client.cc +++ b/chromeos/dbus/upstart/fake_upstart_client.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "chromeos/dbus/fake_media_analytics_client.h" namespace chromeos {
diff --git a/chromeos/login/auth/authpolicy_login_helper.cc b/chromeos/login/auth/authpolicy_login_helper.cc index f577b6e..864a8e7 100644 --- a/chromeos/login/auth/authpolicy_login_helper.cc +++ b/chromeos/login/auth/authpolicy_login_helper.cc
@@ -10,7 +10,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/task/post_task.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/upstart/upstart_client.h" #include "chromeos/dbus/util/tpm_util.h"
diff --git a/chromeos/login/auth/authpolicy_login_helper.h b/chromeos/login/auth/authpolicy_login_helper.h index c04716e..4c5134e0 100644 --- a/chromeos/login/auth/authpolicy_login_helper.h +++ b/chromeos/login/auth/authpolicy_login_helper.h
@@ -12,7 +12,7 @@ #include "base/files/scoped_file.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "chromeos/dbus/auth_policy_client.h" +#include "chromeos/dbus/auth_policy/auth_policy_client.h" namespace chromeos {
diff --git a/chromeos/login/auth/authpolicy_login_helper_unittest.cc b/chromeos/login/auth/authpolicy_login_helper_unittest.cc index 7e2503fd..56d53f58 100644 --- a/chromeos/login/auth/authpolicy_login_helper_unittest.cc +++ b/chromeos/login/auth/authpolicy_login_helper_unittest.cc
@@ -5,9 +5,9 @@ #include "chromeos/login/auth/authpolicy_login_helper.h" #include "base/bind.h" +#include "chromeos/dbus/auth_policy/fake_auth_policy_client.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_auth_policy_client.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos {
diff --git a/chromeos/network/OWNERS b/chromeos/network/OWNERS index aa215c7..9288b61f 100644 --- a/chromeos/network/OWNERS +++ b/chromeos/network/OWNERS
@@ -1 +1,3 @@ +khorimoto@chromium.org stevenjb@chromium.org +tbarzic@chromium.org \ No newline at end of file
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index 626546ac..ecfee773 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -206,14 +206,14 @@ // Register handler for media actions. assistant_manager_internal_->RegisterFallbackMediaHandler( - [this](std::string play_media_args_proto) { + [this](std::string action_name, std::string media_action_args_proto) { std::unique_ptr<action::AndroidAppInfo> android_app_info = - GetAndroidAppInfoFromMediaArgs(play_media_args_proto); + GetAndroidAppInfoFromMediaArgs(media_action_args_proto); if (android_app_info) { - OnOpenMediaAndroidIntent(play_media_args_proto, + OnOpenMediaAndroidIntent(media_action_args_proto, android_app_info.get()); } else { - std::string url = GetWebUrlFromMediaArgs(play_media_args_proto); + std::string url = GetWebUrlFromMediaArgs(media_action_args_proto); // Fallack to web URL. if (!url.empty()) OnOpenUrl(url);
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index ac0dbe0..bdf63ad 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -100,6 +100,7 @@ "//base", "//chromeos/components/multidevice", "//chromeos/components/multidevice/logging", + "//chromeos/constants:constants", "//chromeos/network", "//chromeos/services/device_sync/proto:util", "//chromeos/services/device_sync/public/cpp", @@ -198,6 +199,7 @@ "//base/test:test_support", "//chromeos/components/multidevice", "//chromeos/components/multidevice:test_support", + "//chromeos/constants:constants", "//chromeos/dbus:test_support", "//chromeos/network", "//chromeos/network:test_support",
diff --git a/chromeos/services/device_sync/device_sync_impl.cc b/chromeos/services/device_sync/device_sync_impl.cc index a941993..177b5f4 100644 --- a/chromeos/services/device_sync/device_sync_impl.cc +++ b/chromeos/services/device_sync/device_sync_impl.cc
@@ -5,6 +5,7 @@ #include "chromeos/services/device_sync/device_sync_impl.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" @@ -12,12 +13,16 @@ #include "base/time/default_clock.h" #include "chromeos/components/multidevice/logging/logging.h" #include "chromeos/components/multidevice/secure_message_delegate_impl.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/services/device_sync/cryptauth_client_impl.h" #include "chromeos/services/device_sync/cryptauth_device_manager_impl.h" #include "chromeos/services/device_sync/cryptauth_enroller_factory_impl.h" #include "chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h" #include "chromeos/services/device_sync/cryptauth_gcm_manager_impl.h" +#include "chromeos/services/device_sync/cryptauth_key_registry_impl.h" +#include "chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h" #include "chromeos/services/device_sync/device_sync_type_converters.h" +#include "chromeos/services/device_sync/persistent_enrollment_scheduler.h" #include "chromeos/services/device_sync/proto/cryptauth_api.pb.h" #include "chromeos/services/device_sync/proto/device_classifier_util.h" #include "chromeos/services/device_sync/public/cpp/gcm_device_info_provider.h" @@ -38,7 +43,14 @@ void RegisterDeviceSyncPrefs(PrefRegistrySimple* registry) { CryptAuthGCMManager::RegisterPrefs(registry); CryptAuthDeviceManager::RegisterPrefs(registry); - CryptAuthEnrollmentManagerImpl::RegisterPrefs(registry); + if (base::FeatureList::IsEnabled( + chromeos::features::kCryptAuthV2Enrollment)) { + CryptAuthV2EnrollmentManagerImpl::RegisterPrefs(registry); + CryptAuthKeyRegistryImpl::RegisterPrefs(registry); + PersistentEnrollmentScheduler::RegisterPrefs(registry); + } else { + CryptAuthEnrollmentManagerImpl::RegisterPrefs(registry); + } } constexpr base::TimeDelta kSetFeatureEnabledTimeout = @@ -209,11 +221,13 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<base::OneShotTimer> timer) { return base::WrapUnique(new DeviceSyncImpl( identity_manager, gcm_driver, connector, gcm_device_info_provider, - std::move(url_loader_factory), base::DefaultClock::GetInstance(), + client_app_metadata_provider, std::move(url_loader_factory), + base::DefaultClock::GetInstance(), std::make_unique<PrefConnectionDelegate>(), std::move(timer))); } @@ -290,6 +304,7 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::Clock* clock, std::unique_ptr<PrefConnectionDelegate> pref_connection_delegate, @@ -299,6 +314,7 @@ gcm_driver_(gcm_driver), connector_(connector), gcm_device_info_provider_(gcm_device_info_provider), + client_app_metadata_provider_(client_app_metadata_provider), url_loader_factory_(std::move(url_loader_factory)), clock_(clock), pref_connection_delegate_(std::move(pref_connection_delegate)), @@ -491,6 +507,7 @@ remote_device_provider_.reset(); cryptauth_device_manager_.reset(); cryptauth_enrollment_manager_.reset(); + cryptauth_key_registry_.reset(); cryptauth_client_factory_.reset(); cryptauth_gcm_manager_.reset(); pref_connection_delegate_.reset(); @@ -499,6 +516,7 @@ gcm_driver_ = nullptr; connector_ = nullptr; gcm_device_info_provider_ = nullptr; + client_app_metadata_provider_ = nullptr; url_loader_factory_ = nullptr; clock_ = nullptr; } @@ -574,14 +592,28 @@ // Initialize |cryptauth_enrollment_manager_| and start observing, then call // Start() immediately to schedule enrollment. - cryptauth_enrollment_manager_ = - CryptAuthEnrollmentManagerImpl::Factory::NewInstance( - clock_, - std::make_unique<CryptAuthEnrollerFactoryImpl>( - cryptauth_client_factory_.get()), - multidevice::SecureMessageDelegateImpl::Factory::NewInstance(), - gcm_device_info_provider_->GetGcmDeviceInfo(), - cryptauth_gcm_manager_.get(), pref_service_.get()); + if (base::FeatureList::IsEnabled( + chromeos::features::kCryptAuthV2Enrollment)) { + cryptauth_key_registry_ = + CryptAuthKeyRegistryImpl::Factory::Get()->BuildInstance( + pref_service_.get()); + + cryptauth_enrollment_manager_ = + CryptAuthV2EnrollmentManagerImpl::Factory::Get()->BuildInstance( + client_app_metadata_provider_, cryptauth_key_registry_.get(), + cryptauth_client_factory_.get(), cryptauth_gcm_manager_.get(), + pref_service_.get(), clock_); + } else { + cryptauth_enrollment_manager_ = + CryptAuthEnrollmentManagerImpl::Factory::NewInstance( + clock_, + std::make_unique<CryptAuthEnrollerFactoryImpl>( + cryptauth_client_factory_.get()), + multidevice::SecureMessageDelegateImpl::Factory::NewInstance(), + gcm_device_info_provider_->GetGcmDeviceInfo(), + cryptauth_gcm_manager_.get(), pref_service_.get()); + } + cryptauth_enrollment_manager_->AddObserver(this); cryptauth_enrollment_manager_->Start(); }
diff --git a/chromeos/services/device_sync/device_sync_impl.h b/chromeos/services/device_sync/device_sync_impl.h index f3c5544a..a7ed351 100644 --- a/chromeos/services/device_sync/device_sync_impl.h +++ b/chromeos/services/device_sync/device_sync_impl.h
@@ -47,8 +47,10 @@ namespace device_sync { +class ClientAppMetadataProvider; class CryptAuthClientFactory; class CryptAuthDeviceManager; +class CryptAuthKeyRegistry; class GcmDeviceInfoProvider; class SoftwareFeatureManager; @@ -77,6 +79,7 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<base::OneShotTimer> timer); @@ -167,6 +170,7 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::Clock* clock, std::unique_ptr<PrefConnectionDelegate> pref_connection_delegate, @@ -211,6 +215,7 @@ gcm::GCMDriver* gcm_driver_; service_manager::Connector* connector_; const GcmDeviceInfoProvider* gcm_device_info_provider_; + ClientAppMetadataProvider* client_app_metadata_provider_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; base::Clock* clock_; std::unique_ptr<PrefConnectionDelegate> pref_connection_delegate_; @@ -225,6 +230,10 @@ std::unique_ptr<CryptAuthGCMManager> cryptauth_gcm_manager_; std::unique_ptr<CryptAuthClientFactory> cryptauth_client_factory_; + + // Only created and used if v2 Enrollment is enabled; null otherwise. + std::unique_ptr<CryptAuthKeyRegistry> cryptauth_key_registry_; + std::unique_ptr<CryptAuthEnrollmentManager> cryptauth_enrollment_manager_; std::unique_ptr<CryptAuthDeviceManager> cryptauth_device_manager_; std::unique_ptr<RemoteDeviceProvider> remote_device_provider_;
diff --git a/chromeos/services/device_sync/device_sync_service.cc b/chromeos/services/device_sync/device_sync_service.cc index f9ed52a..6b1c9bde 100644 --- a/chromeos/services/device_sync/device_sync_service.cc +++ b/chromeos/services/device_sync/device_sync_service.cc
@@ -19,12 +19,14 @@ identity::IdentityManager* identity_manager, gcm::GCMDriver* gcm_driver, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, service_manager::mojom::ServiceRequest request) : service_binding_(this, std::move(request)), identity_manager_(identity_manager), gcm_driver_(gcm_driver), gcm_device_info_provider_(gcm_device_info_provider), + client_app_metadata_provider_(client_app_metadata_provider), url_loader_factory_(std::move(url_loader_factory)) {} DeviceSyncService::~DeviceSyncService() { @@ -40,8 +42,8 @@ device_sync_ = DeviceSyncImpl::Factory::Get()->BuildInstance( identity_manager_, gcm_driver_, service_binding_.GetConnector(), - gcm_device_info_provider_, url_loader_factory_, - std::make_unique<base::OneShotTimer>()); + gcm_device_info_provider_, client_app_metadata_provider_, + url_loader_factory_, std::make_unique<base::OneShotTimer>()); registry_.AddInterface(base::Bind(&DeviceSyncBase::BindRequest, base::Unretained(device_sync_.get())));
diff --git a/chromeos/services/device_sync/device_sync_service.h b/chromeos/services/device_sync/device_sync_service.h index 8d834ee..9fae89d 100644 --- a/chromeos/services/device_sync/device_sync_service.h +++ b/chromeos/services/device_sync/device_sync_service.h
@@ -29,6 +29,7 @@ namespace device_sync { +class ClientAppMetadataProvider; class DeviceSyncBase; class GcmDeviceInfoProvider; @@ -40,6 +41,7 @@ identity::IdentityManager* identity_manager, gcm::GCMDriver* gcm_driver, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, service_manager::mojom::ServiceRequest request); ~DeviceSyncService() override; @@ -56,6 +58,7 @@ identity::IdentityManager* identity_manager_; gcm::GCMDriver* gcm_driver_; const GcmDeviceInfoProvider* gcm_device_info_provider_; + ClientAppMetadataProvider* client_app_metadata_provider_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; std::unique_ptr<DeviceSyncBase> device_sync_;
diff --git a/chromeos/services/device_sync/device_sync_service_unittest.cc b/chromeos/services/device_sync/device_sync_service_unittest.cc index 4702592d..30a2003 100644 --- a/chromeos/services/device_sync/device_sync_service_unittest.cc +++ b/chromeos/services/device_sync/device_sync_service_unittest.cc
@@ -12,14 +12,18 @@ #include "base/single_thread_task_runner.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/null_task_runner.h" +#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "base/timer/mock_timer.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/services/device_sync/cryptauth_device_manager_impl.h" #include "chromeos/services/device_sync/cryptauth_enrollment_manager_impl.h" #include "chromeos/services/device_sync/cryptauth_gcm_manager_impl.h" +#include "chromeos/services/device_sync/cryptauth_key_registry_impl.h" +#include "chromeos/services/device_sync/cryptauth_v2_enrollment_manager_impl.h" #include "chromeos/services/device_sync/device_sync_impl.h" #include "chromeos/services/device_sync/device_sync_service.h" #include "chromeos/services/device_sync/fake_cryptauth_device_manager.h" @@ -28,6 +32,7 @@ #include "chromeos/services/device_sync/fake_device_sync_observer.h" #include "chromeos/services/device_sync/fake_remote_device_provider.h" #include "chromeos/services/device_sync/fake_software_feature_manager.h" +#include "chromeos/services/device_sync/public/cpp/fake_client_app_metadata_provider.h" #include "chromeos/services/device_sync/public/cpp/fake_gcm_device_info_provider.h" #include "chromeos/services/device_sync/public/mojom/constants.mojom.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" @@ -257,6 +262,107 @@ FakeCryptAuthEnrollmentManager* instance_ = nullptr; }; +class FakeCryptAuthKeyRegistry : public CryptAuthKeyRegistry { + public: + FakeCryptAuthKeyRegistry() = default; + ~FakeCryptAuthKeyRegistry() override = default; + + private: + // CryptAuthKeyRegistry: + void OnKeyRegistryUpdated() override {} +}; + +class FakeCryptAuthKeyRegistryFactory + : public CryptAuthKeyRegistryImpl::Factory { + public: + explicit FakeCryptAuthKeyRegistryFactory( + TestingPrefServiceSimple* test_pref_service) + : test_pref_service_(test_pref_service) {} + + ~FakeCryptAuthKeyRegistryFactory() override = default; + + FakeCryptAuthKeyRegistry* instance() { return instance_; } + + private: + // CryptAuthKeyRegistryImpl::Factory: + std::unique_ptr<CryptAuthKeyRegistry> BuildInstance( + PrefService* pref_service) override { + EXPECT_EQ(test_pref_service_, pref_service); + + // Only one instance is expected to be created per test. + EXPECT_FALSE(instance_); + auto instance = std::make_unique<FakeCryptAuthKeyRegistry>(); + instance_ = instance.get(); + return std::move(instance); + } + + TestingPrefServiceSimple* test_pref_service_; + FakeCryptAuthKeyRegistry* instance_ = nullptr; +}; + +class FakeCryptAuthV2EnrollmentManagerFactory + : public CryptAuthV2EnrollmentManagerImpl::Factory { + public: + FakeCryptAuthV2EnrollmentManagerFactory( + FakeClientAppMetadataProvider* fake_client_app_metadata_provider, + FakeCryptAuthKeyRegistryFactory* fake_cryptauth_key_registry_factory, + FakeCryptAuthGCMManagerFactory* fake_cryptauth_gcm_manager_factory, + TestingPrefServiceSimple* test_pref_service, + base::SimpleTestClock* simple_test_clock) + : fake_client_app_metadata_provider_(fake_client_app_metadata_provider), + fake_cryptauth_key_registry_factory_( + fake_cryptauth_key_registry_factory), + fake_cryptauth_gcm_manager_factory_(fake_cryptauth_gcm_manager_factory), + test_pref_service_(test_pref_service), + simple_test_clock_(simple_test_clock) {} + + ~FakeCryptAuthV2EnrollmentManagerFactory() override = default; + + void set_device_already_enrolled_in_cryptauth( + bool device_already_enrolled_in_cryptauth) { + device_already_enrolled_in_cryptauth_ = + device_already_enrolled_in_cryptauth; + } + + FakeCryptAuthEnrollmentManager* instance() { return instance_; } + + // CryptAuthV2EnrollmentManagerImpl::Factory: + std::unique_ptr<CryptAuthEnrollmentManager> BuildInstance( + ClientAppMetadataProvider* client_app_metadata_provider, + CryptAuthKeyRegistry* key_registry, + CryptAuthClientFactory* client_factory, + CryptAuthGCMManager* gcm_manager, + PrefService* pref_service, + base::Clock* clock, + std::unique_ptr<base::OneShotTimer> timer) override { + EXPECT_EQ(fake_client_app_metadata_provider_, client_app_metadata_provider); + EXPECT_EQ(fake_cryptauth_key_registry_factory_->instance(), key_registry); + EXPECT_EQ(fake_cryptauth_gcm_manager_factory_->instance(), gcm_manager); + EXPECT_EQ(test_pref_service_, pref_service); + EXPECT_EQ(simple_test_clock_, clock); + + // Only one instance is expected to be created per test. + EXPECT_FALSE(instance_); + + auto instance = std::make_unique<FakeCryptAuthEnrollmentManager>(); + instance->set_user_public_key(kLocalDevicePublicKey); + instance->set_is_enrollment_valid(device_already_enrolled_in_cryptauth_); + instance_ = instance.get(); + + return std::move(instance); + } + + private: + FakeClientAppMetadataProvider* fake_client_app_metadata_provider_; + FakeCryptAuthKeyRegistryFactory* fake_cryptauth_key_registry_factory_; + FakeCryptAuthGCMManagerFactory* fake_cryptauth_gcm_manager_factory_; + TestingPrefServiceSimple* test_pref_service_; + base::SimpleTestClock* simple_test_clock_; + + bool device_already_enrolled_in_cryptauth_ = false; + FakeCryptAuthEnrollmentManager* instance_ = nullptr; +}; + class FakeRemoteDeviceProviderFactory : public RemoteDeviceProviderImpl::Factory { public: @@ -265,13 +371,17 @@ identity::IdentityManager* identity_manager, FakeCryptAuthDeviceManagerFactory* fake_cryptauth_device_manager_factory, FakeCryptAuthEnrollmentManagerFactory* - fake_cryptauth_enrollment_manager_factory) + fake_cryptauth_enrollment_manager_factory, + FakeCryptAuthV2EnrollmentManagerFactory* + fake_cryptauth_v2_enrollment_manager_factory) : initial_devices_(initial_devices), identity_manager_(identity_manager), fake_cryptauth_device_manager_factory_( fake_cryptauth_device_manager_factory), fake_cryptauth_enrollment_manager_factory_( - fake_cryptauth_enrollment_manager_factory) {} + fake_cryptauth_enrollment_manager_factory), + fake_cryptauth_v2_enrollment_manager_factory_( + fake_cryptauth_v2_enrollment_manager_factory) {} ~FakeRemoteDeviceProviderFactory() override = default; @@ -285,9 +395,18 @@ EXPECT_EQ(fake_cryptauth_device_manager_factory_->instance(), device_manager); EXPECT_EQ(identity_manager_->GetPrimaryAccountId(), user_id); - EXPECT_EQ(fake_cryptauth_enrollment_manager_factory_->instance() - ->GetUserPrivateKey(), - user_private_key); + if (fake_cryptauth_enrollment_manager_factory_) { + EXPECT_EQ(fake_cryptauth_enrollment_manager_factory_->instance() + ->GetUserPrivateKey(), + user_private_key); + EXPECT_FALSE(fake_cryptauth_v2_enrollment_manager_factory_); + } + if (fake_cryptauth_v2_enrollment_manager_factory_) { + EXPECT_EQ(fake_cryptauth_v2_enrollment_manager_factory_->instance() + ->GetUserPrivateKey(), + user_private_key); + EXPECT_FALSE(fake_cryptauth_enrollment_manager_factory_); + } // Only one instance is expected to be created per test. EXPECT_FALSE(instance_); @@ -306,6 +425,8 @@ FakeCryptAuthDeviceManagerFactory* fake_cryptauth_device_manager_factory_; FakeCryptAuthEnrollmentManagerFactory* fake_cryptauth_enrollment_manager_factory_; + FakeCryptAuthV2EnrollmentManagerFactory* + fake_cryptauth_v2_enrollment_manager_factory_; FakeRemoteDeviceProvider* instance_ = nullptr; }; @@ -336,7 +457,7 @@ } // namespace -class DeviceSyncServiceTest : public testing::Test { +class DeviceSyncServiceTest : public ::testing::TestWithParam<bool> { public: class FakePrefConnectionDelegate : public DeviceSyncImpl::PrefConnectionDelegate { @@ -404,12 +525,14 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<base::OneShotTimer> timer) override { return base::WrapUnique(new DeviceSyncImpl( identity_manager, gcm_driver, connector, gcm_device_info_provider, - std::move(url_loader_factory), simple_test_clock_, - std::move(fake_pref_connection_delegate_), std::move(mock_timer_))); + client_app_metadata_provider, std::move(url_loader_factory), + simple_test_clock_, std::move(fake_pref_connection_delegate_), + std::move(mock_timer_))); } private: @@ -426,6 +549,12 @@ ~DeviceSyncServiceTest() override = default; void SetUp() override { + // Choose between v1 and v2 Enrollment infrastructure based on the parameter + // provided by ::testing::TestWithParam<bool>. + use_v2_enrollment_ = GetParam(); + scoped_feature_list_.InitWithFeatureState( + chromeos::features::kCryptAuthV2Enrollment, use_v2_enrollment_); + DBusThreadManager::Initialize(); fake_gcm_driver_ = std::make_unique<gcm::FakeGCMDriver>(); @@ -455,18 +584,38 @@ CryptAuthDeviceManagerImpl::Factory::SetInstanceForTesting( fake_cryptauth_device_manager_factory_.get()); - fake_cryptauth_enrollment_manager_factory_ = - std::make_unique<FakeCryptAuthEnrollmentManagerFactory>( - simple_test_clock_.get(), fake_cryptauth_gcm_manager_factory_.get(), - test_pref_service_); - CryptAuthEnrollmentManagerImpl::Factory::SetInstanceForTesting( - fake_cryptauth_enrollment_manager_factory_.get()); + if (use_v2_enrollment_) { + fake_client_app_metadata_provider_ = + std::make_unique<FakeClientAppMetadataProvider>(); + + fake_cryptauth_key_registry_factory_ = + std::make_unique<FakeCryptAuthKeyRegistryFactory>(test_pref_service_); + CryptAuthKeyRegistryImpl::Factory::SetFactoryForTesting( + fake_cryptauth_key_registry_factory_.get()); + + fake_cryptauth_v2_enrollment_manager_factory_ = + std::make_unique<FakeCryptAuthV2EnrollmentManagerFactory>( + fake_client_app_metadata_provider_.get(), + fake_cryptauth_key_registry_factory_.get(), + fake_cryptauth_gcm_manager_factory_.get(), test_pref_service_, + simple_test_clock_.get()); + CryptAuthV2EnrollmentManagerImpl::Factory::SetFactoryForTesting( + fake_cryptauth_v2_enrollment_manager_factory_.get()); + } else { + fake_cryptauth_enrollment_manager_factory_ = + std::make_unique<FakeCryptAuthEnrollmentManagerFactory>( + simple_test_clock_.get(), + fake_cryptauth_gcm_manager_factory_.get(), test_pref_service_); + CryptAuthEnrollmentManagerImpl::Factory::SetInstanceForTesting( + fake_cryptauth_enrollment_manager_factory_.get()); + } fake_remote_device_provider_factory_ = std::make_unique<FakeRemoteDeviceProviderFactory>( test_devices_, identity_test_environment_->identity_manager(), fake_cryptauth_device_manager_factory_.get(), - fake_cryptauth_enrollment_manager_factory_.get()); + fake_cryptauth_enrollment_manager_factory_.get(), + fake_cryptauth_v2_enrollment_manager_factory_.get()); RemoteDeviceProviderImpl::Factory::SetInstanceForTesting( fake_remote_device_provider_factory_.get()); @@ -503,20 +652,38 @@ fake_device_sync_observer_ = std::make_unique<FakeDeviceSyncObserver>(); service_ = std::make_unique<DeviceSyncService>( identity_test_environment_->identity_manager(), fake_gcm_driver_.get(), - fake_gcm_device_info_provider_.get(), shared_url_loader_factory, + fake_gcm_device_info_provider_.get(), + fake_client_app_metadata_provider_.get(), shared_url_loader_factory, connector_factory_.RegisterInstance(mojom::kServiceName)); } - void TearDown() override { DBusThreadManager::Shutdown(); } + void TearDown() override { + CryptAuthGCMManagerImpl::Factory::SetInstanceForTesting(nullptr); + CryptAuthDeviceManagerImpl::Factory::SetInstanceForTesting(nullptr); + CryptAuthKeyRegistryImpl::Factory::SetFactoryForTesting(nullptr); + CryptAuthV2EnrollmentManagerImpl::Factory::SetFactoryForTesting(nullptr); + CryptAuthEnrollmentManagerImpl::Factory::SetInstanceForTesting(nullptr); + RemoteDeviceProviderImpl::Factory::SetInstanceForTesting(nullptr); + SoftwareFeatureManagerImpl::Factory::SetInstanceForTesting(nullptr); + DeviceSyncImpl::Factory::SetInstanceForTesting(nullptr); + + DBusThreadManager::Shutdown(); + } void ConnectToDeviceSyncService(bool device_already_enrolled_in_cryptauth) { // Used in CompleteConnectionToPrefService(). device_already_enrolled_in_cryptauth_ = device_already_enrolled_in_cryptauth; - fake_cryptauth_enrollment_manager_factory_ - ->set_device_already_enrolled_in_cryptauth( - device_already_enrolled_in_cryptauth); + if (use_v2_enrollment_) { + fake_cryptauth_v2_enrollment_manager_factory_ + ->set_device_already_enrolled_in_cryptauth( + device_already_enrolled_in_cryptauth); + } else { + fake_cryptauth_enrollment_manager_factory_ + ->set_device_already_enrolled_in_cryptauth( + device_already_enrolled_in_cryptauth); + } connector_factory_.GetDefaultConnector()->BindInterface(mojom::kServiceName, &device_sync_); @@ -536,8 +703,7 @@ // expected to be created and initialized. EXPECT_TRUE(fake_cryptauth_gcm_manager_factory_->instance() ->has_started_listening()); - EXPECT_TRUE( - fake_cryptauth_enrollment_manager_factory_->instance()->has_started()); + EXPECT_TRUE(fake_cryptauth_enrollment_manager()->has_started()); // If the device was already enrolled in CryptAuth, initialization should // now be complete; otherwise, enrollment needs to finish before @@ -566,7 +732,7 @@ // yet in progress before this call, it is started before it is completed. void SimulateEnrollment(bool success) { FakeCryptAuthEnrollmentManager* enrollment_manager = - fake_cryptauth_enrollment_manager_factory_->instance(); + fake_cryptauth_enrollment_manager(); bool had_valid_enrollment_before_call = enrollment_manager->IsEnrollmentValid(); @@ -647,7 +813,9 @@ base::MockOneShotTimer* mock_timer() { return mock_timer_; } FakeCryptAuthEnrollmentManager* fake_cryptauth_enrollment_manager() { - return fake_cryptauth_enrollment_manager_factory_->instance(); + return use_v2_enrollment_ + ? fake_cryptauth_v2_enrollment_manager_factory_->instance() + : fake_cryptauth_enrollment_manager_factory_->instance(); } FakeCryptAuthDeviceManager* fake_cryptauth_device_manager() { @@ -721,10 +889,9 @@ base::Unretained(this), run_loop.QuitClosure())); run_loop.Run(); - if (fake_cryptauth_enrollment_manager_factory_->instance()) { + if (fake_cryptauth_enrollment_manager()) { EXPECT_EQ(last_force_enrollment_now_result_, - fake_cryptauth_enrollment_manager_factory_->instance() - ->IsEnrollmentInProgress()); + fake_cryptauth_enrollment_manager()->IsEnrollmentInProgress()); } return last_force_enrollment_now_result_; @@ -930,6 +1097,12 @@ fake_cryptauth_device_manager_factory_; std::unique_ptr<FakeCryptAuthEnrollmentManagerFactory> fake_cryptauth_enrollment_manager_factory_; + std::unique_ptr<FakeClientAppMetadataProvider> + fake_client_app_metadata_provider_; + std::unique_ptr<FakeCryptAuthKeyRegistryFactory> + fake_cryptauth_key_registry_factory_; + std::unique_ptr<FakeCryptAuthV2EnrollmentManagerFactory> + fake_cryptauth_v2_enrollment_manager_factory_; std::unique_ptr<FakeRemoteDeviceProviderFactory> fake_remote_device_provider_factory_; std::unique_ptr<FakeSoftwareFeatureManagerFactory> @@ -959,10 +1132,13 @@ base::HistogramTester histogram_tester_; + bool use_v2_enrollment_; + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(DeviceSyncServiceTest); }; -TEST_F(DeviceSyncServiceTest, PreferencesNeverConnect) { +TEST_P(DeviceSyncServiceTest, PreferencesNeverConnect) { ConnectToDeviceSyncService(false /* device_already_enrolled_in_cryptauth */); // A connection to the Preferences service should have started. @@ -979,7 +1155,7 @@ EXPECT_EQ(0u, fake_device_sync_observer()->num_sync_events()); } -TEST_F(DeviceSyncServiceTest, +TEST_P(DeviceSyncServiceTest, DeviceNotAlreadyEnrolledInCryptAuth_FailsEnrollment) { ConnectToDeviceSyncService(false /* device_already_enrolled_in_cryptauth */); CompleteConnectionToPrefService(); @@ -1001,7 +1177,7 @@ EXPECT_EQ(0u, fake_device_sync_observer()->num_sync_events()); } -TEST_F(DeviceSyncServiceTest, +TEST_P(DeviceSyncServiceTest, DeviceNotAlreadyEnrolledInCryptAuth_FailsEnrollment_ThenSucceeds) { ConnectToDeviceSyncService(false /* device_already_enrolled_in_cryptauth */); CompleteConnectionToPrefService(); @@ -1031,7 +1207,7 @@ EXPECT_EQ(test_devices(), CallGetSyncedDevices()); } -TEST_F(DeviceSyncServiceTest, +TEST_P(DeviceSyncServiceTest, DeviceAlreadyEnrolledInCryptAuth_InitializationFlow) { InitializeServiceSuccessfully(); @@ -1042,7 +1218,7 @@ EXPECT_EQ(test_devices(), CallGetSyncedDevices()); } -TEST_F(DeviceSyncServiceTest, EnrollAgainAfterInitialization) { +TEST_P(DeviceSyncServiceTest, EnrollAgainAfterInitialization) { InitializeServiceSuccessfully(); // Force an enrollment. @@ -1062,7 +1238,7 @@ EXPECT_EQ(1u, fake_device_sync_observer()->num_enrollment_events()); } -TEST_F(DeviceSyncServiceTest, GetLocalDeviceMetadata) { +TEST_P(DeviceSyncServiceTest, GetLocalDeviceMetadata) { InitializeServiceSuccessfully(); const auto& result = CallGetLocalDeviceMetadata(); @@ -1073,7 +1249,7 @@ EXPECT_EQ(test_devices()[0], *result); } -TEST_F(DeviceSyncServiceTest, SyncedDeviceUpdates) { +TEST_P(DeviceSyncServiceTest, SyncedDeviceUpdates) { InitializeServiceSuccessfully(); EXPECT_EQ(1u, fake_device_sync_observer()->num_sync_events()); @@ -1111,7 +1287,7 @@ EXPECT_EQ(updated_device_list, CallGetSyncedDevices()); } -TEST_F(DeviceSyncServiceTest, SetSoftwareFeatureState_Success) { +TEST_P(DeviceSyncServiceTest, SetSoftwareFeatureState_Success) { InitializeServiceSuccessfully(); const auto& set_software_calls = @@ -1168,7 +1344,7 @@ 0); } -TEST_F(DeviceSyncServiceTest, +TEST_P(DeviceSyncServiceTest, SetSoftwareFeatureState_RequestSucceedsButDoesNotTakeEffect) { InitializeServiceSuccessfully(); @@ -1217,7 +1393,7 @@ "MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Result", true, 0); } -TEST_F(DeviceSyncServiceTest, SetSoftwareFeatureState_Error) { +TEST_P(DeviceSyncServiceTest, SetSoftwareFeatureState_Error) { InitializeServiceSuccessfully(); const auto& set_software_calls = @@ -1262,7 +1438,7 @@ "MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Result", true, 0); } -TEST_F(DeviceSyncServiceTest, FindEligibleDevices) { +TEST_P(DeviceSyncServiceTest, FindEligibleDevices) { InitializeServiceSuccessfully(); const auto& find_eligible_calls = @@ -1329,7 +1505,7 @@ "MultiDevice.DeviceSyncService.FindEligibleDevices.Result", true, 1); } -TEST_F(DeviceSyncServiceTest, GetDebugInfo) { +TEST_P(DeviceSyncServiceTest, GetDebugInfo) { static const base::TimeDelta kTimeBetweenEpochAndLastEnrollment = base::TimeDelta::FromDays(365 * 50); // 50 years static const base::TimeDelta kTimeUntilNextEnrollment = @@ -1374,6 +1550,10 @@ EXPECT_FALSE(result->is_sync_in_progress); } +// Run all tests twice, first with v1 Enrollment infrastructure and then with v2 +// Enrollment infrastructure. +INSTANTIATE_TEST_SUITE_P(, DeviceSyncServiceTest, testing::Bool()); + } // namespace device_sync } // namespace chromeos
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc b/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc index 610b936..3909c72 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc
@@ -21,6 +21,7 @@ #include "chromeos/services/device_sync/device_sync_impl.h" #include "chromeos/services/device_sync/device_sync_service.h" #include "chromeos/services/device_sync/fake_device_sync.h" +#include "chromeos/services/device_sync/public/cpp/fake_client_app_metadata_provider.h" #include "chromeos/services/device_sync/public/cpp/fake_gcm_device_info_provider.h" #include "chromeos/services/device_sync/public/mojom/constants.mojom.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" @@ -64,6 +65,7 @@ gcm::GCMDriver* gcm_driver, service_manager::Connector* connector, const GcmDeviceInfoProvider* gcm_device_info_provider, + ClientAppMetadataProvider* client_app_metadata_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<base::OneShotTimer> timer) override { EXPECT_TRUE(fake_device_sync_); @@ -146,6 +148,8 @@ fake_gcm_driver_ = std::make_unique<gcm::FakeGCMDriver>(); fake_gcm_device_info_provider_ = std::make_unique<FakeGcmDeviceInfoProvider>(GetTestGcmDeviceInfo()); + fake_client_app_metadata_provider_ = + std::make_unique<FakeClientAppMetadataProvider>(); identity_test_environment_ = std::make_unique<identity::IdentityTestEnvironment>(); @@ -168,7 +172,8 @@ service_ = std::make_unique<DeviceSyncService>( identity_test_environment_->identity_manager(), fake_gcm_driver_.get(), - fake_gcm_device_info_provider_.get(), shared_url_loader_factory, + fake_gcm_device_info_provider_.get(), + fake_client_app_metadata_provider_.get(), shared_url_loader_factory, connector_factory_.RegisterInstance(mojom::kServiceName)); test_observer_ = std::make_unique<TestDeviceSyncClientObserver>(); @@ -421,6 +426,8 @@ std::unique_ptr<identity::IdentityTestEnvironment> identity_test_environment_; std::unique_ptr<gcm::FakeGCMDriver> fake_gcm_driver_; std::unique_ptr<FakeGcmDeviceInfoProvider> fake_gcm_device_info_provider_; + std::unique_ptr<FakeClientAppMetadataProvider> + fake_client_app_metadata_provider_; FakeDeviceSync* fake_device_sync_; std::unique_ptr<FakeDeviceSyncImplFactory> fake_device_sync_impl_factory_; service_manager::TestConnectorFactory connector_factory_;
diff --git a/chromeos/services/machine_learning/public/cpp/BUILD.gn b/chromeos/services/machine_learning/public/cpp/BUILD.gn index 0f053cc..ce9be93 100644 --- a/chromeos/services/machine_learning/public/cpp/BUILD.gn +++ b/chromeos/services/machine_learning/public/cpp/BUILD.gn
@@ -16,6 +16,20 @@ ] } +source_set("test_support") { + testonly = true + sources = [ + "fake_service_connection.cc", + "fake_service_connection.h", + ] + deps = [ + ":cpp", + "//base", + "//chromeos/services/machine_learning/public/mojom", + "//mojo/public/cpp/bindings", + ] +} + source_set("unit_tests") { testonly = true sources = [ @@ -23,6 +37,7 @@ ] deps = [ ":cpp", + ":test_support", "//base/test:test_support", "//chromeos/dbus:test_support", "//chromeos/services/machine_learning/public/mojom",
diff --git a/chromeos/services/machine_learning/public/cpp/fake_service_connection.cc b/chromeos/services/machine_learning/public/cpp/fake_service_connection.cc new file mode 100644 index 0000000..3d9ce55 --- /dev/null +++ b/chromeos/services/machine_learning/public/cpp/fake_service_connection.cc
@@ -0,0 +1,52 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h" + +#include <utility> + +namespace chromeos { +namespace machine_learning { + +FakeServiceConnectionImpl::FakeServiceConnectionImpl() + : execute_result_(mojom::Tensor::New()) {} + +FakeServiceConnectionImpl::~FakeServiceConnectionImpl() {} + +void FakeServiceConnectionImpl::LoadModel( + mojom::ModelSpecPtr spec, + mojom::ModelRequest request, + mojom::MachineLearningService::LoadModelCallback callback) { + model_bindings_.AddBinding(this, std::move(request)); + std::move(callback).Run(mojom::LoadModelResult::OK); +} + +void FakeServiceConnectionImpl::CreateGraphExecutor( + mojom::GraphExecutorRequest request, + mojom::Model::CreateGraphExecutorCallback callback) { + graph_bindings_.AddBinding(this, std::move(request)); + std::move(callback).Run(mojom::CreateGraphExecutorResult::OK); +} + +void FakeServiceConnectionImpl::Execute( + base::flat_map<std::string, mojom::TensorPtr> inputs, + const std::vector<std::string>& output_names, + mojom::GraphExecutor::ExecuteCallback callback) { + std::vector<mojom::TensorPtr> output_tensors; + output_tensors.push_back(execute_result_.Clone()); + std::move(callback).Run(mojom::ExecuteResult::OK, std::move(output_tensors)); +} + +void FakeServiceConnectionImpl::SetOutputValue( + const std::vector<int64_t>& shape, + const std::vector<double>& value) { + execute_result_->shape = mojom::Int64List::New(); + execute_result_->shape->value = shape; + execute_result_->data = mojom::ValueList::New(); + execute_result_->data->set_float_list(mojom::FloatList::New()); + execute_result_->data->get_float_list()->value = value; +} + +} // namespace machine_learning +} // namespace chromeos
diff --git a/chromeos/services/machine_learning/public/cpp/fake_service_connection.h b/chromeos/services/machine_learning/public/cpp/fake_service_connection.h new file mode 100644 index 0000000..df5b778 --- /dev/null +++ b/chromeos/services/machine_learning/public/cpp/fake_service_connection.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_ +#define CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "chromeos/services/machine_learning/public/cpp/service_connection.h" +#include "chromeos/services/machine_learning/public/mojom/graph_executor.mojom.h" +#include "chromeos/services/machine_learning/public/mojom/model.mojom.h" +#include "chromeos/services/machine_learning/public/mojom/tensor.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace chromeos { +namespace machine_learning { + +// Fake implementation of chromeos::machine_learning::ServiceConnection. +// Handles LoadModel (and Model::CreateGraphExecutor) by binding to itself. +// Handles GraphExecutor::Execute by always returning the value specified by +// a previous call to SetOutputValue. +// For use with ServiceConnection::UseFakeServiceConnectionForTesting(). +class FakeServiceConnectionImpl : public ServiceConnection, + public mojom::Model, + public mojom::GraphExecutor { + public: + FakeServiceConnectionImpl(); + ~FakeServiceConnectionImpl() override; + + // It's safe to execute LoadModel for multi times, but all the requests will + // be bound to the same instance. + void LoadModel( + mojom::ModelSpecPtr spec, + mojom::ModelRequest request, + mojom::MachineLearningService::LoadModelCallback callback) override; + + // mojom::Model: + void CreateGraphExecutor( + mojom::GraphExecutorRequest request, + mojom::Model::CreateGraphExecutorCallback callback) override; + + // mojom::GraphExecutor: + // Execute() will return the tensor set by SetOutputValue() as the output. + void Execute(base::flat_map<std::string, mojom::TensorPtr> inputs, + const std::vector<std::string>& output_names, + mojom::GraphExecutor::ExecuteCallback callback) override; + + // Call SetOutputValue() before Execute() to set the output tensor. + void SetOutputValue(const std::vector<int64_t>& shape, + const std::vector<double>& value); + + private: + mojo::BindingSet<mojom::Model> model_bindings_; + mojo::BindingSet<mojom::GraphExecutor> graph_bindings_; + mojom::TensorPtr execute_result_; + + DISALLOW_COPY_AND_ASSIGN(FakeServiceConnectionImpl); +}; + +} // namespace machine_learning +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection.cc b/chromeos/services/machine_learning/public/cpp/service_connection.cc index d749cce7..b89e31c 100644 --- a/chromeos/services/machine_learning/public/cpp/service_connection.cc +++ b/chromeos/services/machine_learning/public/cpp/service_connection.cc
@@ -5,7 +5,9 @@ #include "chromeos/services/machine_learning/public/cpp/service_connection.h" #include "base/bind.h" +#include "base/macros.h" #include "base/no_destructor.h" +#include "base/sequence_checker.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/machine_learning_client.h" #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" @@ -17,13 +19,40 @@ namespace chromeos { namespace machine_learning { -/* static */ -ServiceConnection* ServiceConnection::GetInstance() { - static base::NoDestructor<ServiceConnection> service_connection; - return service_connection.get(); -} +namespace { -void ServiceConnection::LoadModel( +// Real Impl of ServiceConnection +class ServiceConnectionImpl : public ServiceConnection { + public: + ServiceConnectionImpl(); + ~ServiceConnectionImpl() override = default; + + void LoadModel(mojom::ModelSpecPtr spec, + mojom::ModelRequest request, + mojom::MachineLearningService::LoadModelCallback + result_callback) override; + + private: + // Binds the top level interface |machine_learning_service_| to an + // implementation in the ML Service daemon, if it is not already bound. The + // binding is accomplished via D-Bus bootstrap. + void BindMachineLearningServiceIfNeeded(); + + // Mojo connection error handler. Resets |machine_learning_service_|, which + // will be reconnected upon next use. + void OnConnectionError(); + + // Response callback for MlClient::BootstrapMojoConnection. + void OnBootstrapMojoConnectionResponse(bool success); + + mojom::MachineLearningServicePtr machine_learning_service_; + + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(ServiceConnectionImpl); +}; + +void ServiceConnectionImpl::LoadModel( mojom::ModelSpecPtr spec, mojom::ModelRequest request, mojom::MachineLearningService::LoadModelCallback result_callback) { @@ -33,7 +62,7 @@ std::move(result_callback)); } -void ServiceConnection::BindMachineLearningServiceIfNeeded() { +void ServiceConnectionImpl::BindMachineLearningServiceIfNeeded() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (machine_learning_service_) { return; @@ -56,30 +85,29 @@ machine_learning::mojom::MachineLearningServicePtrInfo(std::move(pipe), 0u /* version */)); machine_learning_service_.set_connection_error_handler(base::BindOnce( - &ServiceConnection::OnConnectionError, base::Unretained(this))); + &ServiceConnectionImpl::OnConnectionError, base::Unretained(this))); // Send the file descriptor for the other end of |platform_channel| to the // ML service daemon over D-Bus. DBusThreadManager::Get()->GetMachineLearningClient()->BootstrapMojoConnection( platform_channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD(), - base::BindOnce(&ServiceConnection::OnBootstrapMojoConnectionResponse, + base::BindOnce(&ServiceConnectionImpl::OnBootstrapMojoConnectionResponse, base::Unretained(this))); } -ServiceConnection::ServiceConnection() { +ServiceConnectionImpl::ServiceConnectionImpl() { DETACH_FROM_SEQUENCE(sequence_checker_); } -ServiceConnection::~ServiceConnection() {} - -void ServiceConnection::OnConnectionError() { +void ServiceConnectionImpl::OnConnectionError() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Connection errors are not expected so log a warning. LOG(WARNING) << "ML Service Mojo connection closed"; machine_learning_service_.reset(); } -void ServiceConnection::OnBootstrapMojoConnectionResponse(const bool success) { +void ServiceConnectionImpl::OnBootstrapMojoConnectionResponse( + const bool success) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!success) { LOG(WARNING) << "BootstrapMojoConnection D-Bus call failed"; @@ -87,5 +115,22 @@ } } +static ServiceConnection* g_fake_service_connection_for_testing = nullptr; + +} // namespace + +ServiceConnection* ServiceConnection::GetInstance() { + if (g_fake_service_connection_for_testing) { + return g_fake_service_connection_for_testing; + } + static base::NoDestructor<ServiceConnectionImpl> service_connection; + return service_connection.get(); +} + +void ServiceConnection::UseFakeServiceConnectionForTesting( + ServiceConnection* const fake_service_connection) { + g_fake_service_connection_for_testing = fake_service_connection; +} + } // namespace machine_learning } // namespace chromeos
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection.h b/chromeos/services/machine_learning/public/cpp/service_connection.h index 93b88bb..5b456bdf 100644 --- a/chromeos/services/machine_learning/public/cpp/service_connection.h +++ b/chromeos/services/machine_learning/public/cpp/service_connection.h
@@ -5,9 +5,6 @@ #ifndef CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_SERVICE_CONNECTION_H_ #define CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_SERVICE_CONNECTION_H_ -#include "base/macros.h" -#include "base/no_destructor.h" -#include "base/sequence_checker.h" #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" namespace chromeos { @@ -26,37 +23,22 @@ class ServiceConnection { public: static ServiceConnection* GetInstance(); + // Overrides the result of GetInstance() for use in tests. + // Does not take ownership of |fake_service_connection|. + static void UseFakeServiceConnectionForTesting( + ServiceConnection* fake_service_connection); // Instruct ML daemon to load the model specified in |spec|, binding a Model // implementation to |request|. // Bootstraps the initial Mojo connection to the daemon if necessary. - void LoadModel( + virtual void LoadModel( mojom::ModelSpecPtr spec, mojom::ModelRequest request, - mojom::MachineLearningService::LoadModelCallback result_callback); + mojom::MachineLearningService::LoadModelCallback result_callback) = 0; - private: - friend class base::NoDestructor<ServiceConnection>; - ServiceConnection(); - ~ServiceConnection(); - - // Binds the top level interface |machine_learning_service_| to an - // implementation in the ML Service daemon, if it is not already bound. The - // binding is accomplished via D-Bus bootstrap. - void BindMachineLearningServiceIfNeeded(); - - // Mojo connection error handler. Resets |machine_learning_service_|, which - // will be reconnected upon next use. - void OnConnectionError(); - - // Response callback for MlClient::BootstrapMojoConnection. - void OnBootstrapMojoConnectionResponse(bool success); - - mojom::MachineLearningServicePtr machine_learning_service_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(ServiceConnection); + protected: + ServiceConnection() = default; + virtual ~ServiceConnection() {} }; } // namespace machine_learning
diff --git a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc index 67d148a..e37cf61 100644 --- a/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc +++ b/chromeos/services/machine_learning/public/cpp/service_connection_unittest.cc
@@ -4,13 +4,20 @@ #include "chromeos/services/machine_learning/public/cpp/service_connection.h" +#include <utility> +#include <vector> + #include "base/bind.h" #include "base/macros.h" +#include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h" +#include "chromeos/services/machine_learning/public/mojom/graph_executor.mojom.h" #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" #include "chromeos/services/machine_learning/public/mojom/model.mojom.h" +#include "chromeos/services/machine_learning/public/mojom/tensor.mojom.h" #include "mojo/core/embedder/embedder.h" #include "mojo/core/embedder/scoped_ipc_support.h" #include "mojo/public/cpp/bindings/interface_request.h" @@ -51,6 +58,68 @@ base::BindOnce([](mojom::LoadModelResult result) {})); } +// Tests the fake ML service. +TEST_F(ServiceConnectionTest, FakeServiceConnection) { + mojom::ModelPtr model; + bool callback_done = false; + FakeServiceConnectionImpl fake_service_connection; + ServiceConnection::UseFakeServiceConnectionForTesting( + &fake_service_connection); + + const double expected_value = 200.002; + fake_service_connection.SetOutputValue(std::vector<int64_t>{1L}, + std::vector<double>{expected_value}); + + ServiceConnection::GetInstance()->LoadModel( + mojom::ModelSpec::New(mojom::ModelId::TEST_MODEL), + mojo::MakeRequest(&model), + base::BindOnce( + [](bool* callback_done, mojom::LoadModelResult result) { + EXPECT_EQ(result, mojom::LoadModelResult::OK); + *callback_done = true; + }, + &callback_done)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(callback_done); + ASSERT_TRUE(model.is_bound()); + + callback_done = false; + mojom::GraphExecutorPtr graph; + model->CreateGraphExecutor( + mojo::MakeRequest(&graph), + base::BindOnce( + [](bool* callback_done, mojom::CreateGraphExecutorResult result) { + EXPECT_EQ(result, mojom::CreateGraphExecutorResult::OK); + *callback_done = true; + }, + &callback_done)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(callback_done); + ASSERT_TRUE(graph.is_bound()); + + callback_done = false; + base::flat_map<std::string, mojom::TensorPtr> inputs; + std::vector<std::string> outputs; + graph->Execute(std::move(inputs), std::move(outputs), + base::BindOnce( + [](bool* callback_done, double expected_value, + const mojom::ExecuteResult result, + base::Optional<std::vector<mojom::TensorPtr>> outputs) { + EXPECT_EQ(result, mojom::ExecuteResult::OK); + ASSERT_TRUE(outputs.has_value()); + ASSERT_EQ(outputs->size(), 1LU); + mojom::TensorPtr& tensor = (*outputs)[0]; + EXPECT_EQ(tensor->data->get_float_list()->value[0], + expected_value); + + *callback_done = true; + }, + &callback_done, expected_value)); + + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(callback_done); +} + } // namespace } // namespace machine_learning } // namespace chromeos
diff --git a/chromeos/services/media_perception/public/mojom/media_perception_service.mojom b/chromeos/services/media_perception/public/mojom/media_perception_service.mojom index 12151a5..4ac06df 100644 --- a/chromeos/services/media_perception/public/mojom/media_perception_service.mojom +++ b/chromeos/services/media_perception/public/mojom/media_perception_service.mojom
@@ -7,7 +7,7 @@ module chromeos.media_perception.mojom; import "chromeos/services/media_perception/public/mojom/media_perception.mojom"; -import "services/video_capture/public/mojom/device_factory.mojom"; +import "services/video_capture/public/mojom/video_source_provider.mojom"; // Used to establish two-way communication between a client and the media // perception service. @@ -24,6 +24,7 @@ interface MediaPerceptionControllerClient { // Interface for the service to connect to the Video Capture Service // directly via a Mojo pipe set up through a DeviceFactory request. - ConnectToVideoCaptureService@0(video_capture.mojom.DeviceFactory& request); + ConnectToVideoCaptureService@0( + video_capture.mojom.VideoSourceProvider& request); };
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 07c88675..cad7634 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -516,6 +516,7 @@ testonly = true sources = [ "address_combobox_model_unittest.cc", + "address_email_form_label_formatter_unittest.cc", "address_field_unittest.cc", "address_form_label_formatter_unittest.cc", "address_i18n_unittest.cc",
diff --git a/components/autofill/core/browser/address_email_form_label_formatter.cc b/components/autofill/core/browser/address_email_form_label_formatter.cc index 900cb5c5..547365a3 100644 --- a/components/autofill/core/browser/address_email_form_label_formatter.cc +++ b/components/autofill/core/browser/address_email_form_label_formatter.cc
@@ -4,21 +4,68 @@ #include "components/autofill/core/browser/address_email_form_label_formatter.h" +#include "components/autofill/core/browser/label_formatter_utils.h" + namespace autofill { AddressEmailFormLabelFormatter::AddressEmailFormLabelFormatter( const std::string& app_locale, FieldTypeGroup focused_group, const std::vector<ServerFieldType>& field_types) - : LabelFormatter(app_locale, focused_group, field_types) {} + : LabelFormatter(app_locale, focused_group, field_types), + form_has_street_address_(HasStreetAddress(field_types_for_labels())) {} AddressEmailFormLabelFormatter::~AddressEmailFormLabelFormatter() {} std::vector<base::string16> AddressEmailFormLabelFormatter::GetLabels( const std::vector<AutofillProfile*>& profiles) const { - // TODO(crbug.com/936168): Implement GetLabels(). std::vector<base::string16> labels; + + for (const AutofillProfile* profile : profiles) { + switch (focused_group()) { + case ADDRESS_HOME: + labels.push_back(GetLabelForFocusedAddress(*profile)); + break; + + case EMAIL: + labels.push_back(GetLabelForFocusedEmail(*profile)); + break; + + default: + labels.push_back(GetLabelDefault(*profile)); + } + } return labels; } +base::string16 AddressEmailFormLabelFormatter::GetLabelForFocusedAddress( + const AutofillProfile& profile) const { + std::vector<base::string16> label_parts; + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts); + return ConstructLabelLine(label_parts); +} + +base::string16 AddressEmailFormLabelFormatter::GetLabelForFocusedEmail( + const AutofillProfile& profile) const { + std::vector<base::string16> label_parts; + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + AddLabelPartIfNotEmpty( + GetLabelAddress(form_has_street_address_, profile, app_locale(), + field_types_for_labels()), + &label_parts); + return ConstructLabelLine(label_parts); +} + +base::string16 AddressEmailFormLabelFormatter::GetLabelDefault( + const AutofillProfile& profile) const { + std::vector<base::string16> label_parts; + AddLabelPartIfNotEmpty( + GetLabelAddress(form_has_street_address_, profile, app_locale(), + field_types_for_labels()), + &label_parts); + AddLabelPartIfNotEmpty(GetLabelEmail(profile, app_locale()), &label_parts); + return ConstructLabelLine(label_parts); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/address_email_form_label_formatter.h b/components/autofill/core/browser/address_email_form_label_formatter.h index 2d96a42..0d8d36a6 100644 --- a/components/autofill/core/browser/address_email_form_label_formatter.h +++ b/components/autofill/core/browser/address_email_form_label_formatter.h
@@ -28,8 +28,29 @@ std::vector<base::string16> GetLabels( const std::vector<AutofillProfile*>& profiles) const override; + + private: + // Returns a label to show the user when the focused field is related to + // addresses. + base::string16 GetLabelForFocusedAddress( + const AutofillProfile& profile) const; + + // Returns a label to show the user when the focused field is related to + // email addresses. + base::string16 GetLabelForFocusedEmail(const AutofillProfile& profile) const; + + // Returns a label to show the user when the focused field is related to + // neither email addresses nor addresses. This is used, for example, when the + // user focuses on a name-related field. + base::string16 GetLabelDefault(const AutofillProfile& profile) const; + + // True if this formatter's associated form has a street address field. A + // form may have an address-related field, e.g. zip code, without having a + // street address field. If a form does not include a street address field, + // street addresses should not appear in labels. + bool form_has_street_address_; }; } // namespace autofill -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_EMAIL_FORM_LABEL_FORMATTER_H_ +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_EMAIL_FORM_LABEL_FORMATTER_H_ \ No newline at end of file
diff --git a/components/autofill/core/browser/address_email_form_label_formatter_unittest.cc b/components/autofill/core/browser/address_email_form_label_formatter_unittest.cc new file mode 100644 index 0000000..efbefa1a --- /dev/null +++ b/components/autofill/core/browser/address_email_form_label_formatter_unittest.cc
@@ -0,0 +1,258 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/address_email_form_label_formatter.h" + +#include <memory> +#include <string> +#include <vector> + +#include "base/guid.h" +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/label_formatter_utils.h" +#include "components/grit/components_scaled_resources.h" +#include "components/strings/grit/components_strings.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" + +using testing::ElementsAre; + +namespace autofill { +namespace { + +std::vector<ServerFieldType> GetFieldTypes() { + return {NAME_FULL, + EMAIL_ADDRESS, + ADDRESS_BILLING_LINE1, + ADDRESS_BILLING_LINE2, + ADDRESS_BILLING_CITY, + ADDRESS_BILLING_STATE, + ADDRESS_BILLING_ZIP, + ADDRESS_BILLING_COUNTRY}; +} + +base::string16 FormatExpectedLabel(base::StringPiece label_part1, + base::StringPiece label_part2) { + return l10n_util::GetStringFUTF16(IDS_AUTOFILL_SUGGESTION_LABEL, + base::UTF8ToUTF16(label_part1), + base::UTF8ToUTF16(label_part2)); +} + +TEST(AddressEmailFormLabelFormatterTest, GetLabelsWithMissingProfiles) { + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("en-US", NAME_BILLING_FULL, GetFieldTypes()); + EXPECT_TRUE(formatter->GetLabels(std::vector<AutofillProfile*>()).empty()); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForUSProfilesAndFocusedNonAddressNonEmail) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", + "333 Washington St", "", "Brookline", "MA", "02445", + "US", "16177302000"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", + "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", + ""); + + AutofillProfile profile3 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile3, "Paul", "", "Revere", "paul1775@gmail.com", + "", "", "", "", "", "", "US", ""); + + AutofillProfile profile4 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile4, "John", "", "Adams", "", "", "", "", "Quincy", + "MA", "02169", "US", ""); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("en-US", NAME_BILLING_FULL, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2, + &profile3, &profile4}), + ElementsAre(FormatExpectedLabel("333 Washington St", "jfk@gmail.com"), + base::ASCIIToUTF16("151 Irving Ave"), + base::ASCIIToUTF16("paul1775@gmail.com"), base::string16())); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForUSProfilesAndFocusedAddress) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", + "333 Washington St", "", "Brookline", "MA", "02445", + "US", "16177302000"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "", "", + "151 Irving Ave", "", "Hyannis", "MA", "02601", "US", + ""); + + AutofillProfile profile3 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile3, "", "", "", "paul1775@gmail.com", "", "", "", + "", "", "", "US", ""); + + AutofillProfile profile4 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St", "", + "Quincy", "MA", "02169", "US", ""); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("en-US", ADDRESS_BILLING_LINE1, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2, + &profile3, &profile4}), + ElementsAre(FormatExpectedLabel("John F Kennedy", "jfk@gmail.com"), + base::ASCIIToUTF16("Jackie Kennedy"), + base::ASCIIToUTF16("paul1775@gmail.com"), base::string16())); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForUSProfilesAndFocusedEmail) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", + "333 Washington St", "", "Brookline", "MA", "02445", + "US", "16177302000"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Jackie", "", "Kennedy", "jackie@outlook.com", + "", "", "", "Hyannis", "MA", "02601", "US", ""); + + AutofillProfile profile3 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile3, "", "", "", "paul1775@gmail.com", "", "", "", + "", "", "", "US", ""); + + AutofillProfile profile4 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile4, "", "", "", "", "", "141 Franklin St", "", + "Quincy", "MA", "02169", "US", ""); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("en-US", EMAIL_ADDRESS, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2, + &profile3, &profile4}), + ElementsAre(FormatExpectedLabel("John F Kennedy", "333 Washington St"), + base::ASCIIToUTF16("Jackie Kennedy"), base::string16(), + base::ASCIIToUTF16("141 Franklin St"))); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForBRProfilesAndFocusedNonAddressNonEmail) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", + "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", + "São Paulo", "SP", "04094-050", "BR", + "+55 11 2648-0254"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", + "Estr. Dona Castorina, 110", "", "Jardim Botânico", + "Rio de Janeiro", "RJ", "22460-320", "BR", + "21987650000"); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("pt-BR", NAME_BILLING_FULL, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2}), + ElementsAre(FormatExpectedLabel("Av. Pedro Álvares Cabral, 1301", + "tarsila@aol.com"), + FormatExpectedLabel("Estr. Dona Castorina, 110", + "aavila@uol.com.br"))); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForBRProfilesAndFocusedAddress) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", + "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", + "São Paulo", "SP", "04094-050", "BR", + "+55 11 2648-0254"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", + "Estr. Dona Castorina, 110", "", "Jardim Botânico", + "Rio de Janeiro", "RJ", "22460-320", "BR", + "21987650000"); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("pt-BR", ADDRESS_BILLING_LINE1, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2}), + ElementsAre(FormatExpectedLabel("Tarsila do Amaral", "tarsila@aol.com"), + FormatExpectedLabel("Artur Avila", "aavila@uol.com.br"))); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForBRProfilesAndFocusedEmail) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "Tarsila", "do", "Amaral", "tarsila@aol.com", + "", "Av. Pedro Álvares Cabral, 1301", "", "Vila Mariana", + "São Paulo", "SP", "04094-050", "BR", + "+55 11 2648-0254"); + + AutofillProfile profile2 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile2, "Artur", "", "Avila", "aavila@uol.com.br", "", + "Estr. Dona Castorina, 110", "", "Jardim Botânico", + "Rio de Janeiro", "RJ", "22460-320", "BR", + "21987650000"); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("pt-BR", EMAIL_ADDRESS, GetFieldTypes()); + + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2}), + ElementsAre( + FormatExpectedLabel("Tarsila do Amaral", + "Av. Pedro Álvares Cabral, 1301"), + FormatExpectedLabel("Artur Avila", "Estr. Dona Castorina, 110"))); +} + +TEST(AddressEmailFormLabelFormatterTest, + GetLabelsForFormWithAddressFieldsMinusStreetAddress) { + AutofillProfile profile1 = + AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&profile1, "John", "F", "Kennedy", "jfk@gmail.com", "", + "333 Washington St", "", "Brookline", "MA", "02445", + "US", "16177302000"); + + const std::unique_ptr<LabelFormatter> formatter = + LabelFormatter::Create("en-US", EMAIL_ADDRESS, + {NAME_BILLING_FULL, EMAIL_ADDRESS, + ADDRESS_BILLING_CITY, ADDRESS_BILLING_STATE}); + + // Checks that only address fields in the form are shown in the label. + EXPECT_THAT( + formatter->GetLabels(std::vector<AutofillProfile*>{&profile1}), + ElementsAre(FormatExpectedLabel("John F Kennedy", "Brookline, MA"))); +} + +} // namespace +} // namespace autofill
diff --git a/components/autofill/core/browser/contact_form_label_formatter.cc b/components/autofill/core/browser/contact_form_label_formatter.cc index d7e6da83..bf00bcd 100644 --- a/components/autofill/core/browser/contact_form_label_formatter.cc +++ b/components/autofill/core/browser/contact_form_label_formatter.cc
@@ -4,10 +4,7 @@ #include "components/autofill/core/browser/contact_form_label_formatter.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/label_formatter_utils.h" -#include "components/autofill/core/browser/validation.h" namespace autofill { @@ -41,57 +38,40 @@ return labels; } -void ContactFormLabelFormatter::MaybeAddEmail( - const AutofillProfile& profile, - std::vector<base::string16>* label_parts) const { - const base::string16 email = ContainsEmail(groups_) - ? GetLabelEmail(profile, app_locale()) - : base::string16(); - if (!email.empty() && IsValidEmailAddress(email)) { - label_parts->push_back(email); - } +base::string16 ContactFormLabelFormatter::MaybeGetEmail( + const AutofillProfile& profile) const { + return ContainsEmail(groups_) ? GetLabelEmail(profile, app_locale()) + : base::string16(); } -void ContactFormLabelFormatter::MaybeAddPhone( - const AutofillProfile& profile, - std::vector<base::string16>* label_parts) const { - const base::string16 phone = ContainsPhone(groups_) - ? GetLabelPhone(profile, app_locale()) - : base::string16(); - if (!phone.empty()) { - label_parts->push_back(phone); - } +base::string16 ContactFormLabelFormatter::MaybeGetPhone( + const AutofillProfile& profile) const { + return ContainsPhone(groups_) ? GetLabelPhone(profile, app_locale()) + : base::string16(); } base::string16 ContactFormLabelFormatter::GetLabelForFocusedEmail( const AutofillProfile& profile) const { std::vector<base::string16> label_parts; - MaybeAddPhone(profile, &label_parts); - - const base::string16 name = GetLabelName(profile, app_locale()); - if (!name.empty()) { - label_parts.push_back(name); - } - return base::JoinString(label_parts, base::WideToUTF16(kLabelDelimiter)); + AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts); + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + return ConstructLabelLine(label_parts); } base::string16 ContactFormLabelFormatter::GetLabelForFocusedPhone( const AutofillProfile& profile) const { std::vector<base::string16> label_parts; - const base::string16 name = GetLabelName(profile, app_locale()); - if (!name.empty()) { - label_parts.push_back(name); - } - MaybeAddEmail(profile, &label_parts); - return base::JoinString(label_parts, base::WideToUTF16(kLabelDelimiter)); + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + AddLabelPartIfNotEmpty(MaybeGetEmail(profile), &label_parts); + return ConstructLabelLine(label_parts); } base::string16 ContactFormLabelFormatter::GetLabelDefault( const AutofillProfile& profile) const { std::vector<base::string16> label_parts; - MaybeAddPhone(profile, &label_parts); - MaybeAddEmail(profile, &label_parts); - return base::JoinString(label_parts, base::WideToUTF16(kLabelDelimiter)); + AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts); + AddLabelPartIfNotEmpty(MaybeGetEmail(profile), &label_parts); + return ConstructLabelLine(label_parts); } } // namespace autofill
diff --git a/components/autofill/core/browser/contact_form_label_formatter.h b/components/autofill/core/browser/contact_form_label_formatter.h index db9a0d3..6ca2e17e 100644 --- a/components/autofill/core/browser/contact_form_label_formatter.h +++ b/components/autofill/core/browser/contact_form_label_formatter.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_CONTACT_FORM_LABEL_FORMATTER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_CONTACT_FORM_LABEL_FORMATTER_H_ -#include <set> #include <string> #include <vector> @@ -31,15 +30,13 @@ const std::vector<AutofillProfile*>& profiles) const override; private: - // Adds |profile|'s email address to |label_parts| if |profile| has a valid - // email address and if this formatter's associated form has an email field. - void MaybeAddEmail(const AutofillProfile& profile, - std::vector<base::string16>* label_parts) const; + // Returns |profile|'s email address if |profile| has a valid email address + // and if this formatter's associated form has an email field. + base::string16 MaybeGetEmail(const AutofillProfile& profile) const; - // Adds |profile|'s phone number to |label_parts| if |profile| has a phone - // number and if this formatter's associated form has a phone field. - void MaybeAddPhone(const AutofillProfile& profile, - std::vector<base::string16>* label_parts) const; + // Returns |profile|'s phone number if |profile| has a phone number and if + // this formatter's associated form has a phone field. + base::string16 MaybeGetPhone(const AutofillProfile& profile) const; // Returns a label to show the user when the focused field is related to // phone numbers.
diff --git a/components/autofill/core/browser/contact_form_label_formatter_unittest.cc b/components/autofill/core/browser/contact_form_label_formatter_unittest.cc index b16f3f0..504735b7 100644 --- a/components/autofill/core/browser/contact_form_label_formatter_unittest.cc +++ b/components/autofill/core/browser/contact_form_label_formatter_unittest.cc
@@ -17,8 +17,11 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/label_formatter_utils.h" +#include "components/grit/components_scaled_resources.h" +#include "components/strings/grit/components_strings.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" using testing::ElementsAre; @@ -31,9 +34,9 @@ base::string16 FormatExpectedLabel(base::StringPiece label_part1, base::StringPiece label_part2) { - return base::JoinString( - {base::ASCIIToUTF16(label_part1), base::ASCIIToUTF16(label_part2)}, - base::WideToUTF16(kLabelDelimiter)); + return l10n_util::GetStringFUTF16(IDS_AUTOFILL_SUGGESTION_LABEL, + base::UTF8ToUTF16(label_part1), + base::UTF8ToUTF16(label_part2)); } TEST(ContactFormLabelFormatterTest, GetLabelsWithMissingProfiles) {
diff --git a/components/autofill/core/browser/label_formatter_utils.cc b/components/autofill/core/browser/label_formatter_utils.cc index b1bcfa4b..43b4554 100644 --- a/components/autofill/core/browser/label_formatter_utils.cc +++ b/components/autofill/core/browser/label_formatter_utils.cc
@@ -4,13 +4,21 @@ #include "components/autofill/core/browser/label_formatter_utils.h" +#include <algorithm> +#include <iterator> #include <memory> +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/address_i18n.h" #include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/phone_number_i18n.h" +#include "components/autofill/core/browser/validation.h" +#include "components/grit/components_scaled_resources.h" +#include "components/strings/grit/components_strings.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h" +#include "ui/base/l10n/l10n_util.h" namespace autofill { @@ -30,6 +38,28 @@ return groups & label_formatter_groups::kPhone; } +bool HasStreetAddress(const std::vector<ServerFieldType>& types) { + return std::any_of(types.begin(), types.end(), [](ServerFieldType type) { + return type == ADDRESS_HOME_STREET_ADDRESS || type == ADDRESS_HOME_LINE1 || + type == ADDRESS_BILLING_STREET_ADDRESS || + type == ADDRESS_BILLING_LINE1; + }); +} + +void AddLabelPartIfNotEmpty(const base::string16& part, + std::vector<base::string16>* parts) { + if (!part.empty()) { + parts->push_back(part); + } +} + +base::string16 ConstructLabelLine(const std::vector<base::string16>& parts) { + return parts.size() == kMaxNumberOfParts + ? l10n_util::GetStringFUTF16(IDS_AUTOFILL_SUGGESTION_LABEL, + parts.front(), parts.back()) + : base::JoinString(parts, base::string16()); +} + uint32_t DetermineGroups(const std::vector<ServerFieldType>& field_types) { uint32_t group_bitmask = 0; for (const ServerFieldType& type : field_types) { @@ -79,6 +109,17 @@ return profile.GetInfo(AutofillType(NAME_FULL), app_locale); } +base::string16 GetLabelAddress(bool form_has_street_address_, + const AutofillProfile& profile, + const std::string& app_locale, + const std::vector<ServerFieldType>& types) { + return form_has_street_address_ + ? GetLabelStreetAddress(profile, app_locale, + {ADDRESS_HOME_STREET_ADDRESS}) + : GetLabelNationalAddress(profile, app_locale, + ExtractAddressFieldTypes(types)); +} + base::string16 GetLabelNationalAddress( const AutofillProfile& profile, const std::string& app_locale, @@ -93,9 +134,25 @@ return base::UTF8ToUTF16(address_line); } +base::string16 GetLabelStreetAddress( + const AutofillProfile& profile, + const std::string& app_locale, + const std::vector<ServerFieldType>& field_types) { + std::unique_ptr<::i18n::addressinput::AddressData> address_data = + i18n::CreateAddressDataFromAutofillProfile( + MakeTrimmedProfile(profile, app_locale, field_types), app_locale); + + std::string address_line; + ::i18n::addressinput::GetStreetAddressLinesAsSingleLine(*address_data, + &address_line); + return base::UTF8ToUTF16(address_line); +} + base::string16 GetLabelEmail(const AutofillProfile& profile, const std::string& app_locale) { - return profile.GetInfo(AutofillType(EMAIL_ADDRESS), app_locale); + const base::string16 email = + profile.GetInfo(AutofillType(EMAIL_ADDRESS), app_locale); + return IsValidEmailAddress(email) ? email : base::string16(); } base::string16 GetLabelPhone(const AutofillProfile& profile, @@ -109,4 +166,16 @@ data_util::GetCountryCodeWithFallback(profile, app_locale))); } +std::vector<ServerFieldType> ExtractAddressFieldTypes( + const std::vector<ServerFieldType>& types) { + std::vector<ServerFieldType> address_types; + std::copy_if( + types.begin(), types.end(), std::back_inserter(address_types), + [](ServerFieldType type) { + return AutofillType(AutofillType(type).GetStorableType()).group() == + ADDRESS_HOME; + }); + return address_types; +} + } // namespace autofill
diff --git a/components/autofill/core/browser/label_formatter_utils.h b/components/autofill/core/browser/label_formatter_utils.h index 06dfb794..c4c2946fe 100644 --- a/components/autofill/core/browser/label_formatter_utils.h +++ b/components/autofill/core/browser/label_formatter_utils.h
@@ -9,7 +9,6 @@ #include <vector> #include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/field_types.h" @@ -32,9 +31,7 @@ } // namespace label_formatter_groups -// Used to separate the parts of a label that should appear on the same line, -// for example, (202) 456-1111 • george.washington@gmail.com. -constexpr wchar_t kLabelDelimiter[] = L" • "; +const size_t kMaxNumberOfParts = 2; // Returns true if kName is set in |groups|. bool ContainsName(uint32_t groups); @@ -48,6 +45,26 @@ // Returns true if kPhone is set in |groups|. bool ContainsPhone(uint32_t groups); +// Returns true if |types| has a street-address-related field. +bool HasStreetAddress(const std::vector<ServerFieldType>& types); + +// Adds |part| to |parts| if |part| is not an empty string. +void AddLabelPartIfNotEmpty(const base::string16& part, + std::vector<base::string16>* parts); + +// Returns the text to be shown to the user. |parts| may have 0, 1, or 2 +// elements. +// +// If |parts| is empty, then an empty string is returned. This might happen +// when (A) a profile has only name and address information and (B) the user +// associated with this profile interacts with a contact form, which includes +// name, email address, and phone number fields and excludes address fields. +// +// If |parts| has a single element, then the string is returned. This might +// happen when (A) a profile has only name and email address information and +// (B) the user associated with this profile interacts with a contact form. +base::string16 ConstructLabelLine(const std::vector<base::string16>& parts); + // Returns a bitmask indicating whether the NAME, ADDRESS_HOME, EMAIL, and // PHONE_HOME FieldTypeGroups are associated with the given |field_types|. uint32_t DetermineGroups(const std::vector<ServerFieldType>& field_types); @@ -63,6 +80,17 @@ base::string16 GetLabelName(const AutofillProfile& profile, const std::string& app_locale); +// If |form_has_street_address_| is true and |profile| is associated with a +// street address, then returns |profile|'s street address, e.g. 24 Beacon St. +// +// If |form_has_street_address_| is false and |profile| is associated with +// address fields other than street addresses, then returns the address-related +// data corresponding to |types|. +base::string16 GetLabelAddress(bool form_has_street_address_, + const AutofillProfile& profile, + const std::string& app_locale, + const std::vector<ServerFieldType>& types); + // Returns the national address associated with |profile|, e.g. // 24 Beacon St., Boston, MA 02133. base::string16 GetLabelNationalAddress( @@ -70,6 +98,13 @@ const std::string& app_locale, const std::vector<ServerFieldType>& field_types); +// Returns the street address associated with |profile|, e.g. +// 24 Beacon St. +base::string16 GetLabelStreetAddress( + const AutofillProfile& profile, + const std::string& app_locale, + const std::vector<ServerFieldType>& field_types); + // Returns the email address associated with |profile|, if any; otherwise, // returns an empty string. base::string16 GetLabelEmail(const AutofillProfile& profile, @@ -81,6 +116,10 @@ base::string16 GetLabelPhone(const AutofillProfile& profile, const std::string& app_locale); +// Returns a vector of only address-related field types in |types|. +std::vector<ServerFieldType> ExtractAddressFieldTypes( + const std::vector<ServerFieldType>& types); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_UTILS_H_
diff --git a/components/autofill/core/common/password_form.cc b/components/autofill/core/common/password_form.cc index 66eae10..9e6e5ee 100644 --- a/components/autofill/core/common/password_form.cc +++ b/components/autofill/core/common/password_form.cc
@@ -218,6 +218,12 @@ return base::JoinString(pairs, base::ASCIIToUTF16(", ")); } +bool IsHttpAuthScheme(PasswordForm::Scheme scheme) { + return scheme == PasswordForm::SCHEME_BASIC || + scheme == PasswordForm::SCHEME_DIGEST || + scheme == PasswordForm::SCHEME_OTHER; +} + std::ostream& operator<<(std::ostream& os, const PasswordForm& form) { base::DictionaryValue form_json; PasswordFormToJSON(form, &form_json);
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h index fc55fa5..b863440 100644 --- a/components/autofill/core/common/password_form.h +++ b/components/autofill/core/common/password_form.h
@@ -365,6 +365,9 @@ base::string16 ValueElementVectorToString( const ValueElementVector& value_element_pairs); +// Returns true if |scheme| corresponds to http auth scheme. +bool IsHttpAuthScheme(PasswordForm::Scheme scheme); + // For testing. std::ostream& operator<<(std::ostream& os, const PasswordForm& form); std::ostream& operator<<(std::ostream& os, PasswordForm* form);
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 8c5ba22..f883777 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -348,6 +348,11 @@ </message> </if> + <!-- Autofill suggestion label with delimiter --> + <message name="IDS_AUTOFILL_SUGGESTION_LABEL" desc="Text with disambiguating information to help users select the correct Autofill profile. Sometimes more than one type of information, such as a phone number and an email address or a name and a street address, is shown. A symbol, in this case a bullet •, is used to separate the two parts of the label that will appear on the same line, e.g. (877) 733-7699 • fanfeedback@redsox.com or George Washington • 465 Huntington Ave. A bullet • is preferred for separating the label parts; however, if the bullet • resembles another symbol in the language, please translate the bullet • as a symbol (A) that is not easily mistaken for a number or letter in the language and (B) that is typically used to separate elements."> + <ph name="LEFT_PART">$1<ex>(877) 733-7699</ex></ph> • <ph name="RIGHT_PART">$2<ex>fanfeedback@redsox.com</ex></ph> + </message> + <!-- Autofill credit card suggestion popup --> <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. [CHAR-LIMIT=32]"> Exp: <ph name="EXPIRATION_MONTH">$1<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">$2<ex>17</ex></ph>
diff --git a/components/browser_sync/BUILD.gn b/components/browser_sync/BUILD.gn index 430e510..f0f1f6f 100644 --- a/components/browser_sync/BUILD.gn +++ b/components/browser_sync/BUILD.gn
@@ -16,8 +16,6 @@ "profile_sync_service.h", "signin_confirmation_helper.cc", "signin_confirmation_helper.h", - "sync_auth_manager.cc", - "sync_auth_manager.h", ] public_deps = [ @@ -54,7 +52,6 @@ "profile_sync_service_bookmark_unittest.cc", "profile_sync_service_startup_unittest.cc", "profile_sync_service_unittest.cc", - "sync_auth_manager_unittest.cc", ] deps = [
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index caafb88..e10c3fb 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -16,7 +16,6 @@ #include "base/metrics/histogram_macros.h" #include "components/autofill/core/common/autofill_features.h" #include "components/browser_sync/browser_sync_switches.h" -#include "components/browser_sync/sync_auth_manager.h" #include "components/invalidation/public/invalidation_service.h" #include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/signin_metrics.h" @@ -31,6 +30,7 @@ #include "components/sync/driver/directory_data_type_controller.h" #include "components/sync/driver/model_type_controller.h" #include "components/sync/driver/sync_api_component_factory.h" +#include "components/sync/driver/sync_auth_manager.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/driver/sync_type_preference_provider.h" #include "components/sync/driver/sync_util.h" @@ -142,7 +142,7 @@ : sync_client_(std::move(init_params.sync_client)), sync_prefs_(sync_client_->GetPrefService()), identity_manager_(init_params.identity_manager), - auth_manager_(std::make_unique<SyncAuthManager>( + auth_manager_(std::make_unique<syncer::SyncAuthManager>( identity_manager_, base::BindRepeating(&ProfileSyncService::AccountStateChanged, base::Unretained(this)), @@ -275,13 +275,14 @@ // Note: We need to record the initial state *after* calling // RegisterForAuthNotifications(), because before that the authenticated // account isn't initialized. - RecordSyncInitialState(GetDisableReasons(), IsFirstSetupComplete()); + RecordSyncInitialState(GetDisableReasons(), + user_settings_->IsFirstSetupComplete()); // Auto-start means the first time the profile starts up, sync should start up // immediately. bool force_immediate = (start_behavior_ == AUTO_START && !HasDisableReason(DISABLE_REASON_USER_CHOICE) && - !IsFirstSetupComplete()); + !user_settings_->IsFirstSetupComplete()); startup_controller_->TryStart(force_immediate); } @@ -295,7 +296,7 @@ } } -bool ProfileSyncService::IsDataTypeControllerRunning( +bool ProfileSyncService::IsDataTypeControllerRunningForTest( syncer::ModelType type) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto iter = data_type_controllers_.find(type); @@ -377,10 +378,6 @@ return (GetDisableReasons() & kDisableReasonMask) == DISABLE_REASON_NONE; } -bool ProfileSyncService::IsEncryptedDatatypeEnabled() const { - return user_settings_->IsEncryptedDatatypeEnabled(); -} - void ProfileSyncService::OnProtocolEvent(const syncer::ProtocolEvent& event) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto& observer : protocol_event_observers_) @@ -425,7 +422,8 @@ // If this is a data type change after a major version update, reset the // passphrase prompted state and notify observers. - if (IsPassphraseRequired() && passphrase_prompt_triggered_by_version_) { + if (user_settings_->IsPassphraseRequired() && + passphrase_prompt_triggered_by_version_) { // The major version has changed and a local syncable change was made. // Reset the passphrase prompt state. passphrase_prompt_triggered_by_version_ = false; @@ -450,7 +448,7 @@ sync_prefs_.AsWeakPtr()); // Clear any old errors the first time sync starts. - if (!IsFirstSetupComplete()) { + if (!user_settings_->IsFirstSetupComplete()) { last_actionable_error_ = syncer::SyncProtocolError(); } @@ -490,7 +488,7 @@ std::make_unique<syncer::SyncManagerFactory>(network_connection_tracker_); // The first time we start up the engine we want to ensure we have a clean // directory, so delete any old one that might be there. - params.delete_sync_data_folder = !IsFirstSetupComplete(); + params.delete_sync_data_folder = !user_settings_->IsFirstSetupComplete(); params.enable_local_sync_backend = sync_prefs_.IsLocalSyncEnabled(); params.local_sync_backend_folder = sync_client_->GetLocalSyncBackendFolder(); params.restored_key_for_bootstrapping = @@ -648,10 +646,12 @@ } syncer::SyncUserSettings* ProfileSyncService::GetUserSettings() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return user_settings_.get(); } const syncer::SyncUserSettings* ProfileSyncService::GetUserSettings() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return user_settings_.get(); } @@ -743,11 +743,6 @@ return TransportState::ACTIVE; } -bool ProfileSyncService::IsFirstSetupComplete() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return user_settings_->IsFirstSetupComplete(); -} - void ProfileSyncService::UpdateLastSyncedTime() { sync_prefs_.SetLastSyncedTime(base::Time::Now()); } @@ -914,7 +909,8 @@ crypto_.SetSyncEngine(engine_.get()); // Auto-start means IsFirstSetupComplete gets set automatically. - if (start_behavior_ == AUTO_START && !IsFirstSetupComplete()) { + if (start_behavior_ == AUTO_START && + !user_settings_->IsFirstSetupComplete()) { // This will trigger a configure if it completes setup. user_settings_->SetFirstSetupComplete(); } else if (CanConfigureDataTypes(/*bypass_setup_in_progress_check=*/false)) { @@ -1095,8 +1091,8 @@ // We should never get in a state where we have no encrypted datatypes // enabled, and yet we still think we require a passphrase for decryption. - DCHECK(!GetUserSettings()->IsPassphraseRequiredForDecryption() || - IsEncryptedDatatypeEnabled()); + DCHECK(!user_settings_->IsPassphraseRequiredForDecryption() || + user_settings_->IsEncryptedDatatypeEnabled()); // Notify listeners that configuration is done. for (auto& observer : observers_) @@ -1196,11 +1192,6 @@ return !GetAuthenticatedAccountInfo().account_id.empty(); } -bool ProfileSyncService::IsPassphraseRequired() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return user_settings_->IsPassphraseRequired(); -} - base::Time ProfileSyncService::GetLastSyncedTime() const { return sync_prefs_.GetLastSyncedTime(); } @@ -1390,6 +1381,11 @@ return last_snapshot_; } +syncer::PassphraseRequiredReason +ProfileSyncService::GetPassphraseRequiredReasonForTest() const { + return crypto_.passphrase_required_reason(); +} + void ProfileSyncService::HasUnsyncedItemsForTest( base::OnceCallback<void(bool)> cb) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1487,18 +1483,11 @@ return std::move(result); } -bool ProfileSyncService::encryption_pending() const { +bool ProfileSyncService::IsEncryptionPendingForTest() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // We may be called during the setup process before we're initialized (via - // IsEncryptedDatatypeEnabled and IsPassphraseRequiredForDecryption). return user_settings_->IsEncryptionPending(); } -syncer::ModelTypeSet ProfileSyncService::GetEncryptedDataTypes() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return user_settings_->GetEncryptedDataTypes(); -} - void ProfileSyncService::OnSyncManagedPrefChange(bool is_sync_managed) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_sync_managed) {
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index 3d68f796..c65654e 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -54,6 +54,7 @@ namespace syncer { class BackendMigrator; class NetworkResources; +class SyncAuthManager; class SyncTypePreferenceProvider; class TypeDebugInfoObserver; struct CommitCounters; @@ -64,8 +65,6 @@ namespace browser_sync { -class SyncAuthManager; - // ProfileSyncService is the layer between browser subsystems like bookmarks, // and the sync engine. Each subsystem is logically thought of as being a sync // datatype. Individual datatypes can, at any point, be in a variety of stages @@ -262,11 +261,6 @@ const syncer::DataTypeManager::ConfigureResult& result) override; void OnConfigureStart() override; - // TODO(crbug.com/884159): Remove these; they should be queried via - // SyncUserSettings instead. - bool IsPassphraseRequired() const; - syncer::ModelTypeSet GetEncryptedDataTypes() const; - // IdentityManager::Observer implementation. void OnAccountsInCookieUpdated( const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, @@ -282,14 +276,30 @@ bool HasCookieJarMismatch( const std::vector<gaia::ListedAccount>& cookie_jar_accounts); - syncer::PassphraseRequiredReason passphrase_required_reason_for_test() const { - return crypto_.passphrase_required_reason(); - } - // syncer::UnrecoverableErrorHandler implementation. void OnUnrecoverableError(const base::Location& from_here, const std::string& message) override; + // SyncPrefObserver implementation. + void OnSyncManagedPrefChange(bool is_sync_managed) override; + void OnFirstSetupCompletePrefChange(bool is_first_setup_complete) override; + void OnSyncRequestedPrefChange(bool is_sync_requested) override; + void OnPreferredDataTypesPrefChange() override; + + // KeyedService implementation. This must be called exactly + // once (before this object is destroyed). + void Shutdown() override; + + // This triggers a Directory::SaveChanges() call on the sync thread. + // It should be used to persist data to disk when the process might be + // killed in the near future. + void FlushDirectory() const; + + bool IsPassphrasePrompted() const; + void SetPassphrasePrompted(bool prompted); + + syncer::PassphraseRequiredReason GetPassphraseRequiredReasonForTest() const; + // Returns whether or not the underlying sync engine has made any // local changes to items that have not yet been synced with the // server. @@ -304,18 +314,8 @@ // Used by tests to inspect the OAuth2 access tokens used by PSS. std::string GetAccessTokenForTest() const; - // SyncPrefObserver implementation. - void OnSyncManagedPrefChange(bool is_sync_managed) override; - void OnFirstSetupCompletePrefChange(bool is_first_setup_complete) override; - void OnSyncRequestedPrefChange(bool is_sync_requested) override; - void OnPreferredDataTypesPrefChange() override; - // Returns true if the syncer is waiting for new datatypes to be encrypted. - bool encryption_pending() const; - - // KeyedService implementation. This must be called exactly - // once (before this object is destroyed). - void Shutdown() override; + bool IsEncryptionPendingForTest() const; // Overrides the NetworkResources used for Sync connections. // TODO(treib): Inject this in the ctor instead. As it is, it's possible that @@ -324,18 +324,7 @@ void OverrideNetworkResourcesForTest( std::unique_ptr<syncer::NetworkResources> network_resources); - // Virtual for testing. - virtual bool IsDataTypeControllerRunning(syncer::ModelType type) const; - - // This triggers a Directory::SaveChanges() call on the sync thread. - // It should be used to persist data to disk when the process might be - // killed in the near future. - void FlushDirectory() const; - - bool IsPassphrasePrompted() const; - void SetPassphrasePrompted(bool prompted); - - void SyncAllowedByPlatformChanged(bool allowed); + bool IsDataTypeControllerRunningForTest(syncer::ModelType type) const; // Sometimes we need to wait for tasks on the sync thread in tests. scoped_refptr<base::SingleThreadTaskRunner> GetSyncThreadTaskRunnerForTest() @@ -347,6 +336,8 @@ syncer::SyncClient* GetSyncClientForTest(); private: + friend class TestProfileSyncService; + // Passed as an argument to StopImpl to control whether or not the sync // engine should clear its data directory when it shuts down. See StopImpl // for more information. @@ -355,8 +346,15 @@ CLEAR_DATA, }; - // Shorthand for user_settings_.IsFirstSetupComplete(). - bool IsFirstSetupComplete() const; + enum UnrecoverableErrorReason { + ERROR_REASON_UNSET, + ERROR_REASON_SYNCER, + ERROR_REASON_ENGINE_INIT_FAILURE, + ERROR_REASON_CONFIGURATION_RETRY, + ERROR_REASON_CONFIGURATION_FAILURE, + ERROR_REASON_ACTIONABLE_ERROR, + ERROR_REASON_LIMIT + }; // Virtual for testing. virtual syncer::WeakHandle<syncer::JsEventHandler> GetJsEventHandler(); @@ -371,20 +369,11 @@ void AccountStateChanged(); void CredentialsChanged(); + // Callback for SyncPrefs. + void SyncAllowedByPlatformChanged(bool allowed); + bool IsEngineAllowedToStart() const; - enum UnrecoverableErrorReason { - ERROR_REASON_UNSET, - ERROR_REASON_SYNCER, - ERROR_REASON_ENGINE_INIT_FAILURE, - ERROR_REASON_CONFIGURATION_RETRY, - ERROR_REASON_CONFIGURATION_FAILURE, - ERROR_REASON_ACTIONABLE_ERROR, - ERROR_REASON_LIMIT - }; - - friend class TestProfileSyncService; - // Reconfigures the data type manager with the latest enabled types. // Note: Does not initialize the engine if it is not already initialized. // If a Sync setup is currently in progress (i.e. a settings UI is open), then @@ -396,13 +385,9 @@ void ConfigureDataTypeManager(syncer::ConfigureReason reason); // Shuts down the engine sync components. - // |reason| dictates if syncing is being disabled or not, and whether - // to claim ownership of sync thread from engine. + // |reason| dictates if syncing is being disabled or not. void ShutdownImpl(syncer::ShutdownReason reason); - // Helper method for managing encryption UI. - bool IsEncryptedDatatypeEnabled() const; - // Helper for OnUnrecoverableError. void OnUnrecoverableErrorImpl(const base::Location& from_here, const std::string& message, @@ -429,8 +414,7 @@ void ClearUnrecoverableError(); // Kicks off asynchronous initialization of the SyncEngine. - // Virtual for testing. - virtual void StartUpSlowEngineComponents(); + void StartUpSlowEngineComponents(); // Update UMA for syncing engine. void UpdateEngineInitUMA(bool success) const; @@ -455,7 +439,7 @@ bool CanConfigureDataTypes(bool bypass_setup_in_progress_check) const; // Called when a SetupInProgressHandle issued by this instance is destroyed. - virtual void OnSetupInProgressHandleDestroyed(); + void OnSetupInProgressHandleDestroyed(); // Called by SyncServiceCrypto when a passphrase is required or accepted. void ReconfigureDueToPassphrase(syncer::ConfigureReason reason); @@ -471,11 +455,12 @@ // email address and sign-out upon error. identity::IdentityManager* const identity_manager_; + // The user-configurable knobs. Non-null between Initialize() and Shutdown(). std::unique_ptr<syncer::SyncUserSettingsImpl> user_settings_; // Handles tracking of the authenticated account and acquiring access tokens. // Only null after Shutdown(). - std::unique_ptr<SyncAuthManager> auth_manager_; + std::unique_ptr<syncer::SyncAuthManager> auth_manager_; // An identifier representing this instance for debugging purposes. const std::string debug_identifier_;
diff --git a/components/browser_sync/profile_sync_test_util.h b/components/browser_sync/profile_sync_test_util.h index bda4db31..364c262 100644 --- a/components/browser_sync/profile_sync_test_util.h +++ b/components/browser_sync/profile_sync_test_util.h
@@ -21,16 +21,8 @@ #include "services/identity/public/cpp/identity_test_environment.h" #include "services/network/test/test_url_loader_factory.h" -namespace user_prefs { -class PrefRegistrySyncable; -} - namespace browser_sync { -// Call this to register preferences needed for ProfileSyncService creation. -void RegisterPrefsForProfileSyncService( - user_prefs::PrefRegistrySyncable* registry); - // Aggregate this class to get all necessary support for creating a // ProfileSyncService in tests. The test still needs to have its own // MessageLoop, though.
diff --git a/components/certificate_transparency/tools/make_ct_known_logs_list.py b/components/certificate_transparency/tools/make_ct_known_logs_list.py index cbcd023c..8ded704a 100755 --- a/components/certificate_transparency/tools/make_ct_known_logs_list.py +++ b/components/certificate_transparency/tools/make_ct_known_logs_list.py
@@ -4,6 +4,8 @@ # found in the LICENSE file. """Generate a C++ file containing information on all accepted CT logs.""" +from __future__ import print_function + import base64 import hashlib import json @@ -35,7 +37,10 @@ def _split_and_hexify_binary_data(bin_data): """Pretty-prints, in hex, the given bin_data.""" - hex_data = "".join(["\\x%.2x" % ord(c) for c in bin_data]) + if sys.version_info.major == 2: + hex_data = "".join(["\\x%.2x" % ord(c) for c in bin_data]) + else: + hex_data = "".join(["\\x%.2x" % c for c in bin_data]) # line_width % 4 must be 0 to avoid splitting the hex-encoded data # across '\' which will escape the quotation marks. line_width = 68 @@ -81,7 +86,7 @@ # case into consideration if it ever happens. assert(len(log["operated_by"]) == 1) if operator_id == log["operated_by"][0]: - log_key = base64.decodestring(log["key"]) + log_key = base64.b64decode(log["key"]) log_ids.append(hashlib.sha256(log_key).digest()) return log_ids @@ -101,7 +106,7 @@ def _to_loginfo_struct(log): """Converts the given log to a CTLogInfo initialization code.""" - log_key = base64.decodestring(log["key"]) + log_key = base64.b64decode(log["key"]) split_hex_key = _split_and_hexify_binary_data(log_key) s = " {" s += "\n ".join(split_hex_key) @@ -121,7 +126,7 @@ def _to_disqualified_loginfo_struct(log): - log_key = base64.decodestring(log["key"]) + log_key = base64.b64decode(log["key"]) log_id = hashlib.sha256(log_key).digest() s = " {" s += "\n ".join(_split_and_hexify_binary_data(log_id)) @@ -145,7 +150,7 @@ return sorted( filter(_is_log_disqualified, all_logs), key=lambda l: hashlib.sha256( - base64.decodestring(l["key"])).digest()) + base64.b64decode(l["key"])).digest()) def _write_qualifying_logs_loginfo(f, qualifying_logs):
diff --git a/components/certificate_transparency/tools/make_ct_known_logs_list_unittest.py b/components/certificate_transparency/tools/make_ct_known_logs_list_unittest.py index b4862bf..18caae7 100755 --- a/components/certificate_transparency/tools/make_ct_known_logs_list_unittest.py +++ b/components/certificate_transparency/tools/make_ct_known_logs_list_unittest.py
@@ -11,12 +11,12 @@ def b64e(x): - return base64.encodestring(x) + return base64.b64encode(x.encode()) class FormattingTest(unittest.TestCase): def testSplitAndHexifyBinData(self): - bin_data = ''.join([chr(i) for i in range(32,60)]) + bin_data = bytes(bytearray(range(32,60))) expected_encoded_array = [ ('"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a' '\\x2b\\x2c\\x2d\\x2e\\x2f\\x30"'), @@ -27,7 +27,7 @@ expected_encoded_array) # This data should fit in exactly one line - 17 bytes. - short_bin_data = ''.join([chr(i) for i in range(32, 49)]) + short_bin_data = bytes(bytearray(range(32,49))) expected_short_array = [ ('"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a' '\\x2b\\x2c\\x2d\\x2e\\x2f\\x30"')] @@ -37,7 +37,7 @@ expected_short_array) # This data should fit exactly in two lines - 34 bytes. - two_line_data = ''.join([chr(i) for i in range(32, 66)]) + two_line_data = bytes(bytearray(range(32,66))) expected_two_line_data_array = [ ('"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a' '\\x2b\\x2c\\x2d\\x2e\\x2f\\x30"'), @@ -45,11 +45,11 @@ '\\x3c\\x3d\\x3e\\x3f\\x40\\x41"')] self.assertEqual( make_ct_known_logs_list._split_and_hexify_binary_data( - short_bin_data), - expected_short_array) + two_line_data), + expected_two_line_data_array) def testGetLogIDsArray(self): - log_ids = ["def", "abc", "ghi"] + log_ids = [b"def", b"abc", b"ghi"] expected_log_ids_code = [ "// The list is sorted.\n", "const char kTestIDs[][4] = {\n", @@ -76,6 +76,11 @@ class OperatorIDHandlingTest(unittest.TestCase): + @classmethod + def setUpClass(self): + if sys.version_info.major == 2: + self.assertCountEqual = self.assertItemsEqual + def testFindingGoogleOperatorID(self): ops_list = {"operators": [ {"id": 0, "name": "First"}, @@ -103,9 +108,9 @@ ] log_ids = make_ct_known_logs_list._get_log_ids_for_operator(logs, 1) self.assertEqual(2, len(log_ids)) - self.assertItemsEqual( - [hashlib.sha256(t).digest() for t in ('a', 'd')], - log_ids) + self.assertCountEqual( + [hashlib.sha256(t).digest() for t in (b'a', b'd')], + log_ids) class DisqualifiedLogsHandlingTest(unittest.TestCase):
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index 8309e6b..d6b3e50e 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -763,6 +763,7 @@ "//base:base_java", "//base:base_java_test_support", "//net/android:net_java_test_support", + "//third_party/android_tools:android_test_base_java", "//third_party/junit", "//third_party/netty4:netty_all_java", ] @@ -843,6 +844,7 @@ ":cronet_impl_all_java", ":cronet_urlconnection_impl_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_test_base_java", "//third_party/hamcrest:hamcrest_core_java", ] deps += cronet_javatests_deps_to_package @@ -878,6 +880,7 @@ "//net/android:net_java", "//net/android:net_java_test_support", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_test_base_java", "//third_party/android_tools:android_test_mock_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/junit", @@ -923,6 +926,7 @@ ":cronet_smoketests_platform_only_apk_resources", "//base:base_java_test_support", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_test_base_java", "//third_party/android_tools:android_test_mock_java", "//third_party/junit", "//third_party/netty4:netty_all_java", @@ -953,6 +957,7 @@ "//base:base_java", "//base:base_java_test_support", "//third_party/android_support_test_runner:runner_java", + "//third_party/android_tools:android_test_base_java", "//third_party/android_tools:android_test_mock_java", "//third_party/junit", "//third_party/netty4:netty_all_java",
diff --git a/components/feedback/feedback_data.cc b/components/feedback/feedback_data.cc index 238c25b..38fab874a1 100644 --- a/components/feedback/feedback_data.cc +++ b/components/feedback/feedback_data.cc
@@ -27,6 +27,11 @@ const char kTraceFilename[] = "tracing.zip"; const char kPerformanceCategoryTag[] = "Performance"; +const base::FilePath::CharType kHistogramsFilename[] = + FILE_PATH_LITERAL("histograms.txt"); + +const char kHistogramsAttachmentName[] = "histograms.zip"; + } // namespace FeedbackData::FeedbackData(feedback::FeedbackUploader* uploader) @@ -74,6 +79,21 @@ } } +void FeedbackData::SetAndCompressHistograms( + std::unique_ptr<std::string> histograms) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (!histograms) + return; + ++pending_op_count_; + base::PostTaskWithTraitsAndReply( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&FeedbackData::CompressFile, this, + base::FilePath(kHistogramsFilename), + kHistogramsAttachmentName, std::move(histograms)), + base::BindOnce(&FeedbackData::OnCompressComplete, this)); +} + void FeedbackData::AttachAndCompressFileData( std::unique_ptr<std::string> attached_filedata) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/components/feedback/feedback_data.h b/components/feedback/feedback_data.h index 4dda76a..46bbc33 100644 --- a/components/feedback/feedback_data.h +++ b/components/feedback/feedback_data.h
@@ -34,6 +34,10 @@ // compression. void SetAndCompressSystemInfo(std::unique_ptr<SystemLogsMap> sys_info); + // Sets the histograms for this instance and kicks off its + // compression. + void SetAndCompressHistograms(std::unique_ptr<std::string> histograms); + // Sets the attached file data and kicks off its compression. void AttachAndCompressFileData( std::unique_ptr<std::string> attached_filedata);
diff --git a/components/feedback/feedback_data_unittest.cc b/components/feedback/feedback_data_unittest.cc index b0deac0..1ca48b6 100644 --- a/components/feedback/feedback_data_unittest.cc +++ b/components/feedback/feedback_data_unittest.cc
@@ -24,6 +24,7 @@ namespace { +constexpr char kHistograms[] = "Histogram Data"; constexpr char kImageData[] = "Image Data"; constexpr char kFileData[] = "File Data"; @@ -97,6 +98,7 @@ }; TEST_F(FeedbackDataTest, ReportSending) { + data_->SetAndCompressHistograms(MakeScoped(kHistograms)); data_->set_image(MakeScoped(kImageData)); data_->AttachAndCompressFileData(MakeScoped(kFileData)); Send();
diff --git a/components/gwp_asan/client/guarded_page_allocator.cc b/components/gwp_asan/client/guarded_page_allocator.cc index 81abb6ef..7badc53 100644 --- a/components/gwp_asan/client/guarded_page_allocator.cc +++ b/components/gwp_asan/client/guarded_page_allocator.cc
@@ -52,8 +52,9 @@ size_t num_metadata, size_t total_pages) { CHECK_GT(max_alloced_pages, 0U); - CHECK_LE(max_alloced_pages, total_pages); - CHECK_EQ(num_metadata, total_pages); + CHECK_LE(max_alloced_pages, num_metadata); + CHECK_LE(num_metadata, AllocatorState::kMaxMetadata); + CHECK_LE(num_metadata, total_pages); CHECK_LE(total_pages, AllocatorState::kMaxSlots); max_alloced_pages_ = max_alloced_pages; state_.num_metadata = num_metadata; @@ -73,9 +74,17 @@ // Obtain this lock exclusively to satisfy the thread-safety annotations, // there should be no risk of a race here. base::AutoLock lock(lock_); + + for (size_t i = 0; i < num_metadata; i++) + free_metadata_[i] = i; + free_metadata_end_ = num_metadata; + for (size_t i = 0; i < total_pages; i++) free_slots_[i] = i; free_slots_end_ = total_pages; + + for (size_t i = 0; i < total_pages; i++) + state_.slot_to_metadata_idx[i] = AllocatorState::kInvalidMetadataIdx; } metadata_ = @@ -129,11 +138,13 @@ const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); AllocatorState::SlotIdx slot = state_.AddrToSlot(state_.GetPageAddr(addr)); - AllocatorState::MetadataIdx metadata_idx = slot; + AllocatorState::MetadataIdx metadata_idx = state_.slot_to_metadata_idx[slot]; - // Check for a call to free() with an incorrect pointer (e.g. the pointer does - // not match the allocated pointer.) - if (addr != metadata_[metadata_idx].alloc_ptr) { + // Check for a call to free() with an incorrect pointer, e.g. the pointer does + // not match the allocated pointer. This may occur with a bad free pointer or + // an outdated double free when the metadata has expired. + if (metadata_idx == AllocatorState::kInvalidMetadataIdx || + addr != metadata_[metadata_idx].alloc_ptr) { state_.free_invalid_address = addr; __builtin_trap(); } @@ -161,8 +172,9 @@ CHECK(PointerIsMine(ptr)); const uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); AllocatorState::SlotIdx slot = state_.AddrToSlot(state_.GetPageAddr(addr)); - AllocatorState::MetadataIdx metadata_idx = slot; - DCHECK_EQ(addr, metadata_[metadata_idx].alloc_ptr); + AllocatorState::MetadataIdx metadata_idx = state_.slot_to_metadata_idx[slot]; + CHECK_LT(metadata_idx, state_.num_metadata); + CHECK_EQ(addr, metadata_[metadata_idx].alloc_ptr); return metadata_[metadata_idx].alloc_size; } @@ -178,33 +190,55 @@ return false; num_alloced_pages_++; + DCHECK_GT(free_metadata_end_, 0U); + DCHECK_LE(free_metadata_end_, state_.num_metadata); + size_t rand = base::RandGenerator(free_metadata_end_); + *metadata_idx = free_metadata_[rand]; + free_metadata_end_--; + free_metadata_[rand] = free_metadata_[free_metadata_end_]; + DCHECK_EQ(free_metadata_end_, state_.num_metadata - num_alloced_pages_); + + // If this metadata has been previously used, overwrite the outdated + // slot_to_metadata_idx mapping from the previous use if it's still valid. + if (metadata_[*metadata_idx].alloc_ptr) { + DCHECK(state_.PointerIsMine(metadata_[*metadata_idx].alloc_ptr)); + size_t old_slot = state_.GetNearestSlot(metadata_[*metadata_idx].alloc_ptr); + if (state_.slot_to_metadata_idx[old_slot] == *metadata_idx) + state_.slot_to_metadata_idx[old_slot] = + AllocatorState::kInvalidMetadataIdx; + } + DCHECK_GT(free_slots_end_, 0U); DCHECK_LE(free_slots_end_, state_.total_pages); - size_t rand = base::RandGenerator(free_slots_end_); + rand = base::RandGenerator(free_slots_end_); *slot = free_slots_[rand]; free_slots_end_--; free_slots_[rand] = free_slots_[free_slots_end_]; DCHECK_EQ(free_slots_end_, state_.total_pages - num_alloced_pages_); - *metadata_idx = *slot; - + state_.slot_to_metadata_idx[*slot] = *metadata_idx; return true; } void GuardedPageAllocator::FreeSlotAndMetadata( AllocatorState::SlotIdx slot, AllocatorState::MetadataIdx metadata_idx) { - (void)metadata_idx; DCHECK_LT(slot, state_.total_pages); + DCHECK_LT(metadata_idx, state_.num_metadata); base::AutoLock lock(lock_); DCHECK_LT(free_slots_end_, state_.total_pages); free_slots_[free_slots_end_] = slot; free_slots_end_++; + DCHECK_LT(free_metadata_end_, state_.num_metadata); + free_metadata_[free_metadata_end_] = metadata_idx; + free_metadata_end_++; + DCHECK_GT(num_alloced_pages_, 0U); num_alloced_pages_--; + DCHECK_EQ(free_metadata_end_, state_.num_metadata - num_alloced_pages_); DCHECK_EQ(free_slots_end_, state_.total_pages - num_alloced_pages_); }
diff --git a/components/gwp_asan/client/guarded_page_allocator.h b/components/gwp_asan/client/guarded_page_allocator.h index 283d1ae..d8152da 100644 --- a/components/gwp_asan/client/guarded_page_allocator.h +++ b/components/gwp_asan/client/guarded_page_allocator.h
@@ -31,8 +31,10 @@ GuardedPageAllocator(); // Configures this allocator to allocate up to max_alloced_pages pages at a - // time from a pool of total_pages pages, where: - // 1 <= max_alloced_pages <= num_metadata == total_pages <= kMaxSlots + // time, holding metadata for up to num_metadata allocations, from a pool of + // total_pages pages, where: + // 1 <= max_alloced_pages <= num_metadata <= kMaxMetadata + // num_metadata <= total_pages <= kMaxSlots void Init(size_t max_alloced_pages, size_t num_metadata, size_t total_pages); // On success, returns a pointer to size bytes of page-guarded memory. On @@ -114,6 +116,12 @@ // Stores the end index of the array. size_t free_slots_end_ GUARDED_BY(lock_) = 0; + // Fixed-size array used to store all free metadata indices. + AllocatorState::MetadataIdx + free_metadata_[AllocatorState::kMaxMetadata] GUARDED_BY(lock_); + // Stores the end of the array. + size_t free_metadata_end_ GUARDED_BY(lock_) = 0; + // Number of currently-allocated pages. size_t num_alloced_pages_ GUARDED_BY(lock_) = 0; // Max number of concurrent allocations.
diff --git a/components/gwp_asan/client/gwp_asan.cc b/components/gwp_asan/client/gwp_asan.cc index d556855..4c37daa 100644 --- a/components/gwp_asan/client/gwp_asan.cc +++ b/components/gwp_asan/client/gwp_asan.cc
@@ -15,6 +15,7 @@ #include "base/numerics/safe_math.h" #include "base/rand_util.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "components/gwp_asan/client/guarded_page_allocator.h" #include "components/gwp_asan/client/sampling_allocator_shims.h" @@ -24,7 +25,16 @@ namespace { constexpr int kDefaultMaxAllocations = 7; -constexpr int kDefaultTotalPages = 30; +constexpr int kDefaultMaxMetadata = 30; + +#if defined(ARCH_CPU_64_BITS) +constexpr int kDefaultTotalPages = 512; +#else +// Use much less virtual memory on 32-bit builds (where OOMing due to lack of +// address space is a concern.) +constexpr int kDefaultTotalPages = kDefaultMaxMetadata * 2; +#endif + constexpr int kDefaultAllocationSamplingFrequency = 1000; constexpr double kDefaultProcessSamplingProbability = 1.0; constexpr int kDefaultIncreasedMemoryMultiplier = 4; @@ -35,6 +45,9 @@ const base::FeatureParam<int> kMaxAllocationsParam{&kGwpAsan, "MaxAllocations", kDefaultMaxAllocations}; +const base::FeatureParam<int> kMaxMetadataParam{&kGwpAsan, "MaxMetadata", + kDefaultMaxMetadata}; + const base::FeatureParam<int> kTotalPagesParam{&kGwpAsan, "TotalPages", kDefaultTotalPages}; @@ -46,9 +59,9 @@ &kGwpAsan, "ProcessSamplingProbability", kDefaultProcessSamplingProbability}; -// The multiplier to increase MaxAllocations/TotalPages in scenarios where we -// want to perform additional testing (e.g. on canary/dev builds or in the -// browser process.) The multiplier increase is cumulative when multiple +// The multiplier to increase MaxAllocations/MaxMetadata/TotalPages in scenarios +// where we want to perform additional testing (e.g. on canary/dev builds or in +// the browser process.) The multiplier increase is cumulative when multiple // conditions apply. const base::FeatureParam<int> kIncreasedMemoryMultiplierParam{ &kGwpAsan, "IncreasedMemoryMultiplier", kDefaultIncreasedMemoryMultiplier}; @@ -61,16 +74,27 @@ "kMaxSlots out of range"); constexpr int kMaxSlots = static_cast<int>(AllocatorState::kMaxSlots); + static_assert(AllocatorState::kMaxMetadata <= std::numeric_limits<int>::max(), + "kMaxMetadata out of range"); + constexpr int kMaxMetadata = static_cast<int>(AllocatorState::kMaxMetadata); + int total_pages = kTotalPagesParam.Get(); if (total_pages < 1 || total_pages > kMaxSlots) { DLOG(ERROR) << "GWP-ASan TotalPages is out-of-range: " << total_pages; return false; } + int max_metadata = kMaxMetadataParam.Get(); + if (max_metadata < 1 || max_metadata > std::min(total_pages, kMaxMetadata)) { + DLOG(ERROR) << "GWP-ASan MaxMetadata is out-of-range: " << max_metadata + << " with TotalPages = " << total_pages; + return false; + } + int max_allocations = kMaxAllocationsParam.Get(); - if (max_allocations < 1 || max_allocations > total_pages) { + if (max_allocations < 1 || max_allocations > max_metadata) { DLOG(ERROR) << "GWP-ASan MaxAllocations is out-of-range: " - << max_allocations << " with TotalPages = " << total_pages; + << max_allocations << " with MaxMetadata = " << max_metadata; return false; } @@ -96,30 +120,35 @@ multiplier += kIncreasedMemoryMultiplierParam.Get(); if (!multiplier.IsValid() || multiplier.ValueOrDie() < 1 || - multiplier.ValueOrDie() > kMaxSlots) { + multiplier.ValueOrDie() > kMaxMetadata) { DLOG(ERROR) << "GWP-ASan IncreaseMemoryMultiplier is out-of-range"; return false; } base::CheckedNumeric<int> total_pages_mult = total_pages; total_pages_mult *= multiplier.ValueOrDie(); + base::CheckedNumeric<int> max_metadata_mult = max_metadata; + max_metadata_mult *= multiplier; base::CheckedNumeric<int> max_allocations_mult = max_allocations; max_allocations_mult *= multiplier.ValueOrDie(); - if (!total_pages_mult.IsValid() || !max_allocations_mult.IsValid()) { + if (!total_pages_mult.IsValid() || !max_metadata_mult.IsValid() || + !max_allocations_mult.IsValid()) { DLOG(ERROR) << "GWP-ASan multiplier caused out-of-range multiply: " << multiplier.ValueOrDie(); return false; } total_pages = std::min<int>(total_pages_mult.ValueOrDie(), kMaxSlots); + max_metadata = std::min<int>( + {max_metadata_mult.ValueOrDie(), total_pages, kMaxMetadata}); max_allocations = - std::min<int>(max_allocations_mult.ValueOrDie(), total_pages); + std::min<int>(max_allocations_mult.ValueOrDie(), max_metadata); if (base::RandDouble() >= process_sampling_probability) return false; - InstallAllocatorHooks(max_allocations, total_pages, total_pages, + InstallAllocatorHooks(max_allocations, max_metadata, total_pages, alloc_sampling_freq); return true; }
diff --git a/components/gwp_asan/common/allocator_state.cc b/components/gwp_asan/common/allocator_state.cc index f09f175..c764bef 100644 --- a/components/gwp_asan/common/allocator_state.cc +++ b/components/gwp_asan/common/allocator_state.cc
@@ -4,6 +4,8 @@ #include "components/gwp_asan/common/allocator_state.h" +#include <algorithm> + #include "base/bits.h" #include "base/process/process_metrics.h" #include "base/threading/platform_thread.h" @@ -22,7 +24,8 @@ AllocatorState::GetMetadataReturnType AllocatorState::GetMetadataForAddress( uintptr_t exception_address, - uintptr_t* slot_address) const { + const SlotMetadata* metadata_arr, + MetadataIdx* metadata_idx) const { CHECK(IsValid()); if (!PointerIsMine(exception_address)) @@ -32,7 +35,17 @@ if (slot_idx >= total_pages) return GetMetadataReturnType::kErrorBadSlot; - *slot_address = metadata_addr + (slot_idx * sizeof(SlotMetadata)); + size_t index = slot_to_metadata_idx[slot_idx]; + if (index == kInvalidMetadataIdx) + return GetMetadataReturnType::kGwpAsanCrashWithMissingMetadata; + + if (index >= num_metadata) + return GetMetadataReturnType::kErrorBadMetadataIndex; + + if (GetNearestSlot(metadata_arr[index].alloc_ptr) != slot_idx) + return GetMetadataReturnType::kErrorOutdatedMetadataIndex; + + *metadata_idx = index; return GetMetadataReturnType::kGwpAsanCrash; } @@ -43,6 +56,9 @@ if (total_pages == 0 || total_pages > kMaxSlots) return false; + if (num_metadata == 0 || num_metadata > std::min(kMaxMetadata, total_pages)) + return false; + if (pages_base_addr % page_size != 0 || pages_end_addr % page_size != 0 || first_page_addr % page_size != 0) return false; @@ -57,6 +73,12 @@ if (!metadata_addr) return false; + for (size_t i = 0; i < total_pages; i++) { + if (slot_to_metadata_idx[i] != kInvalidMetadataIdx && + slot_to_metadata_idx[i] >= num_metadata) + return false; + } + return true; }
diff --git a/components/gwp_asan/common/allocator_state.h b/components/gwp_asan/common/allocator_state.h index 6a81f952..d79d8b5 100644 --- a/components/gwp_asan/common/allocator_state.h +++ b/components/gwp_asan/common/allocator_state.h
@@ -38,13 +38,15 @@ class AllocatorState { public: using MetadataIdx = uint8_t; - using SlotIdx = uint8_t; + using SlotIdx = uint16_t; // Maximum number of virtual memory slots (guard-page buffered pages) this // class can allocate. - static constexpr size_t kMaxSlots = 256; + static constexpr size_t kMaxSlots = 512; // Maximum number of concurrent allocations/metadata this class can allocate. - static constexpr size_t kMaxMetadata = 256; + static constexpr size_t kMaxMetadata = 255; + // Invalid metadata index. + static constexpr MetadataIdx kInvalidMetadataIdx = kMaxMetadata; // Maximum number of stack trace frames to collect. static constexpr size_t kMaxStackFrames = 60; @@ -56,6 +58,8 @@ "SlotIdx can hold all possible slot index values"); static_assert(std::numeric_limits<MetadataIdx>::max() >= kMaxMetadata - 1, "MetadataIdx can hold all possible metadata index values"); + static_assert(kInvalidMetadataIdx >= kMaxMetadata, + "kInvalidMetadataIdx can not reference a real index"); enum class ErrorType { kUseAfterFree = 0, @@ -69,7 +73,10 @@ enum class GetMetadataReturnType { kUnrelatedCrash = 0, kGwpAsanCrash = 1, - kErrorBadSlot = 2, + kGwpAsanCrashWithMissingMetadata = 2, + kErrorBadSlot = 3, + kErrorBadMetadataIndex = 4, + kErrorOutdatedMetadataIndex = 5, }; // Structure for storing data about a slot. @@ -117,14 +124,18 @@ bool IsValid() const; // This method is meant to be called from the crash handler with a validated - // AllocatorState object read from the crashed process. This method checks if - // exception_address is an address in the GWP-ASan region, and writes the - // address of the SlotMetadata to the provided arguments if so. + // AllocatorState object read from the crashed process. Given the metadata + // array for the allocator and an exception address, this method determines + // if the exception is related to GWP-ASan or not and what the metadata for + // the relevant GWP-ASan allocation is if so. // // Returns an enum indicating an error, unrelated exception, or a GWP-ASan - // exception (with slot_address filled out.) + // exception with or without metadata. If metadata is available, the + // metadata_idx parameter stores the index of the relevant metadata in the + // given array. GetMetadataReturnType GetMetadataForAddress(uintptr_t exception_address, - uintptr_t* slot_address) const; + const SlotMetadata* metadata_arr, + MetadataIdx* metadata_idx) const; // Returns the likely error type given an exception address and whether its // previously been allocated and deallocated. @@ -162,6 +173,10 @@ // pointer. uintptr_t free_invalid_address = 0; + // Maps a page index to a metadata index (or kInvalidMetadataIdx if no such + // mapping exists) in the metadata_addr array. + MetadataIdx slot_to_metadata_idx[kMaxSlots]; + DISALLOW_COPY_AND_ASSIGN(AllocatorState); };
diff --git a/components/gwp_asan/common/allocator_state_unittest.cc b/components/gwp_asan/common/allocator_state_unittest.cc index 47191c5..51087c3 100644 --- a/components/gwp_asan/common/allocator_state_unittest.cc +++ b/components/gwp_asan/common/allocator_state_unittest.cc
@@ -13,6 +13,8 @@ namespace gwp_asan { namespace internal { +using GetMetadataReturnType = AllocatorState::GetMetadataReturnType; + static constexpr size_t kMaxMetadata = AllocatorState::kMaxMetadata; static constexpr size_t kMaxSlots = AllocatorState::kMaxSlots; @@ -37,6 +39,9 @@ // An invalid address, but it's never dereferenced in AllocatorState. state_.metadata_addr = 0x1234; + + for (size_t i = 0; i < AllocatorState::kMaxSlots; i++) + state_.slot_to_metadata_idx[i] = AllocatorState::kInvalidMetadataIdx; } AllocatorState state_; @@ -45,10 +50,23 @@ TEST_F(AllocatorStateTest, Valid) { InitializeState(base::GetPageSize(), 1, 1); EXPECT_TRUE(state_.IsValid()); + InitializeState(base::GetPageSize(), 1, kMaxSlots); + EXPECT_TRUE(state_.IsValid()); InitializeState(base::GetPageSize(), kMaxMetadata, kMaxSlots); EXPECT_TRUE(state_.IsValid()); } +TEST_F(AllocatorStateTest, InvalidNumMetadata) { + InitializeState(base::GetPageSize(), 0, kMaxSlots); + EXPECT_FALSE(state_.IsValid()); + + InitializeState(base::GetPageSize(), kMaxMetadata + 1, kMaxSlots); + EXPECT_FALSE(state_.IsValid()); + + InitializeState(base::GetPageSize(), 2, 1); + EXPECT_FALSE(state_.IsValid()); +} + TEST_F(AllocatorStateTest, InvalidNumPages) { InitializeState(base::GetPageSize(), 1, 0); EXPECT_FALSE(state_.IsValid()); @@ -89,7 +107,19 @@ EXPECT_FALSE(state_.IsValid()); InitializeState(base::GetPageSize(), 1, 1, 0, 0, base::GetPageSize()); EXPECT_FALSE(state_.IsValid()); - InitializeState(base::GetPageSize(), 1, 0, 0, base::GetPageSize()); +} + +TEST_F(AllocatorStateTest, InvalidSlotToMetadataIdx) { + InitializeState(base::GetPageSize(), 1, kMaxSlots); + + state_.slot_to_metadata_idx[0] = AllocatorState::kInvalidMetadataIdx; + EXPECT_TRUE(state_.IsValid()); + + state_.slot_to_metadata_idx[0] = 0; + EXPECT_TRUE(state_.IsValid()); + + // Out-of-bounds metadata index + state_.slot_to_metadata_idx[0] = 1; EXPECT_FALSE(state_.IsValid()); } @@ -126,5 +156,33 @@ AllocatorState::ErrorType::kFreeInvalidAddress); } +TEST_F(AllocatorStateTest, GetMetadataForAddress) { + InitializeState(base::GetPageSize(), 2, kMaxSlots); + + AllocatorState::SlotMetadata md[2]; + md[0].alloc_ptr = state_.first_page_addr; + + AllocatorState::MetadataIdx idx; + EXPECT_EQ(state_.GetMetadataForAddress(state_.pages_base_addr - 1, md, &idx), + GetMetadataReturnType::kUnrelatedCrash); + + state_.slot_to_metadata_idx[0] = AllocatorState::kInvalidMetadataIdx; + EXPECT_EQ(state_.GetMetadataForAddress(state_.first_page_addr, md, &idx), + GetMetadataReturnType::kGwpAsanCrashWithMissingMetadata); + + state_.slot_to_metadata_idx[0] = 0; + ASSERT_EQ(state_.GetMetadataForAddress(state_.first_page_addr, md, &idx), + GetMetadataReturnType::kGwpAsanCrash); + EXPECT_EQ(idx, 0); + + // Metadata[0] is for slot 1, slot_to_metadata_idx[0] point to metadata 0. + md[0].alloc_ptr = state_.first_page_addr + state_.page_size * 2; + state_.slot_to_metadata_idx[0] = 0; + EXPECT_EQ(state_.GetMetadataForAddress(state_.first_page_addr, md, &idx), + GetMetadataReturnType::kErrorOutdatedMetadataIndex); + + // It's impossible to trigger kErrorBad{Slot,Metadata}Indices. +} + } // namespace internal } // namespace gwp_asan
diff --git a/components/gwp_asan/crash_handler/crash.proto b/components/gwp_asan/crash_handler/crash.proto index 6bea260..b410888 100644 --- a/components/gwp_asan/crash_handler/crash.proto +++ b/components/gwp_asan/crash_handler/crash.proto
@@ -41,4 +41,11 @@ // The invalid address that was free()d, if present. optional uint64 free_invalid_address = 8; + + // Set to true if metadata (allocation address and size, stack traces) was + // missing for the allocation involving this crash. This can occur when a + // use-after-free occurs after the metadata for the allocation has been + // deleted or a wild memory access occurs for a page that has no associated + // metadata. + optional bool missing_metadata = 9; }
diff --git a/components/gwp_asan/crash_handler/crash_analyzer.cc b/components/gwp_asan/crash_handler/crash_analyzer.cc index 1b28de46..a13e5ee 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer.cc +++ b/components/gwp_asan/crash_handler/crash_analyzer.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <algorithm> +#include <memory> #include <string> #include "base/logging.h" @@ -26,6 +27,7 @@ namespace gwp_asan { namespace internal { +using GetMetadataReturnType = AllocatorState::GetMetadataReturnType; using GwpAsanCrashAnalysisResult = CrashAnalyzer::GwpAsanCrashAnalysisResult; GwpAsanCrashAnalysisResult CrashAnalyzer::GetExceptionInfo( @@ -112,32 +114,55 @@ if (!exception_addr) return GwpAsanCrashAnalysisResult::kUnrelatedCrash; - uintptr_t slot_address; - auto ret = valid_state.GetMetadataForAddress(exception_addr, &slot_address); - if (ret == AllocatorState::GetMetadataReturnType::kErrorBadSlot) { - DLOG(ERROR) << "Allocator computed a bad slot index!"; - return GwpAsanCrashAnalysisResult::kErrorBadSlot; - } - if (ret == AllocatorState::GetMetadataReturnType::kUnrelatedCrash) - return GwpAsanCrashAnalysisResult::kUnrelatedCrash; - - SlotMetadata metadata; - if (!memory.Read(slot_address, sizeof(metadata), &metadata)) { - DLOG(ERROR) << "Failed to read SlotMetadata from process."; + // Read the allocator's entire metadata array. + auto metadata_arr = std::make_unique<AllocatorState::SlotMetadata[]>( + valid_state.num_metadata); + if (!memory.Read( + valid_state.metadata_addr, + sizeof(AllocatorState::SlotMetadata) * valid_state.num_metadata, + metadata_arr.get())) { + DLOG(ERROR) << "Failed to read metadata from process."; return GwpAsanCrashAnalysisResult::kErrorFailedToReadSlotMetadata; } - AllocatorState::ErrorType error = - valid_state.GetErrorType(exception_addr, metadata.alloc.trace_collected, - metadata.dealloc.trace_collected); - proto->set_error_type(static_cast<Crash_ErrorType>(error)); - proto->set_allocation_address(metadata.alloc_ptr); - proto->set_allocation_size(metadata.alloc_size); - if (metadata.alloc.tid != base::kInvalidThreadId || metadata.alloc.trace_len) - ReadAllocationInfo(metadata.alloc, proto->mutable_allocation()); - if (metadata.dealloc.tid != base::kInvalidThreadId || - metadata.dealloc.trace_len) - ReadAllocationInfo(metadata.dealloc, proto->mutable_deallocation()); + AllocatorState::MetadataIdx metadata_idx; + auto ret = valid_state.GetMetadataForAddress( + exception_addr, metadata_arr.get(), &metadata_idx); + if (ret == GetMetadataReturnType::kErrorBadSlot) { + DLOG(ERROR) << "Allocator computed a bad slot index!"; + return GwpAsanCrashAnalysisResult::kErrorBadSlot; + } + if (ret == GetMetadataReturnType::kErrorBadMetadataIndex) { + DLOG(ERROR) << "Allocator state held a bad metadata index!"; + return GwpAsanCrashAnalysisResult::kErrorBadMetadataIndex; + } + if (ret == GetMetadataReturnType::kErrorOutdatedMetadataIndex) { + DLOG(ERROR) << "Metadata index was outdated!"; + return GwpAsanCrashAnalysisResult::kErrorOutdatedMetadataIndex; + } + if (ret == GetMetadataReturnType::kUnrelatedCrash) + return GwpAsanCrashAnalysisResult::kUnrelatedCrash; + + bool missing_metadata = + (ret == GetMetadataReturnType::kGwpAsanCrashWithMissingMetadata); + proto->set_missing_metadata(missing_metadata); + + if (!missing_metadata) { + SlotMetadata& metadata = metadata_arr[metadata_idx]; + AllocatorState::ErrorType error = + valid_state.GetErrorType(exception_addr, metadata.alloc.trace_collected, + metadata.dealloc.trace_collected); + proto->set_error_type(static_cast<Crash_ErrorType>(error)); + proto->set_allocation_address(metadata.alloc_ptr); + proto->set_allocation_size(metadata.alloc_size); + if (metadata.alloc.tid != base::kInvalidThreadId || + metadata.alloc.trace_len) + ReadAllocationInfo(metadata.alloc, proto->mutable_allocation()); + if (metadata.dealloc.tid != base::kInvalidThreadId || + metadata.dealloc.trace_len) + ReadAllocationInfo(metadata.dealloc, proto->mutable_deallocation()); + } + proto->set_region_start(valid_state.pages_base_addr); proto->set_region_size(valid_state.pages_end_addr - valid_state.pages_base_addr);
diff --git a/components/gwp_asan/crash_handler/crash_analyzer.h b/components/gwp_asan/crash_handler/crash_analyzer.h index bfa5055..78eef1dd 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer.h +++ b/components/gwp_asan/crash_handler/crash_analyzer.h
@@ -49,8 +49,12 @@ kErrorBadSlot = 8, // Failed to read the crashing process' memory of the SlotMetadata. kErrorFailedToReadSlotMetadata = 9, + // The allocator stored an invalid metadata index for a given slot. + kErrorBadMetadataIndex = 10, + // The computed metadata index was outdated. + kErrorOutdatedMetadataIndex = 11, // Number of values in this enumeration, required by UMA. - kMaxValue = kErrorFailedToReadSlotMetadata + kMaxValue = kErrorOutdatedMetadataIndex }; // Given a ProcessSnapshot, determine if the exception is related to GWP-ASan.
diff --git a/components/gwp_asan/crash_handler/crash_handler.cc b/components/gwp_asan/crash_handler/crash_handler.cc index ca6a75e9..b729203f 100644 --- a/components/gwp_asan/crash_handler/crash_handler.cc +++ b/components/gwp_asan/crash_handler/crash_handler.cc
@@ -85,9 +85,14 @@ if (result != GwpAsanCrashAnalysisResult::kGwpAsanCrash) return nullptr; - LOG(ERROR) << "Detected GWP-ASan crash for allocation at 0x" << std::hex - << proto.allocation_address() << std::dec << " of type " - << ErrorToString(proto.error_type()); + if (proto.missing_metadata()) { + LOG(ERROR) << "Detected GWP-ASan crash with missing metadata."; + } else { + LOG(ERROR) << "Detected GWP-ASan crash for allocation at 0x" << std::hex + << proto.allocation_address() << std::dec << " of type " + << ErrorToString(proto.error_type()); + } + if (proto.has_free_invalid_address()) { LOG(ERROR) << "Invalid address passed to free() is " << std::hex << proto.free_invalid_address() << std::dec;
diff --git a/components/gwp_asan/crash_handler/crash_handler_unittest.cc b/components/gwp_asan/crash_handler/crash_handler_unittest.cc index 3b69926..2d17694 100644 --- a/components/gwp_asan/crash_handler/crash_handler_unittest.cc +++ b/components/gwp_asan/crash_handler/crash_handler_unittest.cc
@@ -135,6 +135,25 @@ void* ptr = gpa->Allocate(kAllocationSize); uintptr_t bad_address = reinterpret_cast<uintptr_t>(ptr) + 1; gpa->Deallocate(reinterpret_cast<void*>(bad_address)); + } else if (test_name == "MissingMetadata") { + // Consume all allocations/metadata + void* ptrs[AllocatorState::kMaxMetadata]; + for (size_t i = 0; i < AllocatorState::kMaxMetadata; i++) + ptrs[i] = gpa->Allocate(1); + + gpa->Deallocate(ptrs[0]); + + // Take the remaining metadata slot with an allocation on a different page. + while (1) { + void* new_alloc = gpa->Allocate(1); + if (new_alloc != ptrs[0]) + break; + gpa->Deallocate(new_alloc); + } + + // Cause a crash accessing an allocation that no longer has metadata + // associated with it. + *(uint8_t*)(ptrs[0]) = 0; } else { LOG(ERROR) << "Unknown test name " << test_name; } @@ -250,6 +269,9 @@ EXPECT_EQ(proto_.region_start() & (base::GetPageSize() - 1), 0U); EXPECT_EQ(proto_.region_size(), base::GetPageSize() * (2 * kTotalPages + 1)); + + EXPECT_TRUE(proto_.has_missing_metadata()); + EXPECT_FALSE(proto_.missing_metadata()); } gwp_asan::Crash proto_; @@ -289,6 +311,22 @@ EXPECT_TRUE(proto_.has_free_invalid_address()); } +TEST_F(CrashHandlerTest, MAYBE_DISABLED(MissingMetadata)) { + ASSERT_TRUE(gwp_asan_found_); + + ASSERT_TRUE(proto_.has_missing_metadata()); + EXPECT_TRUE(proto_.missing_metadata()); + + EXPECT_FALSE(proto_.has_error_type()); + EXPECT_FALSE(proto_.has_allocation_address()); + EXPECT_FALSE(proto_.has_allocation_size()); + EXPECT_FALSE(proto_.has_allocation()); + EXPECT_FALSE(proto_.has_deallocation()); + EXPECT_FALSE(proto_.has_free_invalid_address()); + EXPECT_TRUE(proto_.has_region_start()); + EXPECT_TRUE(proto_.has_region_size()); +} + TEST_F(CrashHandlerTest, MAYBE_DISABLED(UnrelatedException)) { ASSERT_FALSE(gwp_asan_found_); }
diff --git a/components/invalidation/impl/invalidation_switches.cc b/components/invalidation/impl/invalidation_switches.cc index 36b0a1e..0ba1bd4 100644 --- a/components/invalidation/impl/invalidation_switches.cc +++ b/components/invalidation/impl/invalidation_switches.cc
@@ -30,5 +30,10 @@ "FCMInvalidationsStartOnceActiveAccountAvailable", base::FEATURE_ENABLED_BY_DEFAULT}; +extern const base::Feature kFCMInvalidationsForSyncDontCheckVersion; +const base::Feature kFCMInvalidationsForSyncDontCheckVersion = { + "FCMInvalidationsForSyncDontCheckVersion", + base::FEATURE_ENABLED_BY_DEFAULT}; + } // namespace switches } // namespace invalidation
diff --git a/components/invalidation/impl/invalidation_switches.h b/components/invalidation/impl/invalidation_switches.h index 8b280dc..a797066 100644 --- a/components/invalidation/impl/invalidation_switches.h +++ b/components/invalidation/impl/invalidation_switches.h
@@ -20,6 +20,7 @@ extern const base::Feature kFCMInvalidations; extern const base::Feature kFCMInvalidationsConservativeEnabling; extern const base::Feature kFCMInvalidationsStartOnceActiveAccountAvailable; +extern const base::Feature kFCMInvalidationsForSyncDontCheckVersion; } // namespace switches } // namespace invalidation
diff --git a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java index 61dcf0c2..6cfb667 100644 --- a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java +++ b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java
@@ -5,6 +5,10 @@ package org.chromium.components.module_installer; import org.chromium.base.StrictModeContext; +import org.chromium.base.VisibleForTesting; + +import java.util.HashSet; +import java.util.Set; /** * Represents a feature module. Can be used to install the module, access its interface, etc. See @@ -14,11 +18,20 @@ * @param <T> The interface of the module/ */ public class Module<T> { + private static final Set<String> sModulesUninstalledForTesting = new HashSet<>(); private final String mName; private final Class<T> mInterfaceClass; private final String mImplClassName; private T mImpl; + /** Forces a module to appear uninstalled. */ + @VisibleForTesting + public static void setForceUninstalled(String moduleName) { + // TODO(crbug.com/944223): Make sure that this is not set after the module API has been + // used. + sModulesUninstalledForTesting.add(moduleName); + } + /** * Instantiates a module. * @@ -35,6 +48,7 @@ /** Returns true if the module is currently installed and can be accessed. */ public boolean isInstalled() { + if (sModulesUninstalledForTesting.contains(mName)) return false; if (mImpl != null) return true; // Accessing classes in the module may cause its DEX file to be loaded. And on some devices // that causes a read mode violation.
diff --git a/components/omnibox/browser/in_memory_url_index_types.cc b/components/omnibox/browser/in_memory_url_index_types.cc index 1fd5cde..dadaa6c 100644 --- a/components/omnibox/browser/in_memory_url_index_types.cc +++ b/components/omnibox/browser/in_memory_url_index_types.cc
@@ -73,13 +73,15 @@ } // Comparison function for sorting TermMatches by their offsets. -bool MatchOffsetLess(const TermMatch& m1, const TermMatch& m2) { - return m1.offset < m2.offset; +bool SortMatchComparator(const TermMatch& m1, const TermMatch& m2) { + // Return the match that occurs first (smallest offset). In the case of a tie, + // return the longer match. + return m1.offset == m2.offset ? m1.length > m2.length : m1.offset < m2.offset; } TermMatches SortMatches(const TermMatches& matches) { TermMatches sorted_matches(matches); - std::sort(sorted_matches.begin(), sorted_matches.end(), MatchOffsetLess); + std::sort(sorted_matches.begin(), sorted_matches.end(), SortMatchComparator); return sorted_matches; }
diff --git a/components/password_manager/core/browser/new_password_form_manager.cc b/components/password_manager/core/browser/new_password_form_manager.cc index 014f915f..15fa407 100644 --- a/components/password_manager/core/browser/new_password_form_manager.cc +++ b/components/password_manager/core/browser/new_password_form_manager.cc
@@ -4,6 +4,8 @@ #include "components/password_manager/core/browser/new_password_form_manager.h" +#include <utility> + #include "base/bind.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -126,33 +128,33 @@ FormFetcher* form_fetcher, std::unique_ptr<FormSaver> form_saver, scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder) - : client_(client), - driver_(driver), - observed_form_(observed_form), - metrics_recorder_(metrics_recorder), - owned_form_fetcher_( - form_fetcher ? nullptr - : std::make_unique<FormFetcherImpl>( - PasswordStore::FormDigest(observed_form), - client_, - true /* should_migrate_http_passwords */, - true /* should_query_suppressed_https_forms */)), - form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()), - form_saver_(std::move(form_saver)), - // TODO(https://crbug.com/831123): set correctly - // |is_possible_change_password_form| in |votes_uploader_| constructor - votes_uploader_(client, false /* is_possible_change_password_form */), - weak_ptr_factory_(this) { - if (!metrics_recorder_) { - metrics_recorder_ = base::MakeRefCounted<PasswordFormMetricsRecorder>( - client_->IsMainFrameSecure(), client_->GetUkmSourceId()); - } + : NewPasswordFormManager(client, + form_fetcher, + std::move(form_saver), + metrics_recorder, + PasswordStore::FormDigest(observed_form)) { + driver_ = driver; + observed_form_ = observed_form; metrics_recorder_->RecordFormSignature(CalculateFormSignature(observed_form)); - - if (owned_form_fetcher_) - owned_form_fetcher_->Fetch(); form_fetcher_->AddConsumer(this); } + +NewPasswordFormManager::NewPasswordFormManager( + PasswordManagerClient* client, + const PasswordForm& http_auth_observed_form, + FormFetcher* form_fetcher, + std::unique_ptr<FormSaver> form_saver) + : NewPasswordFormManager( + client, + form_fetcher, + std::move(form_saver), + nullptr /* metrics_recorder */, + PasswordStore::FormDigest(http_auth_observed_form)) { + observed_http_auth_digest_ = + PasswordStore::FormDigest(http_auth_observed_form); + form_fetcher_->AddConsumer(this); +} + NewPasswordFormManager::~NewPasswordFormManager() = default; bool NewPasswordFormManager::DoesManage( @@ -192,6 +194,8 @@ const autofill::FormData& form) const { if (!is_submitted_) return false; + if (IsHttpAuth()) + return false; if (form.action == submitted_form_.action) return true; // TODO(https://crbug.com/831123): Implement other checks from a function @@ -544,10 +548,14 @@ size_t filtered_count) { received_stored_credentials_time_ = TimeTicks::Now(); std::vector<const PasswordForm*> matches; + PasswordForm::Scheme observed_form_scheme = + observed_http_auth_digest_ ? observed_http_auth_digest_->scheme + : PasswordForm::SCHEME_HTML; std::copy_if(non_federated.begin(), non_federated.end(), - std::back_inserter(matches), [](const PasswordForm* form) { + std::back_inserter(matches), + [observed_form_scheme](const PasswordForm* form) { return !form->blacklisted_by_user && - form->scheme == PasswordForm::SCHEME_HTML; + form->scheme == observed_form_scheme; }); password_manager_util::FindBestMatches(matches, &best_matches_, @@ -564,7 +572,11 @@ autofills_left_ = kMaxTimesAutofill; - if (parser_.predictions() || !wait_for_server_predictions_for_filling_) { + if (IsHttpAuth()) { + // No server prediction for http auth, so no need to wait. + FillHttpAuth(); + } else if (parser_.predictions() || + !wait_for_server_predictions_for_filling_) { ReportTimeBetweenStoreAndServerUMA(); Fill(); } else if (!waiting_for_server_predictions_) { @@ -602,6 +614,25 @@ return true; } +bool NewPasswordFormManager::ProvisionallySaveHttpAuthFormIfIsManaged( + const PasswordForm& submitted_form) { + if (!IsHttpAuth()) + return false; + if (!(*observed_http_auth_digest_ == + PasswordStore::FormDigest(submitted_form))) + return false; + + parsed_submitted_form_.reset(new PasswordForm(submitted_form)); + is_submitted_ = true; + + CreatePendingCredentials(); + return true; +} + +bool NewPasswordFormManager::IsHttpAuth() const { + return !!observed_http_auth_digest_; +} + void NewPasswordFormManager::ProcessServerPredictions( const std::map<FormSignature, FormPredictions>& predictions) { if (parser_.predictions()) { @@ -683,6 +714,36 @@ Fill(); } +NewPasswordFormManager::NewPasswordFormManager( + PasswordManagerClient* client, + FormFetcher* form_fetcher, + std::unique_ptr<FormSaver> form_saver, + scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder, + const PasswordStore::FormDigest& form_digest) + : client_(client), + metrics_recorder_(metrics_recorder), + owned_form_fetcher_( + form_fetcher ? nullptr + : std::make_unique<FormFetcherImpl>( + form_digest, + client_, + true /* should_migrate_http_passwords */, + true /* should_query_suppressed_https_forms */)), + form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()), + form_saver_(std::move(form_saver)), + // TODO(https://crbug.com/831123): set correctly + // |is_possible_change_password_form| in |votes_uploader_| constructor + votes_uploader_(client, false /* is_possible_change_password_form */), + weak_ptr_factory_(this) { + if (!metrics_recorder_) { + metrics_recorder_ = base::MakeRefCounted<PasswordFormMetricsRecorder>( + client_->IsMainFrameSecure(), client_->GetUkmSourceId()); + } + + if (owned_form_fetcher_) + owned_form_fetcher_->Fetch(); +} + void NewPasswordFormManager::RecordMetricOnCompareParsingResult( const PasswordForm& parsed_form) { bool same = @@ -970,6 +1031,10 @@ void NewPasswordFormManager::CreatePendingCredentialsForNewCredentials( const PasswordForm& submitted_password_form, const base::string16& password_element) { + if (IsHttpAuth()) { + pending_credentials_ = submitted_password_form; + return; + } // TODO(https://crbug.com/831123): Replace parsing of the observed form with // usage of already parsed submitted form. std::unique_ptr<PasswordForm> parsed_observed_form = @@ -1031,6 +1096,14 @@ } } +void NewPasswordFormManager::FillHttpAuth() { + DCHECK(IsHttpAuth()); + if (!preferred_match_) + return; + + client_->AutofillHttpAuth(best_matches_, *preferred_match_); +} + std::vector<PasswordForm> NewPasswordFormManager::FindOtherCredentialsToUpdate() { std::vector<autofill::PasswordForm> credentials_to_update;
diff --git a/components/password_manager/core/browser/new_password_form_manager.h b/components/password_manager/core/browser/new_password_form_manager.h index c69987cd..249bd5bf 100644 --- a/components/password_manager/core/browser/new_password_form_manager.h +++ b/components/password_manager/core/browser/new_password_form_manager.h
@@ -21,6 +21,7 @@ #include "components/password_manager/core/browser/password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_form_metrics_recorder.h" #include "components/password_manager/core/browser/password_form_user_action.h" +#include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/votes_uploader.h" namespace password_manager { @@ -51,6 +52,12 @@ std::unique_ptr<FormSaver> form_saver, scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder); + // Constructor for http authentication (aka basic authentication). + NewPasswordFormManager(PasswordManagerClient* client, + const autofill::PasswordForm& http_auth_observed_form, + FormFetcher* form_fetcher, + std::unique_ptr<FormSaver> form_saver); + ~NewPasswordFormManager() override; // The upper limit on how many times Chrome will try to autofill the same @@ -79,6 +86,13 @@ // Otherwise returns false. bool ProvisionallySave(const autofill::FormData& submitted_form, const PasswordManagerDriver* driver); + + // If |submitted_form| is managed by *this then saves |submitted_form| to + // |submitted_form_| field, sets |is_submitted| = true and returns true. + // Otherwise returns false. + bool ProvisionallySaveHttpAuthFormIfIsManaged( + const autofill::PasswordForm& submitted_form); + bool is_submitted() { return is_submitted_; } void set_not_submitted() { is_submitted_ = false; } @@ -86,6 +100,9 @@ old_parsing_result_ = form; } + // Returns true if |*this| manages http authentication. + bool IsHttpAuth() const; + // Selects from |predictions| predictions that corresponds to // |observed_form_|, initiates filling and stores predictions in // |predictions_|. @@ -165,6 +182,14 @@ size_t filtered_count) override; private: + // Delegating constructor. + NewPasswordFormManager( + PasswordManagerClient* client, + FormFetcher* form_fetcher, + std::unique_ptr<FormSaver> form_saver, + scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder, + const PasswordStore::FormDigest& form_digest); + // Compares |parsed_form| with |old_parsing_result_| and records UKM metric. // TODO(https://crbug.com/831123): Remove it when the old form parsing is // removed. @@ -216,6 +241,9 @@ // triggers some UMA reporting. void ProcessUpdate(); + // Sends fill data to the http auth popup. + void FillHttpAuth(); + // Goes through |not_best_matches_|, updates the password of those which share // the old password and username with |pending_credentials_| to the new // password of |pending_credentials_|, and returns copies of all such modified @@ -238,8 +266,12 @@ base::WeakPtr<PasswordManagerDriver> driver_; + // TODO(https://crbug.com/943045): use std::variant for keeping + // |observed_form_| and |observed_http_auth_digest_|. autofill::FormData observed_form_; + base::Optional<PasswordStore::FormDigest> observed_http_auth_digest_; + // Set of nonblacklisted PasswordForms from the DB that best match the form // being managed by |this|, indexed by username. The PasswordForms are owned // by |form_fetcher_|.
diff --git a/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/components/password_manager/core/browser/new_password_form_manager_unittest.cc index a77139b..d6081f0 100644 --- a/components/password_manager/core/browser/new_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/new_password_form_manager_unittest.cc
@@ -102,6 +102,10 @@ autofill::AutofillDownloadManager*()); MOCK_METHOD0(UpdateFormManagers, void()); + + MOCK_CONST_METHOD2(AutofillHttpAuth, + void(const std::map<base::string16, const PasswordForm*>&, + const PasswordForm&)); }; void CheckPendingCredentials(const PasswordForm& expected, @@ -353,6 +357,17 @@ &client_, driver_.AsWeakPtr(), observed_form, fetcher_.get(), std::make_unique<NiceMock<MockFormSaver>>(), nullptr)); } + + // Creates NewPasswordFormManager and sets it to |form_manager_| for + // |base_auth_observed_form|. Along the way a new |fetcher_| is created. + void CreateFormManagerForHttpAuthForm( + const PasswordForm& base_auth_observed_form) { + fetcher_.reset(new FakeFormFetcher()); + fetcher_->Fetch(); + form_manager_.reset(new NewPasswordFormManager( + &client_, base_auth_observed_form, fetcher_.get(), + std::make_unique<NiceMock<MockFormSaver>>())); + } }; TEST_F(NewPasswordFormManagerTest, DoesManage) { @@ -1822,6 +1837,113 @@ } } +TEST_F(NewPasswordFormManagerTest, SaveHttpAuthNoHttpAuthStored) { + TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); + + for (bool html_credentials_saved : {false, true}) { + SCOPED_TRACE(testing::Message("html_credentials_saved=") + << html_credentials_saved); + PasswordForm http_auth_form = parsed_observed_form_; + http_auth_form.scheme = PasswordForm::SCHEME_BASIC; + + // Check that no filling because no http auth credentials are stored. + EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0); + EXPECT_CALL(client_, AutofillHttpAuth(_, _)).Times(0); + + CreateFormManagerForHttpAuthForm(http_auth_form); + MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get()); + + std::vector<const PasswordForm*> saved_matches; + if (html_credentials_saved) + saved_matches.push_back(&saved_match_); + fetcher_->SetNonFederated(saved_matches, 0u); + + base::string16 username = ASCIIToUTF16("user1"); + base::string16 password = ASCIIToUTF16("pass1"); + http_auth_form.username_value = username; + http_auth_form.password_value = password; + + // Check that submitted credentials are saved. + ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthFormIfIsManaged( + http_auth_form)); + EXPECT_TRUE(form_manager_->IsNewLogin()); + + PasswordForm saved_form; + EXPECT_CALL(form_saver, Save(_, _)).WillOnce(SaveArg<0>(&saved_form)); + form_manager_->Save(); + + EXPECT_EQ(http_auth_form.signon_realm, saved_form.signon_realm); + EXPECT_EQ(username, saved_form.username_value); + EXPECT_EQ(password, saved_form.password_value); + } +} + +TEST_F(NewPasswordFormManagerTest, HTTPAuthAlreadySaved) { + TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); + PasswordForm http_auth_form = parsed_observed_form_; + http_auth_form.scheme = PasswordForm::SCHEME_BASIC; + + CreateFormManagerForHttpAuthForm(http_auth_form); + + const base::string16 username = ASCIIToUTF16("user1"); + const base::string16 password = ASCIIToUTF16("pass1"); + http_auth_form.username_value = username; + http_auth_form.password_value = password; + EXPECT_CALL(client_, AutofillHttpAuth(_, http_auth_form)).Times(1); + fetcher_->SetNonFederated({&http_auth_form}, 0u); + + // Check that if known credentials are submitted, then |form_manager_| is not + // in state new login nor password overridden. + ASSERT_TRUE( + form_manager_->ProvisionallySaveHttpAuthFormIfIsManaged(http_auth_form)); + EXPECT_FALSE(form_manager_->IsNewLogin()); + EXPECT_FALSE(form_manager_->IsPasswordOverridden()); +} + +TEST_F(NewPasswordFormManagerTest, HTTPAuthPasswordOverridden) { + TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); + PasswordForm http_auth_form = parsed_observed_form_; + http_auth_form.scheme = PasswordForm::SCHEME_BASIC; + + CreateFormManagerForHttpAuthForm(http_auth_form); + MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get()); + + PasswordForm saved_http_auth_form = http_auth_form; + const base::string16 username = ASCIIToUTF16("user1"); + const base::string16 password = ASCIIToUTF16("pass1"); + saved_http_auth_form.username_value = username; + saved_http_auth_form.password_value = password; + EXPECT_CALL(client_, AutofillHttpAuth(_, saved_http_auth_form)).Times(1); + fetcher_->SetNonFederated({&saved_http_auth_form}, 0u); + + // Check that if new password is submitted, then |form_manager_| is in state + // password overridden. + PasswordForm submitted_http_auth_form = saved_http_auth_form; + base::string16 new_password = password + ASCIIToUTF16("1"); + submitted_http_auth_form.password_value = new_password; + ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthFormIfIsManaged( + submitted_http_auth_form)); + EXPECT_FALSE(form_manager_->IsNewLogin()); + EXPECT_TRUE(form_manager_->IsPasswordOverridden()); + + // Check that the password is updated in the stored credential. + PasswordForm updated_form; + std::map<base::string16, const PasswordForm*> best_matches; + std::vector<PasswordForm> credentials_to_update; + EXPECT_CALL(form_saver, Update(_, _, _, nullptr)) + .WillOnce(DoAll(SaveArg<0>(&updated_form), SaveArg<1>(&best_matches), + SaveArgPointee<2>(&credentials_to_update))); + + form_manager_->Save(); + + EXPECT_TRUE( + ArePasswordFormUniqueKeyEqual(saved_http_auth_form, updated_form)); + EXPECT_EQ(new_password, updated_form.password_value); + ASSERT_TRUE(best_matches.find(username) != best_matches.end()); + EXPECT_EQ(saved_http_auth_form, *best_matches[username]); + EXPECT_TRUE(credentials_to_update.empty()); +} + } // namespace } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index ad41647d..09cd3027 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -329,6 +329,25 @@ metrics_recorder->RecordParsingOnSavingDifference(result); } +bool IsNewFormParsingForFillingEnabled() { + return base::FeatureList::IsEnabled(features::kNewPasswordFormParsing); +} + +bool IsNewFormParsingForSavingEnabled() { + return base::FeatureList::IsEnabled( + features::kNewPasswordFormParsingForSaving) && + base::FeatureList::IsEnabled(features::kNewPasswordFormParsing); +} + +// Returns true if it is turned off using PasswordFormManager in +// PasswordManager. +bool IsOnlyNewParserEnabled() { + return base::FeatureList::IsEnabled( + features::kNewPasswordFormParsingForSaving) && + base::FeatureList::IsEnabled(features::kNewPasswordFormParsing) && + base::FeatureList::IsEnabled(features::kOnlyNewParser); +} + } // namespace // static @@ -373,16 +392,7 @@ } PasswordManager::PasswordManager(PasswordManagerClient* client) - : client_(client), - is_new_form_parsing_for_saving_enabled_( - base::FeatureList::IsEnabled( - features::kNewPasswordFormParsingForSaving) && - base::FeatureList::IsEnabled(features::kNewPasswordFormParsing)), - is_only_new_parser_enabled_( - base::FeatureList::IsEnabled( - features::kNewPasswordFormParsingForSaving) && - base::FeatureList::IsEnabled(features::kNewPasswordFormParsing) && - base::FeatureList::IsEnabled(features::kOnlyNewParser)) { + : client_(client) { DCHECK(client_); } @@ -441,7 +451,7 @@ // If there is no corresponding PasswordFormManager, we create one. This is // not the common case, and should only happen when there is a bug in our // ability to detect forms. No matched |NewPasswordFormManager| is unlikely. - if (!is_new_form_parsing_for_saving_enabled_) { + if (!IsNewFormParsingForSavingEnabled()) { auto manager = std::make_unique<PasswordFormManager>( this, client_, driver->AsWeakPtr(), form, std::make_unique<FormSaverImpl>(client_->GetPasswordStore()), nullptr); @@ -547,12 +557,15 @@ void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) { pending_login_managers_.clear(); - if (form_may_be_submitted) { - for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { - if (manager->is_submitted()) { - owned_submitted_form_manager_ = std::move(manager); - break; - } + for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { + if (!form_may_be_submitted && !manager->IsHttpAuth()) { + // |form_may_be_submitted| applies only to HTML forms, http auth has to be + // considered anyway. + continue; + } + if (manager->is_submitted()) { + owned_submitted_form_manager_ = std::move(manager); + break; } } @@ -635,12 +648,24 @@ void PasswordManager::OnPasswordFormSubmitted( password_manager::PasswordManagerDriver* driver, const PasswordForm& password_form) { - if (is_new_form_parsing_for_saving_enabled_) + if (IsNewFormParsingForSavingEnabled()) ProvisionallySaveForm(password_form.form_data, driver); ProvisionallySavePassword(password_form, driver); } +void PasswordManager::OnPasswordHttpAuthFormSubmitted( + const PasswordForm& password_form) { + // TODO(https://crbug.com/602676): extract http auth handling in a separate + // class. + if (!client_->IsSavingAndFillingEnabled(password_form.origin)) + return; + if (IsNewFormParsingForSavingEnabled()) + ProvisionallySaveHttpAuthForm(password_form); + else + ProvisionallySavePassword(password_form, nullptr); +} + void PasswordManager::OnPasswordFormSubmittedNoChecks( password_manager::PasswordManagerDriver* driver, const PasswordForm& password_form) { @@ -659,7 +684,7 @@ return; } - if (is_new_form_parsing_for_saving_enabled_) + if (IsNewFormParsingForSavingEnabled()) ProvisionallySaveForm(password_form.form_data, driver); ProvisionallySavePassword(password_form, driver); @@ -679,7 +704,7 @@ return; std::unique_ptr<PasswordFormManagerInterface> manager = nullptr; - if (is_new_form_parsing_for_saving_enabled_) { + if (IsNewFormParsingForSavingEnabled()) { NewPasswordFormManager* matched_manager = ProvisionallySaveForm(password_form.form_data, driver); manager = matched_manager ? matched_manager->Clone() : nullptr; @@ -736,9 +761,8 @@ logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD); } - if (base::FeatureList::IsEnabled(features::kNewPasswordFormParsing)) { + if (IsNewFormParsingForFillingEnabled()) CreateFormManagers(driver, forms); - } // Record whether or not this top-level URL has at least one password field. client_->AnnotateNavigationEntry(!forms.empty()); @@ -772,14 +796,7 @@ pending_login_managers_.size()); } - bool html_scheme = - !forms.empty() && forms[0].scheme == PasswordForm::SCHEME_HTML; - - // Create PasswordFormManager for non-html scheme even if - // |is_only_new_parser_enabled_|. - // TODO(https://crbug.com/915161) Implement support of non-html schemes in - // NewPasswordFormManager. - if (html_scheme && is_only_new_parser_enabled_) + if (IsOnlyNewParserEnabled()) return; for (const PasswordForm& form : forms) { @@ -840,6 +857,7 @@ const std::vector<PasswordForm>& forms) { // Find new forms. std::vector<const PasswordForm*> new_forms; + std::vector<const PasswordForm*> new_http_auth_forms; for (const PasswordForm& form : forms) { // TODO(https://crbug.com/831123): Implement inside NewPasswordFormManger // not-filling Gaia forms that should be ignored instead of non-creating @@ -848,6 +866,13 @@ continue; if (!client_->IsFillingEnabled(form.origin)) continue; + + if (IsHttpAuthScheme(form.scheme)) { + // No need to look for existing http auth forms, a http auth form is sent + // only once. + new_http_auth_forms.push_back(&form); + continue; + } NewPasswordFormManager* manager = FindMatchedManager(form.form_data, form_managers_, driver); @@ -868,6 +893,14 @@ auto* manager = CreateFormManager(driver, new_form->form_data); manager->set_old_parsing_result(*new_form); } + + for (const PasswordForm* new_form : new_http_auth_forms) { + // TODO(https://crbug.com/602676): extract http auth handling in a separate + // class. + form_managers_.push_back(std::make_unique<NewPasswordFormManager>( + client_, *new_form, nullptr, + std::make_unique<FormSaverImpl>(client_->GetPasswordStore()))); + } } NewPasswordFormManager* PasswordManager::CreateFormManager( @@ -951,6 +984,25 @@ return matched_manager; } +void PasswordManager::ProvisionallySaveHttpAuthForm( + const autofill::PasswordForm& password_form) { + // TODO(https://crbug.com/602676): extract http auth handling in a separate + // class. + NewPasswordFormManager* matching_manager = nullptr; + for (const auto& manager : form_managers_) { + if (manager->ProvisionallySaveHttpAuthFormIfIsManaged(password_form)) { + matching_manager = manager.get(); + break; + } + } + + // Set all other form managers to no submission state. + for (const auto& manager : form_managers_) { + if (manager.get() != matching_manager) + manager->set_not_submitted(); + } +} + void PasswordManager::ReportSpecPriorityForGeneratedPassword( const PasswordForm& password_form, uint32_t spec_priority) { @@ -1187,7 +1239,7 @@ // TODO(https://crbug.com/831123): Remove logging when the old form parsing is // removed. - if (is_new_form_parsing_for_saving_enabled_) { + if (IsNewFormParsingForSavingEnabled()) { // In this case, |submitted_manager| points to a NewPasswordFormManager and // |provisional_save_manager_| to a PasswordFormManager. They use the new // and the old FormData parser, respectively. Log the differences using UKM @@ -1310,8 +1362,7 @@ logger.reset( new BrowserSavePasswordProgressLogger(client_->GetLogManager())); - if (base::FeatureList::IsEnabled( - password_manager::features::kNewPasswordFormParsing)) { + if (IsNewFormParsingForFillingEnabled()) { for (const autofill::FormStructure* form : forms) predictions_[form->form_signature()] = ConvertToFormPredictions(*form); for (auto& manager : form_managers_) @@ -1386,14 +1437,7 @@ } PasswordFormManagerInterface* PasswordManager::GetSubmittedManager() const { - // TODO(https://crbug.com/915161) Implement support of non-html schemes in - // NewPasswordFormManager remove using PasswordFormManager for such forms. - if (provisional_save_manager_ && - provisional_save_manager_->GetPendingCredentials().scheme != - PasswordForm::SCHEME_HTML) - return provisional_save_manager_.get(); - - if (!is_new_form_parsing_for_saving_enabled_) + if (!IsNewFormParsingForSavingEnabled()) return provisional_save_manager_.get(); if (owned_submitted_form_manager_) @@ -1410,14 +1454,7 @@ std::unique_ptr<PasswordFormManagerForUI> PasswordManager::MoveOwnedSubmittedManager() { - // TODO(https://crbug.com/915161) Implement support of non-html schemes in - // NewPasswordFormManager remove using PasswordFormManager for such forms. - if (provisional_save_manager_ && - provisional_save_manager_->GetPendingCredentials().scheme != - PasswordForm::SCHEME_HTML) - return std::move(provisional_save_manager_); - - if (!is_new_form_parsing_for_saving_enabled_) + if (!IsNewFormParsingForSavingEnabled()) return std::move(provisional_save_manager_); if (owned_submitted_form_manager_) @@ -1460,7 +1497,7 @@ PasswordFormManagerInterface* PasswordManager::GetMatchedManager( const PasswordManagerDriver* driver, const PasswordForm& form) { - if (!is_new_form_parsing_for_saving_enabled_) + if (!IsNewFormParsingForSavingEnabled()) return GetMatchingPendingManager(form); return GetMatchedManager(driver, form.form_data);
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index be1f968..3a06935 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -117,6 +117,10 @@ void OnPasswordFormSubmitted(PasswordManagerDriver* driver, const autofill::PasswordForm& password_form); + // Handles submitted http auth credentials. + void OnPasswordHttpAuthFormSubmitted( + const autofill::PasswordForm& password_form); + // Handles a password form being submitted, assumes that submission is // successful and does not do any checks on success of submission. // For example, this is called if |password_form| was filled @@ -281,6 +285,11 @@ NewPasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form, PasswordManagerDriver* driver); + // Passes |form| to NewPasswordFormManager that manages it for using it after + // detecting submission success for saving. + void ProvisionallySaveHttpAuthForm( + const autofill::PasswordForm& password_form); + // Returns the best match in |pending_login_managers_| for |form|. May return // nullptr if no match exists. PasswordFormManager* GetMatchingPendingManager( @@ -390,11 +399,6 @@ // The user-visible URL from the last time a password was provisionally saved. GURL main_frame_url_; - const bool is_new_form_parsing_for_saving_enabled_; - - // If true, it turns off using PasswordFormManager in PasswordManager. - const bool is_only_new_parser_enabled_; - // True if Credential Management API function store() was called. In this case // PasswordManager does not need to show a save/update prompt since // CredentialManagerImpl takes care of it.
diff --git a/components/password_manager/core/browser/password_manager_client.cc b/components/password_manager/core/browser/password_manager_client.cc index 53e69f4..9148b1c 100644 --- a/components/password_manager/core/browser/password_manager_client.cc +++ b/components/password_manager/core/browser/password_manager_client.cc
@@ -36,6 +36,10 @@ const std::vector<const autofill::PasswordForm*>* federated_matches) const { } +void PasswordManagerClient::AutofillHttpAuth( + const std::map<base::string16, const autofill::PasswordForm*>& best_matches, + const autofill::PasswordForm& preferred_match) const {} + SyncState PasswordManagerClient::GetPasswordSyncState() const { return NOT_SYNCING; }
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h index 898adcc..24419d3 100644 --- a/components/password_manager/core/browser/password_manager_client.h +++ b/components/password_manager/core/browser/password_manager_client.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_CLIENT_H_ #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_CLIENT_H_ +#include <map> #include <vector> #include "base/callback.h" @@ -177,6 +178,13 @@ const std::vector<const autofill::PasswordForm*>* federated_matches) const; + // Sends username/password from |preferred_match| for filling in the http auth + // prompt. + virtual void AutofillHttpAuth( + const std::map<base::string16, const autofill::PasswordForm*>& + best_matches, + const autofill::PasswordForm& preferred_match) const; + // Gets prefs associated with this embedder. virtual PrefService* GetPrefs() const = 0;
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 66061fe6..732d803a 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -46,6 +46,7 @@ using autofill::PasswordForm; using autofill::PasswordFormFillData; using base::ASCIIToUTF16; +using base::Feature; using base::TestMockTimeTaskRunner; using testing::_; using testing::AnyNumber; @@ -419,12 +420,27 @@ manager()->OnPasswordFormSubmitted(&driver_, form); } + void TurnOnNewParsingForFilling( + base::test::ScopedFeatureList* scoped_feature_list, + bool enabled) { + std::vector<Feature> enabled_features; + std::vector<Feature> disabled_features; + (enabled ? enabled_features : disabled_features) = + std::vector<Feature>({features::kNewPasswordFormParsing}); + scoped_feature_list->InitWithFeatures(enabled_features, disabled_features); + manager_.reset(new PasswordManager(&client_)); + } + void TurnOnNewParsingForSaving( - base::test::ScopedFeatureList* scoped_feature_list) { - scoped_feature_list->InitWithFeatures( - {features::kNewPasswordFormParsing, - features::kNewPasswordFormParsingForSaving}, - {}); + base::test::ScopedFeatureList* scoped_feature_list, + bool enabled) { + std::vector<Feature> enabled_features; + std::vector<Feature> disabled_features; + (enabled ? enabled_features : disabled_features) = + std::vector<Feature>({features::kNewPasswordFormParsing, + features::kNewPasswordFormParsingForSaving}); + scoped_feature_list->InitWithFeatures(enabled_features, disabled_features); + manager_.reset(new PasswordManager(&client_)); } @@ -501,8 +517,7 @@ SCOPED_TRACE(testing::Message() << "new_parsing_for_saving = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parsing_for_saving) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); // Test that generated passwords are stored without asking the user. std::vector<PasswordForm> observed; PasswordForm form(MakeFormWithOnlyNewPasswordField()); @@ -949,23 +964,69 @@ form_manager_to_save->Save(); } -TEST_F(PasswordManagerTest, ProxyAuth) { - PasswordForm observed_form; - observed_form.scheme = PasswordForm::SCHEME_BASIC; - observed_form.origin = GURL("http://proxy.com/"); - observed_form.signon_realm = "proxy.com/realm"; +TEST_F(PasswordManagerTest, HttpAuthFilling) { + for (bool new_parser_enabled : {false, true}) { + SCOPED_TRACE(testing::Message("new_parser_enabled=") << new_parser_enabled); + base::test::ScopedFeatureList scoped_feature_list; + TurnOnNewParsingForFilling(&scoped_feature_list, new_parser_enabled); + EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) + .WillRepeatedly(Return(true)); + PasswordForm observed_form; + observed_form.scheme = PasswordForm::SCHEME_BASIC; + observed_form.origin = GURL("http://proxy.com/"); + observed_form.signon_realm = "proxy.com/realm"; - PasswordForm stored_form = observed_form; - stored_form.username_value = ASCIIToUTF16("user"); - stored_form.password_value = ASCIIToUTF16("1234"); + PasswordForm stored_form = observed_form; + stored_form.username_value = ASCIIToUTF16("user"); + stored_form.password_value = ASCIIToUTF16("1234"); - MockLoginModelObserver observer; - EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(stored_form))); - EXPECT_CALL(observer, OnAutofillDataAvailableInternal(ASCIIToUTF16("user"), - ASCIIToUTF16("1234"))); - manager()->AddObserverAndDeliverCredentials(&observer, observed_form); - manager()->RemoveObserver(&observer); + MockLoginModelObserver observer; + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeConsumer(stored_form))); + EXPECT_CALL(observer, OnAutofillDataAvailableInternal( + ASCIIToUTF16("user"), ASCIIToUTF16("1234"))); + manager()->AddObserverAndDeliverCredentials(&observer, observed_form); + manager()->RemoveObserver(&observer); + testing::Mock::VerifyAndClearExpectations(&client_); + testing::Mock::VerifyAndClearExpectations(&store_); + } +} + +TEST_F(PasswordManagerTest, HttpAuthSaving) { + for (bool new_parsing_for_saving : {false, true}) { + SCOPED_TRACE(testing::Message("new_parser_enabled=") + << new_parsing_for_saving); + base::test::ScopedFeatureList scoped_feature_list; + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); + EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) + .WillRepeatedly(Return(true)); + PasswordForm observed_form; + observed_form.scheme = PasswordForm::SCHEME_BASIC; + observed_form.origin = GURL("http://proxy.com/"); + observed_form.signon_realm = "proxy.com/realm"; + + MockLoginModelObserver observer; + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); + + // Initiate creating a form manager. + manager()->AddObserverAndDeliverCredentials(&observer, observed_form); + + // Emulate that http auth credentials submitted. + PasswordForm submitted_form = observed_form; + submitted_form.username_value = ASCIIToUTF16("user"); + submitted_form.password_value = ASCIIToUTF16("1234"); + manager()->OnPasswordHttpAuthFormSubmitted(submitted_form); + + // Expect save prompt on successful submission. + std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + manager()->OnPasswordFormsRendered(&driver_, {}, true); + + testing::Mock::VerifyAndClearExpectations(&client_); + manager()->RemoveObserver(&observer); + } } TEST_F(PasswordManagerTest, InitiallyInvisibleForm) { @@ -2069,17 +2130,20 @@ TEST_F(PasswordManagerTest, SetGenerationElementAndReasonForForm) { // Verifies that |SetGenerationElementAndReasonForForm| method works for both // old and new parsers. - for (bool new_parser : {false, true}) { - SCOPED_TRACE(testing::Message("new_parser = ") << new_parser); + for (bool new_parsing_for_saving : {false, true}) { + SCOPED_TRACE(testing::Message("new_parser = ") << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parser) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); PasswordForm form(MakeSimpleForm()); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) .WillRepeatedly(Return(true)); + + // When the new parser is on both PasswordFormManager and + // NewPasswordFormManager are created, as a result there are 2 requests for + // the saved credentials. EXPECT_CALL(*store_, GetLogins(PasswordStore::FormDigest(form), _)) - .Times(new_parser ? 2 : 1); + .Times(new_parsing_for_saving ? 2 : 1); manager()->OnPasswordFormsParsed(&driver_, {form}); manager()->SetGenerationElementAndReasonForForm(&driver_, form, @@ -2088,7 +2152,7 @@ manager()->OnPresaveGeneratedPassword(&driver_, form); const PasswordFormManagerInterface* form_manager = nullptr; - if (new_parser) { + if (new_parsing_for_saving) { ASSERT_EQ(1u, manager()->form_managers().size()); form_manager = manager()->form_managers().front().get(); } else { @@ -2127,8 +2191,7 @@ SCOPED_TRACE(testing::Message() << "new_parsing_for_saving = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parsing_for_saving) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); // Seeing a form should result in creating PasswordFormManager and // NewPasswordFormManager and querying PasswordStore. Calling @@ -2750,7 +2813,7 @@ if (only_new_parser) TurnOnOnlyNewPassword(&scoped_feature_list); else - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -2804,7 +2867,7 @@ if (only_new_parser) TurnOnOnlyNewPassword(&scoped_feature_list); else - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -2857,7 +2920,7 @@ // have the same metrics recorder. TEST_F(PasswordManagerTest, CheckMetricsRecorder) { base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); PasswordForm form(MakeSimpleForm()); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -2914,7 +2977,7 @@ TEST_F(PasswordManagerTest, ManualFallbackForSavingNewParser) { base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); std::vector<PasswordForm> observed; @@ -2959,7 +3022,7 @@ TEST_F(PasswordManagerTest, ParsingOnSavingMetricRecorded) { ukm::TestAutoSetUkmRecorder test_ukm_recorder; base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); PasswordForm form = MakeSimpleForm(); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -2986,7 +3049,7 @@ TEST_F(PasswordManagerTest, NoSavePromptWhenPasswordManagerDisabled) { base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); PasswordForm form(MakeSimpleForm()); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -3006,7 +3069,7 @@ TEST_F(PasswordManagerTest, NoSavePromptForNotPasswordForm) { base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); PasswordForm form(MakeSimpleForm()); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -3069,7 +3132,7 @@ SCOPED_TRACE(testing::Message() << "form_may_be_submitted = " << form_may_be_submitted); base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); PasswordForm form(MakeSimpleForm()); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -3116,8 +3179,7 @@ SCOPED_TRACE(testing::Message() << "new_parsing_for_saving = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parsing_for_saving) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); manager()->OnPasswordFormsParsed(nullptr, {}); @@ -3282,14 +3344,7 @@ << "test case = " << test_case.description << ", new_parsing_for_saving = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parsing_for_saving) { - // This also resets the password manager. - TurnOnNewParsingForSaving(&scoped_feature_list); - } else { - // Reset the password manager to discard state from the previous - // test_case. - manager_.reset(new PasswordManager(&client_)); - } + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); manager()->OnPasswordFormsParsed(nullptr, test_case.parsed_forms); @@ -3335,7 +3390,7 @@ // |NewPasswordFormManager| is created in process of saving. TEST_F(PasswordManagerTest, CreateNewPasswordFormManagerOnSaving) { base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -3376,8 +3431,7 @@ SCOPED_TRACE(testing::Message() << "new_parsing_for_saving = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (new_parsing_for_saving) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -3404,12 +3458,11 @@ // but no automatic filling and saving are available. TEST_F(PasswordManagerTest, FillingAndSavingFallbacksOnNonPasswordForm) { NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); - for (bool is_new_parsing_on : {false, true}) { + for (bool new_parsing_for_saving : {false, true}) { SCOPED_TRACE(testing::Message() - << "is_new_parsing_on = " << is_new_parsing_on); + << "is_new_parsing_on = " << new_parsing_for_saving); base::test::ScopedFeatureList scoped_feature_list; - if (is_new_parsing_on) - TurnOnNewParsingForSaving(&scoped_feature_list); + TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true));
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index 4bf05e8..748ba7e 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp
@@ -446,6 +446,12 @@ <message name="IDS_POLICY_CONFLICT_DIFF_VALUE" desc="Text explaining that a policy had conflicting sources and values."> Warning: More than one source with conflicting values is present for this policy! </message> + <message name="IDS_POLICY_MIGRATED_OLD_POLICY" desc="Text explaining that a policy is deprecated, and that admins should use the new policy instead"> + This policy is deprecated. You should use the <ph name="NEW_POLICY">$1<ex>AllowDinosaurEasterEgg</ex></ph> policy instead. + </message> + <message name="IDS_POLICY_MIGRATED_NEW_POLICY" desc="Text explaining that the policy value was automatically copied from a deprecated policy's value"> + This policy was automatically copied from the deprecated <ph name="OLD_POLICY">$1<ex>AllowDinosaurEasterEgg</ex></ph> policy. You should use this policy instead. + </message> <message name="IDS_POLICY_BLOCKED" desc="Text explaining that a policy is blocked, therefore ignored."> This policy is blocked, its value will be ignored. </message>
diff --git a/components/previews/content/BUILD.gn b/components/previews/content/BUILD.gn index fb3f705..25a3cd3 100644 --- a/components/previews/content/BUILD.gn +++ b/components/previews/content/BUILD.gn
@@ -46,6 +46,7 @@ sources = [ "hint_cache_leveldb_store_unittest.cc", "hint_cache_unittest.cc", + "hints_fetcher_unittest.cc", "previews_decider_impl_unittest.cc", "previews_hints_unittest.cc", "previews_hints_util_unittest.cc",
diff --git a/components/previews/content/hints_fetcher.cc b/components/previews/content/hints_fetcher.cc index 9d40db9d..52951d4b 100644 --- a/components/previews/content/hints_fetcher.cc +++ b/components/previews/content/hints_fetcher.cc
@@ -4,27 +4,45 @@ #include "components/previews/content/hints_fetcher.h" +#include <memory> +#include <utility> + #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "components/optimization_guide/proto/hints.pb.h" #include "components/previews/content/hint_cache.h" #include "components/previews/core/previews_experiments.h" +#include "net/base/load_flags.h" +#include "net/base/url_util.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" namespace previews { -HintsFetcher::HintsFetcher(HintCache* hint_cache) : hint_cache_(hint_cache) {} +HintsFetcher::HintsFetcher( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + GURL optimization_guide_service_url, + HintCache* hint_cache) + : hint_cache_(hint_cache), + optimization_guide_service_url_(net::AppendOrReplaceQueryParameter( + optimization_guide_service_url, + "key", + params::GetOptimizationGuideServiceAPIKey())) { + url_loader_factory_ = std::move(url_loader_factory); + CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme)); + CHECK(previews::params::IsHintsFetchingEnabled()); +} HintsFetcher::~HintsFetcher() {} -void HintsFetcher::FetchHintsForHosts(const std::vector<std::string>& hosts) { +bool HintsFetcher::FetchOptimizationGuideServiceHints( + const std::vector<std::string>& hosts) { SEQUENCE_CHECKER(sequence_checker_); - UMA_HISTOGRAM_COUNTS_100("Previews.HintsFetcher.GetHintsRequest.HostCount", - hosts.size()); - GetRemoteHints(hosts); -} + if (url_loader_) + return false; -void HintsFetcher::GetRemoteHints(const std::vector<std::string>& hosts) { get_hints_request_ = std::make_unique<optimization_guide::proto::GetHintsRequest>(); @@ -36,8 +54,8 @@ optimization_guide::proto::RESOURCE_LOADING); static_assert(static_cast<int>(PreviewsType::LITE_PAGE_REDIRECT) + 1 == static_cast<int>(PreviewsType::LAST), - "PreviewsType has been updated, make sure OnePlatform hints " - "are not affected"); + "PreviewsType has been updated, make sure Optimization Guide " + "Service hints are not affected"); get_hints_request_->set_context( optimization_guide::proto::CONTEXT_BATCH_UPDATE); @@ -47,14 +65,80 @@ get_hints_request_->add_hosts(); host_info->set_host(host); } + + std::string serialized_request; + get_hints_request_->SerializeToString(&serialized_request); + + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("hintsfetcher_gethintsrequest", R"( + semantics { + sender: "HintsFetcher" + description: + "Requests Hints from the Optimization Guide Service for use in " + "providing data saving and pageload optimizations for Chrome." + trigger: + "Requested periodically if Data Saver is enabled and the browser " + "has Hints that are older than a threshold set by " + "the server." + data: "A list of the user's most engaged websites." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "Users can control Data Saver on Android via 'Data Saver' setting. " + "Data Saver is not available on iOS." + policy_exception_justification: "Not implemented." + })"); + + auto resource_request = std::make_unique<network::ResourceRequest>(); + + resource_request->url = optimization_guide_service_url_; + + resource_request->method = "POST"; + resource_request->load_flags = net::LOAD_BYPASS_PROXY | + net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES; + + url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), + traffic_annotation); + + url_loader_->AttachStringForUpload(serialized_request, + "application/x-protobuf"); + + UMA_HISTOGRAM_COUNTS_100("Previews.HintsFetcher.GetHintsRequest.HostCount", + hosts.size()); + + // |url_loader_| should not retry on 5xx errors since the server may already + // be overloaded. |url_loader_| should retry on network changes since the + // network stack may receive the connection change event later than |this|. + static const int kMaxRetries = 1; + url_loader_->SetRetryOptions( + kMaxRetries, network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE); + + url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory_.get(), + base::BindOnce(&HintsFetcher::OnURLLoadComplete, base::Unretained(this))); + return true; } void HintsFetcher::HandleResponse(const std::string& config_data, int status, - int response_code) {} + int response_code) { + // TODO(mcrouse): Handle received string and convert to GetHintsResponse + // and pass back via the callback provided by the owner that requested hints. +} void HintsFetcher::OnURLLoadComplete( - std::unique_ptr<std::string> response_body) {} + std::unique_ptr<std::string> response_body) { + int response_code = -1; + if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) { + response_code = url_loader_->ResponseInfo()->headers->response_code(); + } + HandleResponse(response_body ? *response_body : "", url_loader_->NetError(), + response_code); + url_loader_.reset(); +} bool HintsFetcher::ParseGetHintsResponseAndApplyHints( const optimization_guide::proto::GetHintsResponse& get_hints_response) {
diff --git a/components/previews/content/hints_fetcher.h b/components/previews/content/hints_fetcher.h index 37c4923..7e9918cb 100644 --- a/components/previews/content/hints_fetcher.h +++ b/components/previews/content/hints_fetcher.h
@@ -10,35 +10,44 @@ #include <vector> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" #include "components/optimization_guide/proto/hints.pb.h" #include "components/previews/core/previews_experiments.h" #include "url/gurl.h" +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + namespace previews { class HintCache; -// A class to handle OnePlatform client requests for optimization hints from -// the remote Optimization Guide Service. +// A class to handle requests for optimization hints from a remote Optimization +// Guide Service. // -// When Chrome starts up, if the client's OnePlatform hints have not been -// updated in over day, this class will be triggered to fetch new hints from the -// remote Optimization Guide Service. Owner must ensure that |hint_cache| -// remains alive for the lifetime of |HintsFetcher|. +// This class fetches new hints from the remote Optimization Guide Service. +// Owner must ensure that |hint_cache| remains alive for the lifetime of +// |HintsFetcher|. class HintsFetcher { public: - explicit HintsFetcher(HintCache* hint_cache); + HintsFetcher( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + GURL optimization_guide_service_url, + HintCache* hint_cache); ~HintsFetcher(); - // Handles any configuration or checking needed and then - // initiates the fetch of OnePlatform Hints. - void FetchHintsForHosts(const std::vector<std::string>& hosts); + // Requests hints from the Optimization Guide Service if a request for + // them is not already in progress. Returns whether a new request was + // issued. + bool FetchOptimizationGuideServiceHints( + const std::vector<std::string>& hosts); private: - // Creates the GetHintsResponse proto and executes the SimpleURLLoader request - // to the remote Optimization Guide Service with the |get_hints_request_|. - void GetRemoteHints(const std::vector<std::string>& hosts); + // URL loader completion callback. + void OnURLLoadComplete(std::unique_ptr<std::string> response_body); // Handles the response from the remote Optimization Guide Service. // |response| is the response body, |status| is the @@ -48,8 +57,6 @@ int status, int response_code); - // URL loader completion callback. - void OnURLLoadComplete(std::unique_ptr<std::string> response_body); // Parses the hints component of |get_hints_response| and applies it to // |hints_|. Returns true if |get_hints_response| was successfully @@ -62,12 +69,20 @@ std::unique_ptr<optimization_guide::proto::GetHintsRequest> get_hints_request_; - // The URL for the remote Optimization Guide Service. - const GURL oneplatform_service_url_; - - // The caller must ensure that the |hints_| outlives this instance. + // HintCache (unowned) is a reference to the set of Optimization Hints + // provided by the remote Optimization Guide Service. The caller must ensure + // that the |hints_cache_| outlives this instance. HintCache* hint_cache_ = nullptr; + // The URL for the remote Optimization Guide Service. + const GURL optimization_guide_service_url_; + + // Holds the |URLLoader| for an active hints request. + std::unique_ptr<network::SimpleURLLoader> url_loader_; + + // Used for creating a |url_loader_| when needed for request hints. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(HintsFetcher);
diff --git a/components/previews/content/hints_fetcher_unittest.cc b/components/previews/content/hints_fetcher_unittest.cc new file mode 100644 index 0000000..17f0b0e --- /dev/null +++ b/components/previews/content/hints_fetcher_unittest.cc
@@ -0,0 +1,108 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/previews/content/hints_fetcher.h" + +#include <memory> + +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" +#include "components/previews/content/hint_cache.h" +#include "components/previews/core/previews_experiments.h" +#include "components/previews/core/previews_features.h" +#include "net/base/url_util.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace previews { + +constexpr char optimization_guide_service_url[] = "https://hintsserver.com/"; + +class HintsFetcherTest : public testing::Test { + public: + explicit HintsFetcherTest() + : shared_url_loader_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_)) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeatureWithParameters( + features::kOptimizationHintsFetching, {}); + + hints_fetcher_ = std::make_unique<HintsFetcher>( + shared_url_loader_factory_, GURL(optimization_guide_service_url), + hint_cache_); + } + + ~HintsFetcherTest() override {} + + protected: + bool FetchHints(const std::vector<std::string>& hosts) { + bool status = hints_fetcher_->FetchOptimizationGuideServiceHints(hosts); + RunUntilIdle(); + return status; + } + + // Return a 200 response with provided content to any pending requests. + bool SimulateResponse(const std::string& content) { + return test_url_loader_factory_.SimulateResponseForPendingRequest( + optimization_guide_service_url, content, net::HTTP_OK, + network::TestURLLoaderFactory::kUrlMatchPrefix); + } + + void VerifyHasPendingFetchRequests() { + EXPECT_GE(test_url_loader_factory_.NumPending(), 1); + std::string key_value; + for (const auto& pending_request : + *test_url_loader_factory_.pending_requests()) { + EXPECT_EQ(pending_request.request.method, "POST"); + EXPECT_TRUE(net::GetValueForKeyInQuery(pending_request.request.url, "key", + &key_value)); + } + } + + private: + void RunUntilIdle() { + scoped_task_environment_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + + HintCache* hint_cache_; + + std::unique_ptr<HintsFetcher> hints_fetcher_; + + scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; + network::TestURLLoaderFactory test_url_loader_factory_; + + DISALLOW_COPY_AND_ASSIGN(HintsFetcherTest); +}; + +TEST_F(HintsFetcherTest, FetchOptimizationGuideServiceHints) { + std::string response_content; + EXPECT_TRUE(FetchHints(std::vector<std::string>())); + VerifyHasPendingFetchRequests(); + EXPECT_TRUE(SimulateResponse(response_content)); +} + +// Tests to ensure that multiple hint fetches by the same object cannot be in +// progress simultaneously. +TEST_F(HintsFetcherTest, FetchInProcess) { + std::string response_content; + // Fetch back to back without waiting for Fetch to complete, + // |fetch_in_progress_| should cause early exit. + EXPECT_TRUE(FetchHints(std::vector<std::string>())); + EXPECT_FALSE(FetchHints(std::vector<std::string>())); + + // Once response arrives, check to make sure a new fetch can start. + SimulateResponse(response_content); + EXPECT_TRUE(FetchHints(std::vector<std::string>())); +} + +} // namespace previews
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc index 484254f..2612a1d 100644 --- a/components/previews/content/previews_decider_impl_unittest.cc +++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -51,6 +51,7 @@ #include "net/nqe/network_quality_estimator_test_util.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/test/test_network_quality_tracker.h" +#include "services/network/test/test_shared_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -151,11 +152,13 @@ optimization_guide::OptimizationGuideService* optimization_guide_service, const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, const base::FilePath& test_path, - PreviewsTopHostProvider* previews_top_host_provider) + PreviewsTopHostProvider* previews_top_host_provider, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : PreviewsOptimizationGuide(optimization_guide_service, ui_task_runner, test_path, - previews_top_host_provider) {} + previews_top_host_provider, + url_loader_factory) {} ~TestPreviewsOptimizationGuide() override {} // PreviewsOptimizationGuide: @@ -399,7 +402,8 @@ std::make_unique<TestPreviewsOptimizationGuide>( &optimization_guide_service_, scoped_task_environment_.GetMainThreadTaskRunner(), - temp_dir_.GetPath(), &previews_top_host_provider_), + temp_dir_.GetPath(), &previews_top_host_provider_, + url_loader_factory_), base::BindRepeating(&IsPreviewFieldTrialEnabled), std::make_unique<PreviewsLogger>(), std::move(allowed_types), &network_quality_tracker_)); @@ -444,6 +448,7 @@ TestPreviewsTopHostProvider previews_top_host_provider_; std::unique_ptr<TestPreviewsUIService> ui_service_; network::TestNetworkQualityTracker network_quality_tracker_; + scoped_refptr<network::TestSharedURLLoaderFactory> url_loader_factory_; }; TEST_F(PreviewsDeciderImplTest, AllPreviewsDisabledByFeature) {
diff --git a/components/previews/content/previews_optimization_guide.cc b/components/previews/content/previews_optimization_guide.cc index 7d12dbc..b5c270a 100644 --- a/components/previews/content/previews_optimization_guide.cc +++ b/components/previews/content/previews_optimization_guide.cc
@@ -22,6 +22,7 @@ #include "components/previews/content/previews_user_data.h" #include "components/previews/core/previews_constants.h" #include "components/previews/core/previews_switches.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "url/gurl.h" namespace previews { @@ -84,7 +85,8 @@ optimization_guide::OptimizationGuideService* optimization_guide_service, const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, const base::FilePath& profile_path, - PreviewsTopHostProvider* previews_top_host_provider) + PreviewsTopHostProvider* previews_top_host_provider, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : optimization_guide_service_(optimization_guide_service), ui_task_runner_(ui_task_runner), background_task_runner_(base::CreateSequencedTaskRunnerWithTraits( @@ -93,6 +95,7 @@ std::make_unique<HintCacheLevelDBStore>(profile_path, background_task_runner_))), previews_top_host_provider_(previews_top_host_provider), + url_loader_factory_(url_loader_factory), ui_weak_ptr_factory_(this) { DCHECK(optimization_guide_service_); hint_cache_->Initialize( @@ -221,18 +224,18 @@ base::Version(kManualConfigComponentVersion)))); } - // If user is eligible for platform hints, currently controlled by a feature - // flag |kPreviewsOnePlatformHints|, start the OnePlatform client request. + // If the client is eligible to fetch hints, currently controlled by a feature + // flag |kOptimizationHintsFetching|, fetch hints from the remote + // Optimization Guide Service. + // // TODO(mcrouse): Add a check for user specific state in addition to the - // feature state: - // (1) Data saver should be enabled - // (2) Infobar notification does not need to be shown to the user. + // feature state: (1) Data saver should be enabled (2) Infobar notification + // does not need to be shown to the user. - if (previews::params::IsOnePlatformHintsEnabled()) { - // TODO(mcrouse): We will likely need to an async call and likely - // within a timer that will call GetOnePlatformClientHints(). - // This is a temporary call for testing. - GetOnePlatformClientHints(); + if (previews::params::IsHintsFetchingEnabled()) { + // TODO(mcrouse): On initialize, we should check if hints have be fetched + // recently. We will also schedule this to be called on a timer. + FetchHints(); } // Register as an observer regardless of hint proto override usage. This is @@ -267,23 +270,18 @@ std::move(next_update_closure_))); } -void PreviewsOptimizationGuide::GetOnePlatformClientHints() { +void PreviewsOptimizationGuide::FetchHints() { std::vector<std::string> top_hosts = previews_top_host_provider_->GetTopHosts( - previews::params::MaxOnePlatformUpdateHosts()); - DCHECK_GE(previews::params::MaxOnePlatformUpdateHosts(), top_hosts.size()); - + previews::params::MaxHostsForOptimizationGuideServiceHintsFetch()); + DCHECK_GE(previews::params::MaxHostsForOptimizationGuideServiceHintsFetch(), + top_hosts.size()); if (!hints_fetcher_) { - hints_fetcher_ = std::make_unique<HintsFetcher>(hint_cache_.get()); + hints_fetcher_ = std::make_unique<HintsFetcher>( + url_loader_factory_, params::GetOptimizationGuideServiceURL(), + hint_cache_.get()); } - hints_fetcher_->FetchHintsForHosts(top_hosts); - - // TODO(mcrouse) to build SimpleURLLoader to perform request from service - // for per-user client hints. - // Pass callback for when URLLoader request is successful to call - // PreviewOptimizationGuide::OnOnePlatformClientHintsReceived(). - - OnOnePlatformHintsReceived(); + hints_fetcher_->FetchOptimizationGuideServiceHints(top_hosts); } void PreviewsOptimizationGuide::UpdateHints( @@ -322,9 +320,4 @@ next_update_closure_ = std::move(next_update_closure); } -void PreviewsOptimizationGuide::OnOnePlatformHintsReceived() { - // TODO(mcrouse): Once hints reseponse received from server, will need to - // update the cache and store. -} - } // namespace previews
diff --git a/components/previews/content/previews_optimization_guide.h b/components/previews/content/previews_optimization_guide.h index 76a2198..15d5f42 100644 --- a/components/previews/content/previews_optimization_guide.h +++ b/components/previews/content/previews_optimization_guide.h
@@ -12,6 +12,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" @@ -23,6 +24,9 @@ namespace base { class FilePath; } // namespace base +namespace network { +class SharedURLLoaderFactory; +} // namespace network namespace optimization_guide { struct HintsComponentInfo; class OptimizationGuideService; @@ -30,7 +34,6 @@ class Hint; } // namespace proto } // namespace optimization_guide - namespace previews { class HintsFetcher; @@ -49,7 +52,8 @@ optimization_guide::OptimizationGuideService* optimization_guide_service, const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner, const base::FilePath& profile_path, - PreviewsTopHostProvider* previews_top_host_provider); + PreviewsTopHostProvider* previews_top_host_provider, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~PreviewsOptimizationGuide() override; @@ -122,14 +126,9 @@ const GURL& document_url, const optimization_guide::proto::Hint* loaded_hint) const; - // Method to request OnePlatform client hints for user's sites with top - // engagement scores and creates a remote request using |hints_fetcher_| On - // request success OnOnePlatformHintsReceived callback will be called. - void GetOnePlatformClientHints(); - - // Called when the response from the OnePlatform Guide Service is handled and - // stored by the |hints_fetcher_|. received. - void OnOnePlatformHintsReceived(); + // Method to request new hints for user's sites based on + // engagement scores using |hints_fetcher_|. + void FetchHints(); // The OptimizationGuideService that this guide is listening to. Not owned. optimization_guide::OptimizationGuideService* optimization_guide_service_; @@ -152,13 +151,16 @@ // Used in testing to subscribe to an update event in this class. base::OnceClosure next_update_closure_; - // HintsFetcher handles the request to update Hints from OnePlatform Guide - // Service. + // HintsFetcher handles making the request for updated hints from the remote + // Optimization Guide Service. std::unique_ptr<HintsFetcher> hints_fetcher_; // TopHostProvider that this guide can query. Not owned. PreviewsTopHostProvider* previews_top_host_provider_ = nullptr; + // Used for fetching Hints by the Hints Fetcher. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + // Used to get |weak_ptr_| to self on the UI thread. base::WeakPtrFactory<PreviewsOptimizationGuide> ui_weak_ptr_factory_;
diff --git a/components/previews/content/previews_optimization_guide_unittest.cc b/components/previews/content/previews_optimization_guide_unittest.cc index 4867247..3b352c5 100644 --- a/components/previews/content/previews_optimization_guide_unittest.cc +++ b/components/previews/content/previews_optimization_guide_unittest.cc
@@ -30,6 +30,10 @@ #include "components/previews/core/previews_experiments.h" #include "components/previews/core/previews_features.h" #include "components/previews/core/previews_switches.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -67,15 +71,10 @@ bool remove_observer_called_; }; -// A test class implementation for unit testing previews_optimization_guide. -class TestPreviewsTopHostProvider : public PreviewsTopHostProvider { +// A mock class implementation for unittesting previews_optimization_guide. +class MockPreviewsTopHostProvider : public PreviewsTopHostProvider { public: - TestPreviewsTopHostProvider() {} - ~TestPreviewsTopHostProvider() override {} - - std::vector<std::string> GetTopHosts(size_t max_sites) const override { - return std::vector<std::string>(); - } + MOCK_CONST_METHOD1(GetTopHosts, std::vector<std::string>(size_t max_sites)); }; class PreviewsOptimizationGuideTest : public testing::Test { @@ -94,6 +93,10 @@ PreviewsOptimizationGuide* guide() { return guide_.get(); } + MockPreviewsTopHostProvider* top_host_provider() { + return previews_top_host_provider_.get(); + } + TestOptimizationGuideService* optimization_guide_service() { return optimization_guide_service_.get(); } @@ -112,13 +115,20 @@ if (guide_) { ResetGuide(); } + url_loader_factory_ = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_); + if (!previews_top_host_provider_) { + previews_top_host_provider_ = + std::make_unique<MockPreviewsTopHostProvider>(); + } optimization_guide_service_ = std::make_unique<TestOptimizationGuideService>( scoped_task_environment_.GetMainThreadTaskRunner()); guide_ = std::make_unique<PreviewsOptimizationGuide>( optimization_guide_service_.get(), scoped_task_environment_.GetMainThreadTaskRunner(), temp_dir(), - previews_top_host_provider_.get()); + previews_top_host_provider_.get(), url_loader_factory_); // Add observer is called after the HintCache is fully initialized, // indicating that the PreviewsOptimizationGuide is ready to process hints. @@ -191,7 +201,10 @@ std::unique_ptr<PreviewsOptimizationGuide> guide_; std::unique_ptr<TestOptimizationGuideService> optimization_guide_service_; - std::unique_ptr<TestPreviewsTopHostProvider> previews_top_host_provider_; + std::unique_ptr<MockPreviewsTopHostProvider> previews_top_host_provider_; + + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + network::TestURLLoaderFactory test_url_loader_factory_; // Flag set when the OnLoadOptimizationHints callback runs. This indicates // that MaybeLoadOptimizationHints() has completed its processing. @@ -1561,4 +1574,23 @@ EXPECT_TRUE(optimization_guide_service()->RemoveObserverCalled()); } +TEST_F(PreviewsOptimizationGuideTest, HintsFetcherEnabled) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature(features::kOptimizationHintsFetching); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + command_line->AppendSwitchASCII("optimization_guide_service_url", + "https://hintsserver.com"); + + EXPECT_CALL(*top_host_provider(), GetTopHosts(testing::_)); + CreateServiceAndGuide(); +} + +TEST_F(PreviewsOptimizationGuideTest, HintsFetcherDisabled) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature(features::kOptimizationHintsFetching); + + EXPECT_CALL(*top_host_provider(), GetTopHosts(testing::_)).Times(0); + CreateServiceAndGuide(); +} + } // namespace previews
diff --git a/components/previews/core/BUILD.gn b/components/previews/core/BUILD.gn index bc54e154..f27efa0 100644 --- a/components/previews/core/BUILD.gn +++ b/components/previews/core/BUILD.gn
@@ -30,6 +30,7 @@ "//base", "//components/blacklist/opt_out_blacklist", "//components/variations", + "//google_apis", "//net:net", "//third_party/re2", "//third_party/smhasher:murmurhash3",
diff --git a/components/previews/core/DEPS b/components/previews/core/DEPS index 776d207..1f73c3e 100644 --- a/components/previews/core/DEPS +++ b/components/previews/core/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+components/blacklist/opt_out_blacklist", "+components/variations", + "+google_apis", "+net", "+third_party/re2", "+third_party/smhasher"
diff --git a/components/previews/core/previews_experiments.cc b/components/previews/core/previews_experiments.cc index cc909ec..df686ed4 100644 --- a/components/previews/core/previews_experiments.cc +++ b/components/previews/core/previews_experiments.cc
@@ -15,6 +15,7 @@ #include "base/strings/string_util.h" #include "components/previews/core/previews_features.h" #include "components/previews/core/previews_switches.h" +#include "google_apis/google_api_keys.h" namespace previews { @@ -46,6 +47,8 @@ const char kNoScriptInflationPercent[] = "NoScriptInflationPercent"; const char kNoScriptInflationBytes[] = "NoScriptInflationBytes"; +const char kOptimizationGuideServiceURL[] = ""; + // Inflation parameters for estimating ResourceLoadingHints data savings. const char kResourceLoadingHintsInflationPercent[] = "ResourceLoadingHintsInflationPercent"; @@ -111,9 +114,10 @@ "max_hosts_in_blacklist", 100); } -size_t MaxOnePlatformUpdateHosts() { - return GetFieldTrialParamByFeatureAsInt(features::kPreviewsOnePlatformHints, - "max_oneplatform_update_hosts", 30); +size_t MaxHostsForOptimizationGuideServiceHintsFetch() { + return GetFieldTrialParamByFeatureAsInt( + features::kOptimizationHintsFetching, + "max_hosts_for_optimization_guide_service_hints_fetch", 30); } int PerHostBlackListOptOutThreshold() { @@ -224,6 +228,34 @@ return GURL("https://litepages.googlezip.net/"); } +std::string GetOptimizationGuideServiceAPIKey() { + // Command line override takes priority. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kOptimizationGuideServiceAPIKey)) { + return command_line->GetSwitchValueASCII( + switches::kOptimizationGuideServiceAPIKey); + } + + return google_apis::GetAPIKey(); +} + +GURL GetOptimizationGuideServiceURL() { + // Command line override takes priority. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kOptimizationGuideServiceURL)) { + // Assume the command line switch is correct and return it. + return GURL(command_line->GetSwitchValueASCII( + switches::kOptimizationGuideServiceURL)); + } + + std::string url = base::GetFieldTrialParamValueByFeature( + features::kOptimizationHintsFetching, "optimization_guide_service_url"); + if (url.empty()) + return GURL(kOptimizationGuideServiceURL); + + return GURL(url); +} + std::string LitePageRedirectPreviewExperiment() { return GetFieldTrialParamValueByFeature(features::kLitePageServerPreviews, "lite_page_preview_experiment"); @@ -332,8 +364,8 @@ return base::FeatureList::IsEnabled(features::kOptimizationHints); } -bool IsOnePlatformHintsEnabled() { - return base::FeatureList::IsEnabled(features::kPreviewsOnePlatformHints); +bool IsHintsFetchingEnabled() { + return base::FeatureList::IsEnabled(features::kOptimizationHintsFetching); } int NoScriptPreviewsInflationPercent() {
diff --git a/components/previews/core/previews_experiments.h b/components/previews/core/previews_experiments.h index 378e7abd..44f4f52 100644 --- a/components/previews/core/previews_experiments.h +++ b/components/previews/core/previews_experiments.h
@@ -68,9 +68,9 @@ // The maximum number of hosts allowed in the in memory black list. size_t MaxInMemoryHostsInBlackList(); -// The maximum number of hosts requested by the client to the OnePlatform -// Service. -size_t MaxOnePlatformUpdateHosts(); +// The maximum number of hosts allowed to be requested by the client to the +// remote Optimzation Guide Service. +size_t MaxHostsForOptimizationGuideServiceHintsFetch(); // The number of recent navigations that were opted out of for a given host that // would trigger that host to be blacklisted. @@ -100,6 +100,12 @@ // The host for Lite Page server previews. GURL GetLitePagePreviewsDomainURL(); +// The API key for the One Platform Optimization Guide Service. +std::string GetOptimizationGuideServiceAPIKey(); + +// The host for the One Platform Optimization Guide Service. +GURL GetOptimizationGuideServiceURL(); + // The duration of a single bypass for Lite Page Server Previews. base::TimeDelta LitePagePreviewsSingleBypassDuration(); @@ -171,9 +177,9 @@ // Whether server optimization hints are enabled. bool IsOptimizationHintsEnabled(); -// Returns true if the feature to fetch user-specific hints using -// the OnePlatform API is enabled. -bool IsOnePlatformHintsEnabled(); +// Returns true if the feature to fetch hints from the remote Optimization Guide +// Service is enabled. +bool IsHintsFetchingEnabled(); // For estimating NoScript data savings, this is the percentage factor to // multiple by the network bytes for inflating the original_bytes count.
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc index d847338d..8fe59cfa 100644 --- a/components/previews/core/previews_features.cc +++ b/components/previews/core/previews_features.cc
@@ -110,9 +110,9 @@ const base::Feature kPreviewsReloadsAreSoftOptOuts{ "PreviewsReloadsAreSoftOptOuts", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables using the OnePlatform Client Hints requests. -const base::Feature kPreviewsOnePlatformHints{ - "PreviewsOnePlatformHints", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables fetching optimization hints from a remote Optimization Guide Service. +const base::Feature kOptimizationHintsFetching{ + "OptimizationHintsFetching", base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace features } // namespace previews
diff --git a/components/previews/core/previews_features.h b/components/previews/core/previews_features.h index 7da9ed7..c49dc2c 100644 --- a/components/previews/core/previews_features.h +++ b/components/previews/core/previews_features.h
@@ -25,7 +25,7 @@ extern const base::Feature kHTTPSServerPreviewsUsingURLLoader; extern const base::Feature kDataSaverLiteModeRebranding; extern const base::Feature kPreviewsReloadsAreSoftOptOuts; -extern const base::Feature kPreviewsOnePlatformHints; +extern const base::Feature kOptimizationHintsFetching; } // namespace features } // namespace previews
diff --git a/components/previews/core/previews_switches.cc b/components/previews/core/previews_switches.cc index 455d84d..676be59 100644 --- a/components/previews/core/previews_switches.cc +++ b/components/previews/core/previews_switches.cc
@@ -33,6 +33,15 @@ // valid value to this switch causes Chrome startup to block on hints parsing. const char kHintsProtoOverride[] = "optimization_guide_hints_override"; +// Overrides the Optimization Guide Service URL that the HintsFetcher will +// request remote hints from. +const char kOptimizationGuideServiceURL[] = "optimization_guide_service_url"; + +// Overrides the Optimization Guide Service API Key for remote requests to be +// made. +const char kOptimizationGuideServiceAPIKey[] = + "optimization_guide_service_api_key"; + // Purges the hint cache store on startup, so that it's guaranteed to be using // fresh data. const char kPurgeHintCacheStore[] = "purge_hint_cache_store";
diff --git a/components/previews/core/previews_switches.h b/components/previews/core/previews_switches.h index b258e7db6..4fa8f396 100644 --- a/components/previews/core/previews_switches.h +++ b/components/previews/core/previews_switches.h
@@ -14,6 +14,8 @@ extern const char kIgnoreLitePageRedirectOptimizationBlacklist[]; extern const char kClearLitePageRedirectLocalBlacklist[]; extern const char kHintsProtoOverride[]; +extern const char kOptimizationGuideServiceURL[]; +extern const char kOptimizationGuideServiceAPIKey[]; extern const char kPurgeHintCacheStore[]; } // namespace switches
diff --git a/components/safe_browsing/common/BUILD.gn b/components/safe_browsing/common/BUILD.gn index b957213..21079fa 100644 --- a/components/safe_browsing/common/BUILD.gn +++ b/components/safe_browsing/common/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//chrome/common/features.gni") +import("//build/config/features.gni") import("//mojo/public/tools/bindings/mojom.gni") source_set("common") {
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn index 458c948..0f867360 100644 --- a/components/search_engines/BUILD.gn +++ b/components/search_engines/BUILD.gn
@@ -19,7 +19,6 @@ "keyword_web_data_service.h", "search_engine_data_type_controller.cc", "search_engine_data_type_controller.h", - "search_engine_type.h", "search_engines_pref_names.cc", "search_engines_pref_names.h", "search_engines_switches.cc", @@ -50,6 +49,7 @@ ] public_deps = [ + ":search_engine_type", "//base", "//components/google/core/browser", "//components/keyed_service/core", @@ -94,6 +94,12 @@ } } +source_set("search_engine_type") { + sources = [ + "search_engine_type.h", + ] +} + static_library("test_support") { testonly = true sources = [ @@ -162,6 +168,9 @@ source = "prepopulated_engines.json" schema_file = "prepopulated_engines_schema.json" namespace = "TemplateURLPrepopulateData" + deps = [ + ":search_engine_type", + ] } if (is_android) {
diff --git a/components/security_interstitials/core/browser/resources/interstitial_large.js b/components/security_interstitials/core/browser/resources/interstitial_large.js index eb4d75e..197e50cb 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_large.js +++ b/components/security_interstitials/core/browser/resources/interstitial_large.js
@@ -118,7 +118,7 @@ break; case 'LOOKALIKE': - // Primary button is hidden for lookalike URL interstitial. + sendCommand(SecurityInterstitialCommandId.CMD_DONT_PROCEED); break; default: @@ -130,7 +130,6 @@ if (lookalike) { var proceed_button = 'proceed-button'; var dont_proceed_link = 'dont-proceed-link'; - $('primary-button').classList.add(HIDDEN_CLASS); $(proceed_button).classList.remove(HIDDEN_CLASS); $(proceed_button).textContent =
diff --git a/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css b/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css index 56e60af..35aa09a 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css +++ b/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css
@@ -12,3 +12,13 @@ url(images/1x/info.png) 1x, url(images/2x/info.png) 2x); } + +.lookalike-url #primary-button { + float: none; + margin-right: 10px; +} + +[dir='rtl'] .lookalike-url #primary-button { + margin-left: 10px; + margin-right: 0; +}
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp index 581d17f..fa9a8ec5 100644 --- a/components/security_interstitials_strings.grdp +++ b/components/security_interstitials_strings.grdp
@@ -66,16 +66,19 @@ <!-- Lookalike URL warning --> <message name="IDS_LOOKALIKE_URL_TITLE" desc="Tab title. Context: the requested URL looks like a more popular URL."> - Did you mean? + Continue to <ph name="DOMAIN">$1<ex>example.com</ex></ph> </message> <message name="IDS_LOOKALIKE_URL_HEADING" desc="Large heading. Context: the error page that's shown when the requested URL looks like a more popular URL."> - Did you mean <a href="#" id="dont-proceed-link"><ph name="DOMAIN">$1<ex>example.com</ex></ph></a>? + Continue to <a href="#" id="dont-proceed-link"><ph name="DOMAIN">$1<ex>example.com</ex></ph></a> </message> - <message name="IDS_LOOKALIKE_URL_IGNORE" desc="Button text. Context: the error page that's shown when the requested URL looks like a more popular URL. This button continues on to the originally-requested URL."> + <message name="IDS_LOOKALIKE_URL_IGNORE" desc="Button text. Context: the error page that's shown when the requested URL looks like a more popular URL. This button dismisses the interstitial and navigates to the originally-requested URL."> Ignore </message> + <message name="IDS_LOOKALIKE_URL_CONTINUE" desc="Button text. Context: the error page that's shown when the requested URL looks like a more popular URL. This button dismisses the interstitial and navigates to the suggested (safe) URL."> + Continue + </message> <message name="IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL looks like a more popular URL."> - The link you originally opened is unusual + The link you opened goes to a site you don't usually visit. It might be trying to confuse you. </message> <!-- Clock errors -->
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_CONTINUE.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_CONTINUE.png.sha1 new file mode 100644 index 0000000..eb038a7 --- /dev/null +++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_CONTINUE.png.sha1
@@ -0,0 +1 @@ +53e9164a74d630be57a73a0c0b642354a6a97ee1 \ No newline at end of file
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING.png.sha1 index 981ff93..eb038a7 100644 --- a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING.png.sha1 +++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_HEADING.png.sha1
@@ -1 +1 @@ -fbe2d6cd6009517b71a7413b08b6419c5e20674d \ No newline at end of file +53e9164a74d630be57a73a0c0b642354a6a97ee1 \ No newline at end of file
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_IGNORE.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_IGNORE.png.sha1 index 981ff93..eb038a7 100644 --- a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_IGNORE.png.sha1 +++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_IGNORE.png.sha1
@@ -1 +1 @@ -fbe2d6cd6009517b71a7413b08b6419c5e20674d \ No newline at end of file +53e9164a74d630be57a73a0c0b642354a6a97ee1 \ No newline at end of file
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1 index 981ff93..eb038a7 100644 --- a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1 +++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1
@@ -1 +1 @@ -fbe2d6cd6009517b71a7413b08b6419c5e20674d \ No newline at end of file +53e9164a74d630be57a73a0c0b642354a6a97ee1 \ No newline at end of file
diff --git a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_TITLE.png.sha1 b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_TITLE.png.sha1 index 981ff93..eb038a7 100644 --- a/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_TITLE.png.sha1 +++ b/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_TITLE.png.sha1
@@ -1 +1 @@ -fbe2d6cd6009517b71a7413b08b6419c5e20674d \ No newline at end of file +53e9164a74d630be57a73a0c0b642354a6a97ee1 \ No newline at end of file
diff --git a/components/services/leveldb/env_mojo.cc b/components/services/leveldb/env_mojo.cc index fc656fe..86bbf05 100644 --- a/components/services/leveldb/env_mojo.cc +++ b/components/services/leveldb/env_mojo.cc
@@ -18,6 +18,10 @@ #include "third_party/leveldatabase/chromium_logger.h" #include "third_party/leveldatabase/src/include/leveldb/status.h" +#if defined(OS_WIN) && defined(DeleteFile) +#undef DeleteFile +#endif + using leveldb_env::UMALogger; namespace leveldb {
diff --git a/components/services/leveldb/env_mojo.h b/components/services/leveldb/env_mojo.h index 9748900cf..362c3d9a 100644 --- a/components/services/leveldb/env_mojo.h +++ b/components/services/leveldb/env_mojo.h
@@ -8,11 +8,18 @@ #include <string> #include <vector> +#include "build/build_config.h" #include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "components/services/leveldb/leveldb_mojo_proxy.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/include/leveldb/env.h" +#if defined(OS_WIN) && defined(DeleteFile) +// See comment in env.h. +#undef DeleteFile +#define ENV_MOJO_DELETEFILE_UNDEFINED +#endif // defined(OS_WIN) && defined(DeleteFile) + namespace leveldb { class MojoRetrierProvider { @@ -87,4 +94,9 @@ } // namespace leveldb +// Redefine DeleteFile if necessary. +#if defined(OS_WIN) && defined(ENV_MOJO_DELETEFILE_UNDEFINED) +#define DeleteFile DeleteFileW +#endif + #endif // COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index cc33136e..fc683c3 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc
@@ -36,7 +36,10 @@ account_consistency_(account_consistency), weak_pointer_factory_(this) {} -SigninManager::~SigninManager() {} +SigninManager::~SigninManager() { + token_service()->RemoveObserver(this); + local_state_pref_registrar_.RemoveAll(); +} void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) { if (observer_ != nullptr) { @@ -185,12 +188,6 @@ token_service()->AddObserver(this); } -void SigninManager::Shutdown() { - token_service()->RemoveObserver(this); - local_state_pref_registrar_.RemoveAll(); - SigninManagerBase::Shutdown(); -} - void SigninManager::OnGoogleServicesUsernamePatternChanged() { if (IsAuthenticated() && !IsAllowedUsername(GetAuthenticatedAccountInfo().email)) {
diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/signin_manager.h index 44987db..1b5ebf6 100644 --- a/components/signin/core/browser/signin_manager.h +++ b/components/signin/core/browser/signin_manager.h
@@ -109,8 +109,6 @@ void FinalizeInitBeforeLoadingRefreshTokens( PrefService* local_state) override; - void Shutdown() override; - // Signs a user in. SigninManager assumes that |username| can be used to look // up the corresponding account_id and gaia_id for this email. void SignIn(const std::string& username);
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/signin_manager_base.h index fdd331aa..5344bd1b 100644 --- a/components/signin/core/browser/signin_manager_base.h +++ b/components/signin/core/browser/signin_manager_base.h
@@ -31,7 +31,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/observer_list.h" -#include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_member.h" #include "components/signin/core/browser/account_info.h" @@ -43,7 +42,7 @@ class ProfileOAuth2TokenService; class SigninClient; -class SigninManagerBase : public KeyedService { +class SigninManagerBase { public: class Observer { public: @@ -82,7 +81,7 @@ public: #endif - ~SigninManagerBase() override; + virtual ~SigninManagerBase(); // Registers per-profile prefs. static void RegisterProfilePrefs(PrefRegistrySimple* registry);
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/signin_manager_unittest.cc index 3c0c26f..16e61c1 100644 --- a/components/signin/core/browser/signin_manager_unittest.cc +++ b/components/signin/core/browser/signin_manager_unittest.cc
@@ -85,8 +85,7 @@ ~SigninManagerTest() override { if (manager_) { - manager_->ClearObserver(); - manager_->Shutdown(); + ShutDownManager(); } token_service_.Shutdown(); test_signin_client_.Shutdown(); @@ -124,7 +123,6 @@ void ShutDownManager() { DCHECK(manager_); manager_->ClearObserver(); - manager_->Shutdown(); manager_.reset(); }
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index f73f036..92c6f52 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -146,6 +146,8 @@ "driver/startup_controller.h", "driver/sync_api_component_factory.cc", "driver/sync_api_component_factory.h", + "driver/sync_auth_manager.cc", + "driver/sync_auth_manager.h", "driver/sync_auth_util.cc", "driver/sync_auth_util.h", "driver/sync_client.cc", @@ -464,6 +466,9 @@ "model_impl/syncable_service_based_bridge.cc", "model_impl/syncable_service_based_bridge.h", "nigori/keystore_keys_handler.h", + "nigori/nigori_local_change_processor.h", + "nigori/nigori_model_type_processor.cc", + "nigori/nigori_model_type_processor.h", "nigori/nigori_sync_bridge.h", "protocol/proto_enum_conversions.cc", "protocol/proto_enum_conversions.h", @@ -872,6 +877,7 @@ "driver/model_type_controller_unittest.cc", "driver/shared_change_processor_unittest.cc", "driver/startup_controller_unittest.cc", + "driver/sync_auth_manager_unittest.cc", "driver/sync_service_utils_unittest.cc", "driver/sync_session_durations_metrics_recorder_unittest.cc", "driver/sync_stopped_reporter_unittest.cc",
diff --git a/components/sync/driver/glue/sync_backend_host_core.cc b/components/sync/driver/glue/sync_backend_host_core.cc index e22ec85d..59942dd9 100644 --- a/components/sync/driver/glue/sync_backend_host_core.cc +++ b/components/sync/driver/glue/sync_backend_host_core.cc
@@ -248,6 +248,34 @@ sync_manager_->SetInvalidatorEnabled(state == INVALIDATIONS_ENABLED); } +bool SyncBackendHostCore::ShouldIgnoreRedundantInvalidation( + const Invalidation& invalidation, + ModelType type) { + bool fcm_invalidation = + (base::FeatureList::IsEnabled( + invalidation::switches::kFCMInvalidations) && + base::FeatureList::IsEnabled( + invalidation::switches::kFCMInvalidationsForSyncDontCheckVersion)); + bool redundant_invalidation = false; + auto last_invalidation = last_invalidation_versions_.find(type); + if (!invalidation.is_unknown_version() && + last_invalidation != last_invalidation_versions_.end() && + invalidation.version() <= last_invalidation->second) { + DVLOG(1) << "Ignoring redundant invalidation for " + << ModelTypeToString(type) << " with version " + << invalidation.version() << ", last seen version was " + << last_invalidation->second; + redundant_invalidation = true; + UMA_HISTOGRAM_ENUMERATION("Sync.RedundantInvalidationPerModelType", type, + static_cast<int>(syncer::MODEL_TYPE_COUNT)); + } else { + UMA_HISTOGRAM_ENUMERATION("Sync.NonRedundantInvalidationPerModelType", type, + static_cast<int>(syncer::MODEL_TYPE_COUNT)); + } + + return !fcm_invalidation && redundant_invalidation; +} + void SyncBackendHostCore::DoOnIncomingInvalidation( const ObjectIdInvalidationMap& invalidation_map) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -264,16 +292,10 @@ SingleObjectInvalidationSet invalidation_set = invalidation_map.ForObject(object_id); for (Invalidation invalidation : invalidation_set) { - auto last_invalidation = last_invalidation_versions_.find(type); - if (!invalidation.is_unknown_version() && - last_invalidation != last_invalidation_versions_.end() && - invalidation.version() <= last_invalidation->second) { - DVLOG(1) << "Ignoring redundant invalidation for " - << ModelTypeToString(type) << " with version " - << invalidation.version() << ", last seen version was " - << last_invalidation->second; + if (ShouldIgnoreRedundantInvalidation(invalidation, type)) { continue; } + if (!is_grouped && !invalidation.is_unknown_version()) { UMA_HISTOGRAM_ENUMERATION("Sync.NonGroupedInvalidationKnownVersion", ModelTypeToHistogramInt(type),
diff --git a/components/sync/driver/glue/sync_backend_host_core.h b/components/sync/driver/glue/sync_backend_host_core.h index 097fef7f..7753dc1e 100644 --- a/components/sync/driver/glue/sync_backend_host_core.h +++ b/components/sync/driver/glue/sync_backend_host_core.h
@@ -18,6 +18,7 @@ #include "base/sequence_checker.h" #include "base/timer/timer.h" #include "base/trace_event/memory_dump_provider.h" +#include "components/invalidation/impl/invalidation_switches.h" #include "components/invalidation/public/invalidation.h" #include "components/sync/base/cancelation_signal.h" #include "components/sync/base/system_encryptor.h" @@ -182,6 +183,11 @@ ~SyncBackendHostCore() override; + // For the olg tango based invalidations method returns true if the + // invalidation has version lower than last seen version for this datatype. + bool ShouldIgnoreRedundantInvalidation(const Invalidation& invalidation, + ModelType Type); + // Invoked when initialization of syncapi is complete and we can start // our timer. // This must be called from the thread on which SaveChanges is intended to
diff --git a/components/browser_sync/sync_auth_manager.cc b/components/sync/driver/sync_auth_manager.cc similarity index 99% rename from components/browser_sync/sync_auth_manager.cc rename to components/sync/driver/sync_auth_manager.cc index 7bfa58f..d6d0621 100644 --- a/components/browser_sync/sync_auth_manager.cc +++ b/components/sync/driver/sync_auth_manager.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/browser_sync/sync_auth_manager.h" +#include "components/sync/driver/sync_auth_manager.h" #include <utility> @@ -16,7 +16,7 @@ #include "google_apis/gaia/gaia_constants.h" #include "services/identity/public/cpp/access_token_fetcher.h" -namespace browser_sync { +namespace syncer { namespace { @@ -463,4 +463,4 @@ credentials_changed_callback_.Run(); } -} // namespace browser_sync +} // namespace syncer
diff --git a/components/browser_sync/sync_auth_manager.h b/components/sync/driver/sync_auth_manager.h similarity index 96% rename from components/browser_sync/sync_auth_manager.h rename to components/sync/driver/sync_auth_manager.h index fa97a6f..c3cd9bd 100644 --- a/components/browser_sync/sync_auth_manager.h +++ b/components/sync/driver/sync_auth_manager.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_BROWSER_SYNC_SYNC_AUTH_MANAGER_H_ -#define COMPONENTS_BROWSER_SYNC_SYNC_AUTH_MANAGER_H_ +#ifndef COMPONENTS_SYNC_DRIVER_SYNC_AUTH_MANAGER_H_ +#define COMPONENTS_SYNC_DRIVER_SYNC_AUTH_MANAGER_H_ #include <memory> #include <string> @@ -26,10 +26,8 @@ } namespace syncer { -struct SyncCredentials; -} // namespace syncer -namespace browser_sync { +struct SyncCredentials; // SyncAuthManager tracks the account to be used for Sync and its authentication // state. Note that this account may or may not be the primary account (as per @@ -180,6 +178,6 @@ DISALLOW_COPY_AND_ASSIGN(SyncAuthManager); }; -} // namespace browser_sync +} // namespace syncer -#endif // COMPONENTS_BROWSER_SYNC_SYNC_AUTH_MANAGER_H_ +#endif // COMPONENTS_SYNC_DRIVER_SYNC_AUTH_MANAGER_H_
diff --git a/components/browser_sync/sync_auth_manager_unittest.cc b/components/sync/driver/sync_auth_manager_unittest.cc similarity index 99% rename from components/browser_sync/sync_auth_manager_unittest.cc rename to components/sync/driver/sync_auth_manager_unittest.cc index e0509f7..fc564a35 100644 --- a/components/browser_sync/sync_auth_manager_unittest.cc +++ b/components/sync/driver/sync_auth_manager_unittest.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/browser_sync/sync_auth_manager.h" +#include "components/sync/driver/sync_auth_manager.h" #include "base/bind_helpers.h" #include "base/run_loop.h" @@ -19,7 +19,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -namespace browser_sync { +namespace syncer { namespace { @@ -737,4 +737,4 @@ } // namespace -} // namespace browser_sync +} // namespace syncer
diff --git a/components/sync/nigori/DEPS b/components/sync/nigori/DEPS index 8117313..b9dd7f7f 100644 --- a/components/sync/nigori/DEPS +++ b/components/sync/nigori/DEPS
@@ -1,3 +1,5 @@ include_rules = [ + "+components/sync/engine", "+components/sync/model", + "+components/sync/protocol", ]
diff --git a/components/sync/nigori/nigori_local_change_processor.h b/components/sync/nigori/nigori_local_change_processor.h new file mode 100644 index 0000000..bc8476ea --- /dev/null +++ b/components/sync/nigori/nigori_local_change_processor.h
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_NIGORI_NIGORI_LOCAL_CHANGE_PROCESSOR_H_ +#define COMPONENTS_SYNC_NIGORI_NIGORI_LOCAL_CHANGE_PROCESSOR_H_ + +#include <memory> +#include <utility> + +#include "base/macros.h" +#include "components/sync/protocol/entity_metadata.pb.h" +#include "components/sync/protocol/model_type_state.pb.h" + +namespace syncer { + +class NigoriSyncBridge; +struct EntityData; + +// Interface analogous to ModelTypeChangeProcessor for Nigori, used to propagate +// local changes from the bridge to the processor. +class NigoriLocalChangeProcessor { + public: + NigoriLocalChangeProcessor() = default; + + virtual ~NigoriLocalChangeProcessor() = default; + + // The Nigori model is expected to call this method as soon as possible during + // initialization, and must be called before invoking Put(). + virtual void ModelReadyToSync( + NigoriSyncBridge* bridge, + std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> + nigori_metadata) = 0; + + // Informs the Nigori processor of a new or updated Nigori entity. + virtual void Put(std::unique_ptr<EntityData> entity_data) = 0; + + // Returns both the entity metadata and model type state such that the Nigori + // model takes care of persisting them. + virtual std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> + GetMetadata() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(NigoriLocalChangeProcessor); +}; + +} // namespace syncer + +#endif // COMPONENTS_SYNC_NIGORI_NIGORI_LOCAL_CHANGE_PROCESSOR_H_
diff --git a/components/sync/nigori/nigori_model_type_processor.cc b/components/sync/nigori/nigori_model_type_processor.cc new file mode 100644 index 0000000..2e363c4 --- /dev/null +++ b/components/sync/nigori/nigori_model_type_processor.cc
@@ -0,0 +1,102 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/sync/nigori/nigori_model_type_processor.h" + +#include "components/sync/engine/commit_queue.h" + +namespace syncer { + +NigoriModelTypeProcessor::NigoriModelTypeProcessor() : bridge_(nullptr) {} + +NigoriModelTypeProcessor::~NigoriModelTypeProcessor() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void NigoriModelTypeProcessor::ConnectSync( + std::unique_ptr<CommitQueue> worker) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::DisconnectSync() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::GetLocalChanges( + size_t max_entries, + GetLocalChangesCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::OnCommitCompleted( + const sync_pb::ModelTypeState& type_state, + const CommitResponseDataList& response_list) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::OnUpdateReceived( + const sync_pb::ModelTypeState& type_state, + const UpdateResponseDataList& updates) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::OnSyncStarting( + const DataTypeActivationRequest& request, + StartCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::OnSyncStopping( + SyncStopMetadataFate metadata_fate) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::GetAllNodesForDebugging( + AllNodesCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::GetStatusCountersForDebugging( + StatusCountersCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::RecordMemoryUsageAndCountsHistograms() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::ModelReadyToSync( + NigoriSyncBridge* bridge, + std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> + nigori_metadata) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(bridge); + bridge_ = bridge; + NOTIMPLEMENTED(); +} + +void NigoriModelTypeProcessor::Put(std::unique_ptr<EntityData> entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> +NigoriModelTypeProcessor::GetMetadata() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata>( + sync_pb::ModelTypeState(), sync_pb::EntityMetadata()); +} + +} // namespace syncer
diff --git a/components/sync/nigori/nigori_model_type_processor.h b/components/sync/nigori/nigori_model_type_processor.h new file mode 100644 index 0000000..4297f77 --- /dev/null +++ b/components/sync/nigori/nigori_model_type_processor.h
@@ -0,0 +1,66 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SYNC_NIGORI_NIGORI_MODEL_TYPE_PROCESSOR_H_ +#define COMPONENTS_SYNC_NIGORI_NIGORI_MODEL_TYPE_PROCESSOR_H_ + +#include <memory> +#include <utility> + +#include "base/macros.h" +#include "components/sync/engine/model_type_processor.h" +#include "components/sync/model/model_type_controller_delegate.h" +#include "components/sync/nigori/nigori_local_change_processor.h" +#include "components/sync/protocol/entity_metadata.pb.h" +#include "components/sync/protocol/model_type_state.pb.h" + +namespace syncer { + +class NigoriSyncBridge; + +class NigoriModelTypeProcessor : public ModelTypeProcessor, + public ModelTypeControllerDelegate, + public NigoriLocalChangeProcessor { + public: + NigoriModelTypeProcessor(); + ~NigoriModelTypeProcessor() override; + + // ModelTypeProcessor implementation. + void ConnectSync(std::unique_ptr<CommitQueue> worker) override; + void DisconnectSync() override; + void GetLocalChanges(size_t max_entries, + GetLocalChangesCallback callback) override; + void OnCommitCompleted(const sync_pb::ModelTypeState& type_state, + const CommitResponseDataList& response_list) override; + void OnUpdateReceived(const sync_pb::ModelTypeState& type_state, + const UpdateResponseDataList& updates) override; + + // ModelTypeControllerDelegate implementation. + void OnSyncStarting(const DataTypeActivationRequest& request, + StartCallback callback) override; + void OnSyncStopping(SyncStopMetadataFate metadata_fate) override; + void GetAllNodesForDebugging(AllNodesCallback callback) override; + void GetStatusCountersForDebugging(StatusCountersCallback callback) override; + void RecordMemoryUsageAndCountsHistograms() override; + + // NigoriLocalChangeProcessor implementation. + void ModelReadyToSync( + NigoriSyncBridge* bridge, + std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> + nigori_metadata) override; + void Put(std::unique_ptr<EntityData> entity_data) override; + std::pair<sync_pb::ModelTypeState, sync_pb::EntityMetadata> GetMetadata() + override; + + private: + NigoriSyncBridge* bridge_; + + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(NigoriModelTypeProcessor); +}; + +} // namespace syncer + +#endif // COMPONENTS_SYNC_NIGORI_NIGORI_MODEL_TYPE_PROCESSOR_H_
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc index 4a2fe065..59de63d 100644 --- a/components/sync_preferences/pref_model_associator.cc +++ b/components/sync_preferences/pref_model_associator.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/auto_reset.h" +#include "base/feature_list.h" #include "base/json/json_reader.h" #include "base/json/json_string_value_serializer.h" #include "base/location.h" @@ -37,6 +38,14 @@ namespace { +// Enables deleting a pref from Sync if the the user clears it on a client. If +// this feature is disabled, clearing a pref will cause setting it to the +// default value instead of deleting it from sync. This has been introduced in +// M75 as a safety mechanism, should be removed in M76 if no issues are +// observed. +const base::Feature kSyncDeleteClearedPref{"SyncDeleteClearedPrefs", + base::FEATURE_ENABLED_BY_DEFAULT}; + const sync_pb::PreferenceSpecifics& GetSpecifics(const syncer::SyncData& pref) { DCHECK(pref.GetDataType() == syncer::PREFERENCES || pref.GetDataType() == syncer::PRIORITY_PREFERENCES); @@ -515,14 +524,23 @@ // take care syncing any new data. InitPrefAndAssociate(syncer::SyncData(), name, &changes); } else { - // We are already syncing this preference, just update it's sync node. + // We are already syncing this preference, just update or delete its sync + // node. syncer::SyncData sync_data; if (!CreatePrefSyncData(name, *preference->GetValue(), &sync_data)) { LOG(ERROR) << "Failed to update preference."; return; } - changes.push_back(syncer::SyncChange( - FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data)); + if (!base::FeatureList::IsEnabled(kSyncDeleteClearedPref) || + pref_accessor_->GetPreferenceState(type_, name).persisted_value) { + // If the pref was updated, update it. + changes.push_back(syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data)); + } else { + // Otherwise, the pref must have been cleared and hence delete it. + changes.push_back(syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_DELETE, sync_data)); + } } syncer::SyncError error =
diff --git a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png.sha1 b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png.sha1 index aee888a..328f07c 100644 --- a/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png.sha1 +++ b/components/test/data/payments/render_tests/PaymentRequestFreeShippingTest.free_shipping.Nexus_5-19.png.sha1
@@ -1 +1 @@ -ad05b6acc396f72e22a8839cbece4d87408f9500 \ No newline at end of file +cc10274c55805d69434892604346c1bcdf1fc74f \ No newline at end of file
diff --git a/components/update_client/update_query_params.cc b/components/update_client/update_query_params.cc index 7e4b01a..119e71a 100644 --- a/components/update_client/update_query_params.cc +++ b/components/update_client/update_query_params.cc
@@ -55,6 +55,8 @@ "mips64el"; #elif defined(__mips__) "mipsel"; +#elif defined(__powerpc64__) + "ppc64"; #else #error "unknown arch" #endif @@ -127,6 +129,8 @@ return "mips32"; #elif defined(ARCH_CPU_MIPS64EL) return "mips64"; +#elif defined(ARCH_CPU_PPC64) + return "ppc64"; #else // NOTE: when adding new values here, please remember to update the // comment in the .h file about possible return values from this function.
diff --git a/components/update_client/update_query_params.h b/components/update_client/update_query_params.h index a35e4c3..e315e14 100644 --- a/components/update_client/update_query_params.h +++ b/components/update_client/update_query_params.h
@@ -45,7 +45,7 @@ // Returns the value we use for the "nacl_arch" parameter. Note that this may // be different from the "arch" parameter above (e.g. one may be 32-bit and // the other 64-bit). Possible return values include: "x86-32", "x86-64", - // "arm", and "mips32". + // "arm", "mips32", and "ppc64". static const char* GetNaclArch(); // Returns the current version of Chrome/Chromium.
diff --git a/components/url_formatter/top_domains/BUILD.gn b/components/url_formatter/top_domains/BUILD.gn index 04dcc16..26b55ad 100644 --- a/components/url_formatter/top_domains/BUILD.gn +++ b/components/url_formatter/top_domains/BUILD.gn
@@ -127,14 +127,13 @@ # This empty public is intentional to remove unnecessary build dependency. public = [] - visibility = [ ":top500_domains_header" ] - sources = [ "$target_gen_dir/top500-domains-inc.cc", ] deps = [ ":generate_top_domains_for_edit_distance", + ":top500_domains_header", ] } @@ -142,7 +141,4 @@ sources = [ "top500_domains.h", ] - deps = [ - ":top500_domains", - ] }
diff --git a/components/variations/field_trial_config/field_trial_testing_config_schema.json b/components/variations/field_trial_config/field_trial_testing_config_schema.json index 51bfe19..09e3a4b0 100644 --- a/components/variations/field_trial_config/field_trial_testing_config_schema.json +++ b/components/variations/field_trial_config/field_trial_testing_config_schema.json
@@ -27,6 +27,13 @@ "contents": {"type": "enum", "ctype": "Study::Platform"} }, { + "field": "is_low_end_device", + "type": "enum", + "ctype": "Study::OptionalBool", + "default": "Study::OPTIONAL_BOOL_MISSING", + "optional": "True" + }, + { "field": "params", "type": "array", "contents": {
diff --git a/components/variations/field_trial_config/field_trial_util.cc b/components/variations/field_trial_config/field_trial_util.cc index a77d5c8e..cb2fd6a 100644 --- a/components/variations/field_trial_config/field_trial_util.cc +++ b/components/variations/field_trial_config/field_trial_util.cc
@@ -17,6 +17,7 @@ #include "base/metrics/field_trial.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" +#include "base/system/sys_info.h" #include "components/variations/field_trial_config/fieldtrial_testing_config.h" #include "components/variations/variations_associated_data.h" #include "net/base/escape.h" @@ -33,6 +34,19 @@ return false; } +// Returns true if the experiment config is has different value for +// is_low_end_device than the current system value for this. +// If experiment has is_low_end_device missing, then it is False. +bool HasDeviceLevelMismatch(const FieldTrialTestingExperiment& experiment) { + if (experiment.is_low_end_device == Study::OPTIONAL_BOOL_MISSING) { + return false; + } + if (base::SysInfo::IsLowEndDevice()) { + return experiment.is_low_end_device == Study::OPTIONAL_BOOL_FALSE; + } + return experiment.is_low_end_device == Study::OPTIONAL_BOOL_TRUE; +} + void AssociateParamsFromExperiment( const std::string& study_name, const FieldTrialTestingExperiment& experiment, @@ -71,7 +85,11 @@ // - Out of the experiments which match this platform: // - If there is a forcing flag for any experiment, choose the first such // experiment. -// - Otherwise, choose the first experiment. +// - Otherwise, If running on low_end_device and the config specify +// a different experiment group for low end devices then pick that. +// - Otherwise, If running on non low_end_device and the config specify +// a different experiment group for non low_end_device then pick that. +// - Otherwise, select the first experiment. // - If no experiments match this platform, do not associate any of them. void ChooseExperiment(const FieldTrialTestingStudy& study, base::FeatureList* feature_list, @@ -81,7 +99,7 @@ for (size_t i = 0; i < study.experiments_size; ++i) { const FieldTrialTestingExperiment* experiment = study.experiments + i; if (HasPlatform(*experiment, platform)) { - if (!chosen_experiment) + if (!chosen_experiment && !HasDeviceLevelMismatch(*experiment)) chosen_experiment = experiment; if (experiment->forcing_flag &&
diff --git a/components/variations/field_trial_config/field_trial_util_unittest.cc b/components/variations/field_trial_config/field_trial_util_unittest.cc index 3cea9ba..8cb2b9c 100644 --- a/components/variations/field_trial_config/field_trial_util_unittest.cc +++ b/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -68,16 +68,16 @@ const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_0[] = {{"x", "1"}, {"y", "2"}}; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", &platform, 1, array_kFieldTrialConfig_params_0, 2, - nullptr, 0, nullptr, 0, nullptr}, + {"TestGroup1", &platform, 1, Study::OPTIONAL_BOOL_MISSING, + array_kFieldTrialConfig_params_0, 2, nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_1[] = {{"x", "3"}, {"y", "4"}}; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", &platform, 1, array_kFieldTrialConfig_params_0, 2, - nullptr, 0, nullptr, 0, nullptr}, - {"TestGroup2-2", &platform, 1, array_kFieldTrialConfig_params_1, 2, - nullptr, 0, nullptr, 0, nullptr}, + {"TestGroup2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, + array_kFieldTrialConfig_params_0, 2, nullptr, 0, nullptr, 0, nullptr}, + {"TestGroup2-2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, + array_kFieldTrialConfig_params_1, 2, nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1}, @@ -126,7 +126,7 @@ for (size_t i = 0; i < base::size(all_platforms); ++i) { const Study::Platform platform = all_platforms[i]; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, + {"TestGroup", &platform, 1, Study::OPTIONAL_BOOL_MISSING, array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { @@ -158,8 +158,8 @@ const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", &platform, 1, array_kFieldTrialConfig_params, 2, nullptr, 0, - nullptr, 0, nullptr}, + {"TestGroup", &platform, 1, Study::OPTIONAL_BOOL_MISSING, + array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -187,8 +187,8 @@ const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {{"x", "1"}, {"y", "2"}}; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = { - {"TestGroup", platforms, 2, array_kFieldTrialConfig_params, 2, nullptr, 0, - nullptr, 0, nullptr}, + {"TestGroup", platforms, 2, Study::OPTIONAL_BOOL_MISSING, + array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = {{"TestTrial", array_kFieldTrialConfig_experiments, 1}}; @@ -223,14 +223,14 @@ const Study::Platform platform = Study::PLATFORM_LINUX; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", &platform, 1, nullptr, 0, enable_features, 2, nullptr, 0, - nullptr}, + {"TestGroup1", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + enable_features, 2, nullptr, 0, nullptr}, }; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", &platform, 1, nullptr, 0, nullptr, 0, disable_features, 2, - nullptr}, - {"TestGroup2-2", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - nullptr}, + {"TestGroup2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, disable_features, 2, nullptr}, + {"TestGroup2-2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, nullptr}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { @@ -263,21 +263,21 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) { const Study::Platform platform = Study::PLATFORM_LINUX; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = { - {"TestGroup1", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, nullptr} - }; + {"TestGroup1", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, nullptr}}; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = { - {"TestGroup2", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - nullptr}, - {"ForcedGroup2", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - "flag-2"}, + {"TestGroup2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, nullptr}, + {"ForcedGroup2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, "flag-2"}, }; const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { - {"TestGroup3", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - nullptr}, - {"ForcedGroup3", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - "flag-3"}, - {"ForcedGroup3-2", &platform, 1, nullptr, 0, nullptr, 0, nullptr, 0, - "flag-3-2"}, + {"TestGroup3", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, nullptr}, + {"ForcedGroup3", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, "flag-3"}, + {"ForcedGroup3-2", &platform, 1, Study::OPTIONAL_BOOL_MISSING, nullptr, 0, + nullptr, 0, nullptr, 0, "flag-3-2"}, }; const FieldTrialTestingStudy array_kFieldTrialConfig_studies[] = { {"TestTrial1", array_kFieldTrialConfig_experiments_0, 1},
diff --git a/components/variations/proto/study.proto b/components/variations/proto/study.proto index 0993802..00f768c 100644 --- a/components/variations/proto/study.proto +++ b/components/variations/proto/study.proto
@@ -205,6 +205,16 @@ KIOSK = 3; } + // Enum to pass as optional bool. + enum OptionalBool { + // Neither True nor False. (For cases like missing / unset / default etc.) + OPTIONAL_BOOL_MISSING = 0; + // Explicit True. + OPTIONAL_BOOL_TRUE = 1; + // Explicit False. + OPTIONAL_BOOL_FALSE = 2; + } + // Filtering criteria specifying whether this study is applicable to a given // Chrome instance. //
diff --git a/components/viz/common/display/renderer_settings.h b/components/viz/common/display/renderer_settings.h index ce4fb4c..78041fcb 100644 --- a/components/viz/common/display/renderer_settings.h +++ b/components/viz/common/display/renderer_settings.h
@@ -7,7 +7,10 @@ #include <stddef.h> +#include <vector> + #include "build/build_config.h" +#include "components/viz/common/display/overlay_strategy.h" #include "components/viz/common/viz_common_export.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/size.h" @@ -49,6 +52,12 @@ gfx::ColorSpace color_space; #endif + +#if defined(USE_OZONE) + // A list of overlay strategies that should be tried. If the list is empty + // then overlays aren't supported. + std::vector<OverlayStrategy> overlay_strategies; +#endif }; } // namespace viz
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index 344c66d..a85c4bb 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -95,24 +95,26 @@ bool IsUsingSkiaRenderer() { // We require OOP-D everywhere but WebView. + bool enabled = base::FeatureList::IsEnabled(kUseSkiaRenderer); #if !defined(OS_ANDROID) - if (!IsVizDisplayCompositorEnabled()) { + if (enabled && !IsVizDisplayCompositorEnabled()) { DLOG(ERROR) << "UseSkiaRenderer requires VizDisplayCompositor."; return false; } #endif // !defined(OS_ANDROID) - return base::FeatureList::IsEnabled(kUseSkiaRenderer); + return enabled; } bool IsUsingSkiaRendererNonDDL() { // We require OOP-D everywhere but WebView. + bool enabled = base::FeatureList::IsEnabled(kUseSkiaRendererNonDDL); #if !defined(OS_ANDROID) - if (!IsVizDisplayCompositorEnabled()) { + if (enabled && !IsVizDisplayCompositorEnabled()) { DLOG(ERROR) << "UseSkiaRendererNonDDL requires VizDisplayCompositor."; return false; } #endif // !defined(OS_ANDROID) - return base::FeatureList::IsEnabled(kUseSkiaRendererNonDDL); + return enabled; } bool IsRecordingSkPicture() {
diff --git a/components/viz/common/gl_helper.cc b/components/viz/common/gl_helper.cc index cbd11c7..1637b30 100644 --- a/components/viz/common/gl_helper.cc +++ b/components/viz/common/gl_helper.cc
@@ -24,8 +24,6 @@ #include "components/viz/common/gl_helper_scaling.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/common/mailbox.h" -#include "gpu/command_buffer/common/mailbox_holder.h" #include "third_party/skia/include/core/SkRegion.h" #include "third_party/skia/include/gpu/GrTypes.h" #include "ui/gfx/geometry/point.h" @@ -147,11 +145,6 @@ flush_(gl) {} ~CopyTextureToImpl() { CancelRequests(); } - GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token) { - return helper_->ConsumeMailboxToTexture(mailbox, sync_token); - } - void ReadbackTextureAsync(GLuint texture, const gfx::Size& dst_size, unsigned char* out, @@ -257,8 +250,7 @@ bool IsFlippingOutput() const override; - void ReadbackYUV(const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, + void ReadbackYUV(GLuint texture, const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes, @@ -538,27 +530,6 @@ return max_draw_buffers_; } -gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture( - GLuint texture_id) { - gpu::Mailbox mailbox; - gl_->ProduceTextureDirectCHROMIUM(texture_id, mailbox.name); - - gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); - - return gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D); -} - -GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token) { - if (mailbox.IsZero()) - return 0; - if (sync_token.HasData()) - gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); - GLuint texture = gl_->CreateAndConsumeTextureCHROMIUM(mailbox.name); - return texture; -} - void GLHelper::CopyTextureToImpl::ReadbackPlane( const gfx::Size& texture_size, int row_stride_bytes, @@ -756,8 +727,7 @@ } void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV( - const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, + GLuint texture, const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes, @@ -771,12 +741,8 @@ DCHECK(!(paste_location.x() & 1)); DCHECK(!(paste_location.y() & 1)); - GLuint mailbox_texture = - copy_impl_->ConsumeMailboxToTexture(mailbox, sync_token); - I420ConverterImpl::Convert(mailbox_texture, src_texture_size, - gfx::Vector2dF(), scaler_.get(), output_rect, y_, - u_, v_); - gl_->DeleteTextures(1, &mailbox_texture); + I420ConverterImpl::Convert(texture, src_texture_size, gfx::Vector2dF(), + scaler_.get(), output_rect, y_, u_, v_); // Read back planes, one at a time. Keep the video frame alive while doing the // readback.
diff --git a/components/viz/common/gl_helper.h b/components/viz/common/gl_helper.h index e647271a..4f2e4aeb 100644 --- a/components/viz/common/gl_helper.h +++ b/components/viz/common/gl_helper.h
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "components/viz/common/viz_common_export.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/common/mailbox_holder.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "ui/gfx/geometry/size.h" @@ -24,7 +23,6 @@ namespace gpu { class ContextSupport; -struct Mailbox; } // namespace gpu namespace viz { @@ -171,23 +169,6 @@ SkColorType color_type, base::OnceCallback<void(bool)> callback); - // Creates a mailbox holder that is attached to the given texture id, with a - // sync point to wait on before using the mailbox. Returns a holder with an - // empty mailbox on failure. - // Note the texture is assumed to be GL_TEXTURE_2D. - // - // TODO(crbug.com/870036): DEPRECATED. This will be moved to be closer to its - // one caller soon. - gpu::MailboxHolder ProduceMailboxHolderFromTexture(GLuint texture_id); - - // Creates a texture and consumes a mailbox into it. Returns 0 on failure. - // Note the mailbox is assumed to be GL_TEXTURE_2D. - // - // TODO(crbug.com/870036): DEPRECATED. This will be moved to be closer to its - // one caller soon. - GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token); - // Caches all intermediate textures and programs needed to scale any subset of // a source texture at a fixed scaling ratio. class ScalerInterface { @@ -465,17 +446,14 @@ // method comments for the meaning/semantics of |src_texture_size| and // |output_rect|. The process is: // - // 1. Sync-wait and then consume and take ownership of the source texture - // provided by |mailbox|. - // 2. Scale the source texture to an intermediate texture. - // 3. Planarize, producing textures containing the Y, U, and V planes. - // 4. Read-back the planar data, copying it into the given output + // 1. Scale the source texture to an intermediate texture. + // 2. Planarize, producing textures containing the Y, U, and V planes. + // 3. Read-back the planar data, copying it into the given output // destination. |paste_location| specifies the where to place the output // pixels: Rect(paste_location.origin(), output_rect.size()). - // 5. Run |callback| with true on success, false on failure (with no output + // 4. Run |callback| with true on success, false on failure (with no output // modified). - virtual void ReadbackYUV(const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, + virtual void ReadbackYUV(GLuint texture, const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes,
diff --git a/components/viz/common/quads/frame_deadline.cc b/components/viz/common/quads/frame_deadline.cc index 6ab63d9a..a332727 100644 --- a/components/viz/common/quads/frame_deadline.cc +++ b/components/viz/common/quads/frame_deadline.cc
@@ -11,6 +11,11 @@ namespace viz { +// static +FrameDeadline FrameDeadline::MakeZero() { + return FrameDeadline(base::TimeTicks(), 0, base::TimeDelta(), false); +} + base::TimeTicks FrameDeadline::ToWallTime( base::Optional<uint32_t> default_deadline_in_frames) const { uint32_t deadline_in_frames = deadline_in_frames_;
diff --git a/components/viz/common/quads/frame_deadline.h b/components/viz/common/quads/frame_deadline.h index eef30ed..be7a80a 100644 --- a/components/viz/common/quads/frame_deadline.h +++ b/components/viz/common/quads/frame_deadline.h
@@ -24,6 +24,8 @@ // start time + deadline in frames * frame interval class VIZ_COMMON_EXPORT FrameDeadline { public: + static FrameDeadline MakeZero(); + FrameDeadline() = default; FrameDeadline(base::TimeTicks frame_start_time, uint32_t deadline_in_frames,
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index 437ecef..e751bdb 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -352,13 +352,6 @@ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsize, ysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, input_pixels.getPixels()); - gpu::Mailbox mailbox; - gl_->ProduceTextureDirectCHROMIUM(src_texture, mailbox.name); - EXPECT_FALSE(mailbox.IsZero()); - - gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); - std::string message = base::StringPrintf( "input size: %dx%d " "output size: %dx%d " @@ -392,8 +385,7 @@ std::move(quit_closure).Run(); }; yuv_reader->ReadbackYUV( - mailbox, sync_token, gfx::Size(xsize, ysize), - gfx::Rect(0, 0, xsize, ysize), + src_texture, gfx::Size(xsize, ysize), gfx::Rect(0, 0, xsize, ysize), output_frame->stride(media::VideoFrame::kYPlane), output_frame->data(media::VideoFrame::kYPlane), output_frame->stride(media::VideoFrame::kUPlane),
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS index 9a1738b3..6c42755 100644 --- a/components/viz/host/DEPS +++ b/components/viz/host/DEPS
@@ -31,4 +31,7 @@ "+components/viz/service/frame_sinks/frame_sink_manager_impl.h", "+components/viz/service/surfaces/surface_manager.h", ], + "renderer_settings_creation\.cc": [ + "+components/viz/common/switches.h", + ], }
diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc index bdd1e8b..ca788f5 100644 --- a/components/viz/host/host_display_client.cc +++ b/components/viz/host/host_display_client.cc
@@ -34,9 +34,6 @@ return ptr; } -void HostDisplayClient::DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) {} - #if defined(OS_MACOSX) void HostDisplayClient::OnDisplayReceivedCALayerParams( const gfx::CALayerParams& ca_layer_params) {
diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h index 7fd5a4a9..af64385 100644 --- a/components/viz/host/host_display_client.h +++ b/components/viz/host/host_display_client.h
@@ -32,9 +32,6 @@ private: // mojom::DisplayClient implementation: - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override; - #if defined(OS_MACOSX) void OnDisplayReceivedCALayerParams( const gfx::CALayerParams& ca_layer_params) override;
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc index 57584df..63d8a0d 100644 --- a/components/viz/host/host_frame_sink_manager.cc +++ b/components/viz/host/host_frame_sink_manager.cc
@@ -305,10 +305,6 @@ void HostFrameSinkManager::EvictSurfaces( const std::vector<SurfaceId>& surface_ids) { - // TODO(sgilhuly): Remove this check once crbug.com/911308 is fixed. - for (auto& surface_id : surface_ids) { - CHECK(surface_id.is_valid()); - } frame_sink_manager_->EvictSurfaces(surface_ids); }
diff --git a/components/viz/host/renderer_settings_creation.cc b/components/viz/host/renderer_settings_creation.cc index ee1f83f..5d064360 100644 --- a/components/viz/host/renderer_settings_creation.cc +++ b/components/viz/host/renderer_settings_creation.cc
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/strings/string_number_conversions.h" #include "build/build_config.h" +#include "components/viz/common/display/overlay_strategy.h" #include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/features.h" #include "ui/base/ui_base_switches.h" @@ -16,6 +17,10 @@ #include "ui/base/cocoa/remote_layer_api.h" #endif +#if defined(USE_OZONE) +#include "components/viz/common/switches.h" +#endif + namespace viz { namespace { @@ -78,6 +83,15 @@ &renderer_settings.slow_down_compositing_scale_factor); } +#if defined(USE_OZONE) + // TODO(crbug.com/930173): Add the default set of overlay strategies if flag + // isn't present but ozone platform supports overlays. + if (command_line->HasSwitch(switches::kEnableHardwareOverlays)) { + renderer_settings.overlay_strategies = ParseOverlayStategies( + command_line->GetSwitchValueASCII(switches::kEnableHardwareOverlays)); + } +#endif + return renderer_settings; }
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 1fd04b6..2a7caa8 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -309,6 +309,7 @@ # then this build target will no longer be needed. viz_source_set("gpu_service_dependencies") { sources = [ + "display_embedder/skia_output_device.h", "display_embedder/skia_output_surface_impl.cc", "display_embedder/skia_output_surface_impl.h", "display_embedder/skia_output_surface_impl_non_ddl.cc", @@ -347,6 +348,13 @@ } if (enable_vulkan) { + sources += [ + "display_embedder/skia_output_device_offscreen.cc", + "display_embedder/skia_output_device_offscreen.h", + "display_embedder/skia_output_device_vulkan.cc", + "display_embedder/skia_output_device_vulkan.h", + ] + public_deps += [ "//gpu/vulkan" ] } }
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc index 563ade8b..835ab990 100644 --- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc +++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -19,9 +19,9 @@ namespace { // Hard limit on number of bytes of memory to allocate (e.g. for referenced -// bitmaps) in association with a single CompositorFrame. Currently 1 GiB; +// bitmaps) in association with a single CompositorFrame. Currently 0.5 GiB; // reduce this if bots are running out of memory. -constexpr uint64_t kMaxMappedMemory = 1 << 30; +constexpr uint64_t kMaxMappedMemory = 1 << 29; // Handles inf / NaN by setting to 0. double MakeNormal(double x) { @@ -115,11 +115,11 @@ std::unique_ptr<base::SharedMemory> shared_memory) : id(id), size(size), shared_memory(std::move(shared_memory)) {} FuzzedBitmap::~FuzzedBitmap() = default; -FuzzedBitmap::FuzzedBitmap(FuzzedBitmap&& other) = default; +FuzzedBitmap::FuzzedBitmap(FuzzedBitmap&& other) noexcept = default; FuzzedData::FuzzedData() = default; FuzzedData::~FuzzedData() = default; -FuzzedData::FuzzedData(FuzzedData&& other) = default; +FuzzedData::FuzzedData(FuzzedData&& other) noexcept = default; FuzzedData GenerateFuzzedCompositorFrame( const content::fuzzing::proto::RenderPass& render_pass_spec) {
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 41e2a09..99e4be6 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -556,7 +556,10 @@ void Display::DidReceivePresentationFeedback( const gfx::PresentationFeedback& feedback) { - DCHECK(!pending_presented_callbacks_.empty()); + if (pending_presented_callbacks_.empty()) { + DLOG(ERROR) << "Received unexpected PresentationFeedback"; + return; + } ++last_presented_trace_id_; TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0( "viz,benchmark", "Graphics.Pipeline.DrawAndSwap",
diff --git a/components/viz/service/display/display_client.h b/components/viz/service/display/display_client.h index 506e4f1..83cb6f12 100644 --- a/components/viz/service/display/display_client.h +++ b/components/viz/service/display/display_client.h
@@ -11,10 +11,6 @@ struct CALayerParams; } // namespace gfx -namespace ui { -class LatencyInfo; -} // namespace ui - namespace viz { class DisplayClient { @@ -29,11 +25,6 @@ virtual void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) = 0; virtual void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) = 0; - - // Notifies that a swap has occured after some latency info with snapshot - // component reached the display. - virtual void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) = 0; }; } // namespace viz
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc index d57b854a..9b1f936 100644 --- a/components/viz/service/display/display_unittest.cc +++ b/components/viz/service/display/display_unittest.cc
@@ -104,8 +104,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override {} void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override {} - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override {} }; void CopyCallback(bool* called, std::unique_ptr<CopyOutputResult> result) {
diff --git a/components/viz/service/display/skia_output_surface.h b/components/viz/service/display/skia_output_surface.h index b0d6480..5e2e412 100644 --- a/components/viz/service/display/skia_output_surface.h +++ b/components/viz/service/display/skia_output_surface.h
@@ -5,6 +5,9 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_ +#include <memory> +#include <vector> + #include "components/viz/common/resources/resource_format.h" #include "components/viz/service/display/output_surface.h" #include "third_party/skia/include/core/SkRefCnt.h" @@ -61,6 +64,7 @@ virtual sk_sp<SkImage> MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) = 0; // Release SkImages created by MakePromiseSkImage on the thread on which
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 7dc18c3..dcc66000 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -4,6 +4,9 @@ #include "components/viz/service/display/skia_renderer.h" +#include <string> +#include <utility> + #include "base/bits.h" #include "base/command_line.h" #include "base/optional.h" @@ -34,14 +37,19 @@ #include "skia/ext/opacity_filter_canvas.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkColorFilter.h" +#include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkOverdrawCanvas.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkPixelRef.h" #include "third_party/skia/include/core/SkShader.h" +#include "third_party/skia/include/core/SkString.h" #include "third_party/skia/include/effects/SkOverdrawColorFilter.h" #include "third_party/skia/include/effects/SkShaderMaskFilter.h" #include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/src/core/SkColorFilterPriv.h" +#include "ui/gfx/color_transform.h" #include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/skia_util.h" @@ -131,7 +139,9 @@ class SkiaRenderer::ScopedYUVSkImageBuilder { public: ScopedYUVSkImageBuilder(SkiaRenderer* skia_renderer, - const YUVVideoDrawQuad* quad) { + const YUVVideoDrawQuad* quad, + sk_sp<SkColorSpace> dst_color_space, + bool has_color_conversion_filter) { DCHECK(skia_renderer->is_using_ddl()); DCHECK(IsTextureResource(skia_renderer->resource_provider_, quad->y_plane_resource_id())); @@ -148,8 +158,13 @@ auto& image = skia_renderer->yuv_promise_images_[std::move(ids)]; if (!image) { - auto yuv_color_space = kRec601_SkYUVColorSpace; - quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space); + SkYUVColorSpace yuv_color_space; + if (has_color_conversion_filter) { + yuv_color_space = kIdentity_SkYUVColorSpace; + } else { + yuv_color_space = kRec601_SkYUVColorSpace; + quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space); + } const bool is_i420 = quad->u_plane_resource_id() != quad->v_plane_resource_id(); @@ -178,7 +193,7 @@ } image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV( - std::move(metadatas), yuv_color_space, has_alpha); + std::move(metadatas), yuv_color_space, dst_color_space, has_alpha); LOG_IF(ERROR, !image) << "Failed to create the promise sk yuva image."; } sk_image_ = image.get(); @@ -839,6 +854,37 @@ batched_tiles_.clear(); } +sk_sp<SkColorFilter> SkiaRenderer::GetColorFilter(const gfx::ColorSpace& src, + const gfx::ColorSpace& dst) { + sk_sp<SkColorFilter>& color_filter = color_filter_cache_[dst][src]; + if (!color_filter) { + std::unique_ptr<gfx::ColorTransform> transform = + gfx::ColorTransform::NewColorTransform( + src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); + // TODO(backer): Support lookup table transforms (e.g. + // COLOR_CONVERSION_MODE_LUT). + if (!transform->CanGetShaderSource()) + return nullptr; + const char* hdr = R"( +void main(inout half4 color) { + // un-premultiply alpha + if (color.a > 0) + color.rgb /= color.a; +)"; + const char* ftr = R"( + // premultiply alpha + color.rgb *= color.a; +} +)"; + + std::string shader = hdr + transform->GetSkShaderSource() + ftr; + color_filter = + SkRuntimeColorFilterFactory(SkString(shader.c_str(), shader.size())) + .make(SkData::MakeEmpty()); + } + return color_filter; +} + void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, SkPaint* paint) { DCHECK(paint); @@ -847,8 +893,18 @@ return; } + gfx::ColorSpace src_color_space = quad->video_color_space; + // Invalid or unspecified color spaces should be treated as REC709. + if (!src_color_space.IsValid()) + src_color_space = gfx::ColorSpace::CreateREC709(); + gfx::ColorSpace dst_color_space = + current_frame()->current_render_pass->color_space; + sk_sp<SkColorFilter> color_filter = + GetColorFilter(src_color_space, dst_color_space); + DCHECK(resource_provider_); - ScopedYUVSkImageBuilder builder(this, quad); + ScopedYUVSkImageBuilder builder(this, quad, dst_color_space.ToSkColorSpace(), + !!color_filter); const SkImage* image = builder.sk_image(); if (!image) return; @@ -859,6 +915,8 @@ SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect); // TODO(penghuang): figure out how to set correct filter quality. paint->setFilterQuality(kLow_SkFilterQuality); + if (color_filter) + paint->setColorFilter(color_filter); current_canvas_->drawImageRect(image, uv_rect, gfx::RectToSkRect(quad->visible_rect), paint); }
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index b124b20e..dcbaeb4e 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -5,7 +5,10 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_ +#include <map> +#include <memory> #include <tuple> +#include <vector> #include "base/macros.h" #include "cc/cc_export.h" @@ -15,6 +18,7 @@ #include "third_party/skia/include/core/SkPictureRecorder.h" #include "ui/latency/latency_info.h" +class SkColorFilter; class SkNWayCanvas; class SkPictureRecorder; @@ -130,6 +134,8 @@ GrContext* GetGrContext(); bool is_using_ddl() const { return draw_mode_ == DrawMode::DDL; } + sk_sp<SkColorFilter> GetColorFilter(const gfx::ColorSpace& src, + const gfx::ColorSpace& dst); // A map from RenderPass id to the texture used to draw the RenderPass from. struct RenderPassBacking { sk_sp<SkSurface> render_pass_surface; @@ -219,6 +225,9 @@ ContextProvider* context_provider_ = nullptr; base::Optional<SyncQueryCollection> sync_queries_; + std::map<gfx::ColorSpace, std::map<gfx::ColorSpace, sk_sp<SkColorFilter>>> + color_filter_cache_; + DISALLOW_COPY_AND_ASSIGN(SkiaRenderer); };
diff --git a/components/viz/service/display_embedder/gl_output_surface_ozone.cc b/components/viz/service/display_embedder/gl_output_surface_ozone.cc index 98903b1a..2c34702 100644 --- a/components/viz/service/display_embedder/gl_output_surface_ozone.cc +++ b/components/viz/service/display_embedder/gl_output_surface_ozone.cc
@@ -4,7 +4,13 @@ #include "components/viz/service/display_embedder/gl_output_surface_ozone.h" +#include <utility> + +#include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h" #include "ui/display/types/display_snapshot.h" +#include "ui/ozone/public/overlay_candidates_ozone.h" +#include "ui/ozone/public/overlay_manager_ozone.h" +#include "ui/ozone/public/ozone_platform.h" namespace viz { @@ -12,19 +18,29 @@ scoped_refptr<VizProcessContextProvider> context_provider, gpu::SurfaceHandle surface_handle, SyntheticBeginFrameSource* synthetic_begin_frame_source, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + std::vector<OverlayStrategy> strategies) : GLOutputSurfaceBufferQueue(context_provider, surface_handle, synthetic_begin_frame_source, gpu_memory_buffer_manager, - display::DisplaySnapshot::PrimaryFormat()) {} + display::DisplaySnapshot::PrimaryFormat()) { + if (!strategies.empty()) { + auto* overlay_manager = + ui::OzonePlatform::GetInstance()->GetOverlayManager(); + std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates = + overlay_manager->CreateOverlayCandidates(surface_handle); + overlay_candidate_validator_ = + std::make_unique<CompositorOverlayCandidateValidatorOzone>( + std::move(overlay_candidates), std::move(strategies)); + } +} GLOutputSurfaceOzone::~GLOutputSurfaceOzone() = default; OverlayCandidateValidator* GLOutputSurfaceOzone::GetOverlayCandidateValidator() const { - // TODO(crbug.com/930173): Implement overlay functionality. - return nullptr; + return overlay_candidate_validator_.get(); } } // namespace viz
diff --git a/components/viz/service/display_embedder/gl_output_surface_ozone.h b/components/viz/service/display_embedder/gl_output_surface_ozone.h index 683051f..ce0f932 100644 --- a/components/viz/service/display_embedder/gl_output_surface_ozone.h +++ b/components/viz/service/display_embedder/gl_output_surface_ozone.h
@@ -5,23 +5,32 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_OZONE_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_OZONE_H_ +#include <memory> +#include <vector> + +#include "components/viz/common/display/overlay_strategy.h" #include "components/viz/service/display_embedder/gl_output_surface_buffer_queue.h" namespace viz { class GLOutputSurfaceOzone : public GLOutputSurfaceBufferQueue { public: + // |strategies| is a list of overlay strategies that will be attempted. If the + // list is empty then there is no overlay support on this platform. GLOutputSurfaceOzone( scoped_refptr<VizProcessContextProvider> context_provider, gpu::SurfaceHandle surface_handle, SyntheticBeginFrameSource* synthetic_begin_frame_source, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + std::vector<OverlayStrategy> strategies); ~GLOutputSurfaceOzone() override; // OutputSurface implementation. OverlayCandidateValidator* GetOverlayCandidateValidator() const override; private: + std::unique_ptr<OverlayCandidateValidator> overlay_candidate_validator_; + DISALLOW_COPY_AND_ASSIGN(GLOutputSurfaceOzone); };
diff --git a/components/viz/service/display_embedder/gpu_display_provider.cc b/components/viz/service/display_embedder/gpu_display_provider.cc index a3a68265..7f7c2af0 100644 --- a/components/viz/service/display_embedder/gpu_display_provider.cc +++ b/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -58,7 +58,6 @@ #if defined(USE_OZONE) #include "components/viz/service/display_embedder/gl_output_surface_ozone.h" #include "components/viz/service/display_embedder/software_output_device_ozone.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/platform_window_surface.h" #include "ui/ozone/public/surface_factory_ozone.h" @@ -213,7 +212,8 @@ #if defined(USE_OZONE) output_surface = std::make_unique<GLOutputSurfaceOzone>( std::move(context_provider), surface_handle, - synthetic_begin_frame_source, gpu_memory_buffer_manager_.get()); + synthetic_begin_frame_source, gpu_memory_buffer_manager_.get(), + renderer_settings.overlay_strategies); #elif defined(OS_MACOSX) output_surface = std::make_unique<GLOutputSurfaceMac>( std::move(context_provider), surface_handle,
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h new file mode 100644 index 0000000..bf4d5d2 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_ + +#include "base/macros.h" +#include "third_party/skia/include/core/SkRefCnt.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/swap_result.h" + +class SkSurface; + +namespace viz { + +class SkiaOutputDevice { + public: + SkiaOutputDevice() = default; + virtual ~SkiaOutputDevice() = default; + + // SkSurface that can be drawn to. + virtual sk_sp<SkSurface> DrawSurface() = 0; + + // Changes the size of draw surface and invalidates it's contents. + virtual void Reshape(const gfx::Size& size) = 0; + + // Presents DrawSurface. + virtual gfx::SwapResult SwapBuffers() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SkiaOutputDevice); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc new file mode 100644 index 0000000..631689b --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/skia_output_device_offscreen.h" + +#include "third_party/skia/include/core/SkSurface.h" + +namespace viz { + +SkiaOutputDeviceOffscreen::SkiaOutputDeviceOffscreen(GrContext* gr_context) + : gr_context_(gr_context) {} + +SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() = default; + +sk_sp<SkSurface> SkiaOutputDeviceOffscreen::DrawSurface() { + return draw_surface_; +} + +void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size) { + auto image_info = SkImageInfo::Make( + size.width(), size.height(), kRGBA_8888_SkColorType, kOpaque_SkAlphaType); + draw_surface_ = + SkSurface::MakeRenderTarget(gr_context_, SkBudgeted::kNo, image_info); +} + +gfx::SwapResult SkiaOutputDeviceOffscreen::SwapBuffers() { + // Reshape should have been called first. + DCHECK(draw_surface_); + return gfx::SwapResult::SWAP_ACK; +} + +} // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h new file mode 100644 index 0000000..6a7bd18 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_ + +#include "base/macros.h" +#include "components/viz/service/display_embedder/skia_output_device.h" + +class GrContext; + +namespace viz { + +class SkiaOutputDeviceOffscreen : public SkiaOutputDevice { + public: + explicit SkiaOutputDeviceOffscreen(GrContext* gr_context); + ~SkiaOutputDeviceOffscreen() override; + + sk_sp<SkSurface> DrawSurface() override; + void Reshape(const gfx::Size& size) override; + gfx::SwapResult SwapBuffers() override; + + private: + GrContext* const gr_context_; + sk_sp<SkSurface> draw_surface_; + + DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceOffscreen); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc new file mode 100644 index 0000000..2219557 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -0,0 +1,125 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/skia_output_device_vulkan.h" + +#include "build/build_config.h" +#include "components/viz/common/gpu/vulkan_context_provider.h" +#include "gpu/ipc/common/gpu_surface_lookup.h" +#include "gpu/vulkan/vulkan_implementation.h" +#include "gpu/vulkan/vulkan_surface.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/vk/GrVkTypes.h" + +namespace viz { + +SkiaOutputDeviceVulkan::SkiaOutputDeviceVulkan( + VulkanContextProvider* context_provider, + gpu::SurfaceHandle surface_handle) + : context_provider_(context_provider), surface_handle_(surface_handle) {} + +SkiaOutputDeviceVulkan::~SkiaOutputDeviceVulkan() { + if (vulkan_surface_) + vulkan_surface_->Destroy(); +} + +sk_sp<SkSurface> SkiaOutputDeviceVulkan::DrawSurface() { + return draw_surface_; +} + +void SkiaOutputDeviceVulkan::Reshape(const gfx::Size& size) { + if (!vulkan_surface_) + CreateVulkanSurface(); + + auto old_size = vulkan_surface_->size(); + vulkan_surface_->SetSize(size); + if (vulkan_surface_->size() != old_size) { + // Size has been changed, we need to clear all surfaces which will be + // recreated later. + sk_surfaces_.clear(); + sk_surfaces_.resize(vulkan_surface_->GetSwapChain()->num_images()); + } + + UpdateDrawSurface(); +} + +gfx::SwapResult SkiaOutputDeviceVulkan::SwapBuffers() { + // Reshape should have been called first. + DCHECK(vulkan_surface_); + DCHECK(draw_surface_); + + auto backend = draw_surface_->getBackendRenderTarget( + SkSurface::kFlushRead_BackendHandleAccess); + GrVkImageInfo vk_image_info; + if (!backend.getVkImageInfo(&vk_image_info)) + NOTREACHED() << "Failed to get the image info."; + vulkan_surface_->GetSwapChain()->SetCurrentImageLayout( + vk_image_info.fImageLayout); + auto result = vulkan_surface_->SwapBuffers(); + + UpdateDrawSurface(); + + return result; +} + +void SkiaOutputDeviceVulkan::CreateVulkanSurface() { + LOG(ERROR) << "CreateVulkanSurface"; + gfx::AcceleratedWidget accelerated_widget = gfx::kNullAcceleratedWidget; +#if defined(OS_ANDROID) + accelerated_widget = + gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget( + surface_handle_); +#else + accelerated_widget = surface_handle_; +#endif + auto vulkan_surface = + context_provider_->GetVulkanImplementation()->CreateViewSurface( + accelerated_widget); + if (!vulkan_surface) + LOG(FATAL) << "Failed to create vulkan surface."; + if (!vulkan_surface->Initialize(context_provider_->GetDeviceQueue(), + gpu::VulkanSurface::FORMAT_RGBA_32)) { + LOG(FATAL) << "Failed to initialize vulkan surface."; + } + vulkan_surface_ = std::move(vulkan_surface); +} + +void SkiaOutputDeviceVulkan::UpdateDrawSurface() { + DCHECK(vulkan_surface_); + auto* swap_chain = vulkan_surface_->GetSwapChain(); + auto index = swap_chain->current_image(); + auto& sk_surface = sk_surfaces_[index]; + if (!sk_surface) { + SkSurfaceProps surface_props = + SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); + VkImage vk_image = swap_chain->GetCurrentImage(); + VkImageLayout vk_image_layout = swap_chain->GetCurrentImageLayout(); + const auto surface_format = vulkan_surface_->surface_format().format; + DCHECK(surface_format == VK_FORMAT_B8G8R8A8_UNORM || + surface_format == VK_FORMAT_R8G8B8A8_UNORM); + GrVkImageInfo vk_image_info(vk_image, GrVkAlloc(), VK_IMAGE_TILING_OPTIMAL, + vk_image_layout, surface_format, + 1 /* level_count */); + GrBackendRenderTarget render_target(vulkan_surface_->size().width(), + vulkan_surface_->size().height(), + 0 /* sample_cnt */, vk_image_info); + auto sk_color_type = surface_format == VK_FORMAT_B8G8R8A8_UNORM + ? kBGRA_8888_SkColorType + : kRGBA_8888_SkColorType; + sk_surface = SkSurface::MakeFromBackendRenderTarget( + context_provider_->GetGrContext(), render_target, + kTopLeft_GrSurfaceOrigin, sk_color_type, nullptr /* color_space */, + &surface_props); + DCHECK(sk_surface); + } else { + auto backend = sk_surface->getBackendRenderTarget( + SkSurface::kFlushRead_BackendHandleAccess); + backend.setVkImageLayout(swap_chain->GetCurrentImageLayout()); + } + + draw_surface_ = sk_surface; +} + +} // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.h b/components/viz/service/display_embedder/skia_output_device_vulkan.h new file mode 100644 index 0000000..0c8d9b6 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.h
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "components/viz/service/display_embedder/skia_output_device.h" +#include "gpu/ipc/common/surface_handle.h" + +namespace gpu { +class VulkanSurface; +} + +namespace viz { + +class VulkanContextProvider; + +class SkiaOutputDeviceVulkan : public SkiaOutputDevice { + public: + SkiaOutputDeviceVulkan(VulkanContextProvider* context_provider, + gpu::SurfaceHandle surface_handle); + ~SkiaOutputDeviceVulkan() override; + + sk_sp<SkSurface> DrawSurface() override; + void Reshape(const gfx::Size& size) override; + gfx::SwapResult SwapBuffers() override; + + private: + void CreateVulkanSurface(); + void UpdateDrawSurface(); + + VulkanContextProvider* const context_provider_; + + const gpu::SurfaceHandle surface_handle_; + std::unique_ptr<gpu::VulkanSurface> vulkan_surface_; + + // SkSurfaces for swap chain images. + std::vector<sk_sp<SkSurface>> sk_surfaces_; + + // SkSurface to be drawn to. Updated after Reshape and SwapBuffers. + sk_sp<SkSurface> draw_surface_; + + DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceVulkan); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_H_
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index d0f679b1..d8a5a10 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -189,6 +189,7 @@ static sk_sp<SkImage> MakeYUVAPromiseSkImage( SkiaOutputSurfaceImpl* impl, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, std::vector<ResourceMetadata> metadatas, bool has_alpha) { DCHECK_CALLED_ON_VALID_THREAD(impl->thread_checker_); @@ -219,7 +220,7 @@ contexts[i] = new PromiseTextureHelper( impl->impl_on_gpu_->weak_ptr(), metadata.size, metadata.resource_format, metadata.mailbox_holder, - metadata.color_space.ToSkColorSpace(), metadata.alpha_type); + nullptr /* color_space */, metadata.alpha_type); }; if (is_i420) { @@ -259,9 +260,9 @@ auto image = impl->recorder_->makeYUVAPromiseTexture( yuv_color_space, formats, yuva_sizes, indices, yuva_sizes[0].width(), - yuva_sizes[0].height(), kTopLeft_GrSurfaceOrigin, - nullptr /* color_space */, PromiseTextureHelper::Fulfill, - PromiseTextureHelper::Release, PromiseTextureHelper::Done, contexts); + yuva_sizes[0].height(), kTopLeft_GrSurfaceOrigin, dst_color_space, + PromiseTextureHelper::Fulfill, PromiseTextureHelper::Release, + PromiseTextureHelper::Done, contexts); return image; } @@ -505,6 +506,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(recorder_); @@ -512,7 +514,7 @@ (!has_alpha && (metadatas.size() == 2 || metadatas.size() == 3))); return YUVAPromiseTextureHelper::MakeYUVAPromiseSkImage( - this, yuv_color_space, std::move(metadatas), has_alpha); + this, yuv_color_space, dst_color_space, std::move(metadatas), has_alpha); } gpu::SyncToken SkiaOutputSurfaceImpl::ReleasePromiseSkImages(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index bdca1f935..acfb857 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -5,6 +5,9 @@ #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_ #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_ +#include <memory> +#include <vector> + #include "base/macros.h" #include "base/observer_list.h" #include "base/optional.h" @@ -87,6 +90,7 @@ sk_sp<SkImage> MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) override; void SkiaSwapBuffers(OutputSurfaceFrame frame) override; SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc index 444b0d7e..d278bb4 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
@@ -271,6 +271,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImplNonDDL::MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK((has_alpha && (metadatas.size() == 3 || metadatas.size() == 4)) || @@ -331,7 +332,7 @@ return SkImage::MakeFromYUVATextures( gr_context(), yuv_color_space, yuva_textures, indices, SkISize::Make(yuva_textures[0].width(), yuva_textures[1].height()), - kTopLeft_GrSurfaceOrigin); + kTopLeft_GrSurfaceOrigin, dst_color_space); } gpu::SyncToken SkiaOutputSurfaceImplNonDDL::ReleasePromiseSkImages(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.h b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.h index 80cf1df..5c6a94cb 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.h
@@ -86,6 +86,7 @@ sk_sp<SkImage> MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) override; void SkiaSwapBuffers(OutputSurfaceFrame frame) override; SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index c105b90..49299568 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -17,6 +17,7 @@ #include "components/viz/service/display/output_surface_frame.h" #include "components/viz/service/display/texture_deleter.h" #include "components/viz/service/display_embedder/direct_context_provider.h" +#include "components/viz/service/display_embedder/skia_output_device.h" #include "components/viz/service/gl/gpu_service_impl.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/swap_buffers_complete_params.h" @@ -49,9 +50,8 @@ #include "ui/gl/init/gl_factory.h" #if BUILDFLAG(ENABLE_VULKAN) -#include "components/viz/common/gpu/vulkan_context_provider.h" -#include "gpu/vulkan/vulkan_implementation.h" -#include "gpu/vulkan/vulkan_surface.h" +#include "components/viz/service/display_embedder/skia_output_device_offscreen.h" +#include "components/viz/service/display_embedder/skia_output_device_vulkan.h" #endif #if defined(USE_OZONE) @@ -101,27 +101,6 @@ DISALLOW_COPY_AND_ASSIGN(ScopedUseContextProvider); }; -// TODO(backer): Use this wrapper for GL as well. -// Thin wrapper around gpu::VulkanSurface that allows us to easily inject -// a fake offscreen surface for tests. -class SkiaOutputSurfaceImplOnGpu::SurfaceWrapper { - public: - SurfaceWrapper(); - virtual ~SurfaceWrapper(); - - // SkSurface that can be drawn to. - virtual sk_sp<SkSurface> DrawSurface() = 0; - - // Changes the size of draw surface and invalidates it's contents. - virtual void Reshape(const gfx::Size& size) = 0; - - // Presents DrawSurface. - virtual gpu::SwapBuffersCompleteParams SwapBuffers() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(SurfaceWrapper); -}; - namespace { base::AtomicSequenceNumber g_next_command_buffer_id; @@ -282,175 +261,6 @@ DISALLOW_COPY_AND_ASSIGN(ContextCurrentTaskRunner); }; -#if BUILDFLAG(ENABLE_VULKAN) -// Wrap gpu::VulkanSurface for use in Skia API. Creates a sequence of SkSurface -// around the gpu::VulkanSurface::GetSwapChain(). -class OnScreenVulkanSurface final - : public SkiaOutputSurfaceImplOnGpu::SurfaceWrapper { - public: - OnScreenVulkanSurface(VulkanContextProvider* context_provider, - gpu::SurfaceHandle surface_handle) - : context_provider_(context_provider), surface_handle_(surface_handle) {} - - ~OnScreenVulkanSurface() override { - if (vulkan_surface_) - vulkan_surface_->Destroy(); - } - - // SurfaceWrapper implementation - sk_sp<SkSurface> DrawSurface() override { return draw_surface_; } - - void Reshape(const gfx::Size& size) override { - if (!vulkan_surface_) - CreateVulkanSurface(); - - auto old_size = vulkan_surface_->size(); - vulkan_surface_->SetSize(size); - if (vulkan_surface_->size() != old_size) { - // Size has been changed, we need to clear all surfaces which will be - // recreated later. - sk_surfaces_.clear(); - sk_surfaces_.resize(vulkan_surface_->GetSwapChain()->num_images()); - } - - UpdateDrawSurface(); - } - - gpu::SwapBuffersCompleteParams SwapBuffers() override { - // Reshape should have been called first. - DCHECK(vulkan_surface_); - DCHECK(draw_surface_); - - gpu::SwapBuffersCompleteParams params; - params.swap_response.swap_start = base::TimeTicks::Now(); - - auto backend = draw_surface_->getBackendRenderTarget( - SkSurface::kFlushRead_BackendHandleAccess); - GrVkImageInfo vk_image_info; - if (!backend.getVkImageInfo(&vk_image_info)) - NOTREACHED() << "Failed to get the image info."; - vulkan_surface_->GetSwapChain()->SetCurrentImageLayout( - vk_image_info.fImageLayout); - params.swap_response.result = vulkan_surface_->SwapBuffers(); - params.swap_response.swap_end = base::TimeTicks::Now(); - - UpdateDrawSurface(); - - return params; - } - - private: - void CreateVulkanSurface() { - gfx::AcceleratedWidget accelerated_widget = gfx::kNullAcceleratedWidget; -#if defined(OS_ANDROID) - accelerated_widget = - gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget( - surface_handle_); -#else - accelerated_widget = surface_handle_; -#endif - auto vulkan_surface = - context_provider_->GetVulkanImplementation()->CreateViewSurface( - accelerated_widget); - if (!vulkan_surface) - LOG(FATAL) << "Failed to create vulkan surface."; - if (!vulkan_surface->Initialize(context_provider_->GetDeviceQueue(), - gpu::VulkanSurface::FORMAT_RGBA_32)) { - LOG(FATAL) << "Failed to initialize vulkan surface."; - } - vulkan_surface_ = std::move(vulkan_surface); - } - - void UpdateDrawSurface() { - DCHECK(vulkan_surface_); - auto* swap_chain = vulkan_surface_->GetSwapChain(); - auto index = swap_chain->current_image(); - auto& sk_surface = sk_surfaces_[index]; - if (!sk_surface) { - SkSurfaceProps surface_props = - SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); - VkImage vk_image = swap_chain->GetCurrentImage(); - VkImageLayout vk_image_layout = swap_chain->GetCurrentImageLayout(); - const auto surface_format = vulkan_surface_->surface_format().format; - DCHECK(surface_format == VK_FORMAT_B8G8R8A8_UNORM || - surface_format == VK_FORMAT_R8G8B8A8_UNORM); - GrVkImageInfo vk_image_info(vk_image, GrVkAlloc(), - VK_IMAGE_TILING_OPTIMAL, vk_image_layout, - surface_format, 1 /* level_count */); - GrBackendRenderTarget render_target(vulkan_surface_->size().width(), - vulkan_surface_->size().height(), - 0 /* sample_cnt */, vk_image_info); - auto sk_color_type = surface_format == VK_FORMAT_B8G8R8A8_UNORM - ? kBGRA_8888_SkColorType - : kRGBA_8888_SkColorType; - sk_surface = SkSurface::MakeFromBackendRenderTarget( - context_provider_->GetGrContext(), render_target, - kTopLeft_GrSurfaceOrigin, sk_color_type, nullptr /* color_space */, - &surface_props); - DCHECK(sk_surface); - } else { - auto backend = sk_surface->getBackendRenderTarget( - SkSurface::kFlushRead_BackendHandleAccess); - backend.setVkImageLayout(swap_chain->GetCurrentImageLayout()); - } - - draw_surface_ = sk_surface; - } - - VulkanContextProvider* const context_provider_; - - const gpu::SurfaceHandle surface_handle_; - std::unique_ptr<gpu::VulkanSurface> vulkan_surface_; - - // SkSurfaces for swap chain images. - std::vector<sk_sp<SkSurface>> sk_surfaces_; - - // SkSurface to be drawn to. Updated after Reshape and SwapBuffers. - sk_sp<SkSurface> draw_surface_; - - DISALLOW_COPY_AND_ASSIGN(OnScreenVulkanSurface); -}; - -// An offscreen surface suitable for tests. -class OffscreenVulkanSurface final - : public SkiaOutputSurfaceImplOnGpu::SurfaceWrapper { - public: - explicit OffscreenVulkanSurface(GrContext* gr_context) - : gr_context_(gr_context) {} - ~OffscreenVulkanSurface() override = default; - - // SurfaceWrapper implementation: - sk_sp<SkSurface> DrawSurface() override { return draw_surface_; } - - void Reshape(const gfx::Size& size) override { - auto image_info = - SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType, - kOpaque_SkAlphaType); - draw_surface_ = - SkSurface::MakeRenderTarget(gr_context_, SkBudgeted::kNo, image_info); - } - - gpu::SwapBuffersCompleteParams SwapBuffers() override { - // Reshape should have been called first. - DCHECK(draw_surface_); - - gpu::SwapBuffersCompleteParams params; - params.swap_response.swap_start = base::TimeTicks::Now(); - params.swap_response.result = gfx::SwapResult::SWAP_ACK; - params.swap_response.swap_end = params.swap_response.swap_start; - - return params; - } - - private: - GrContext* const gr_context_; - sk_sp<SkSurface> draw_surface_; - - DISALLOW_COPY_AND_ASSIGN(OffscreenVulkanSurface); -}; - -#endif // if BUILDFLAG(ENABLE_VULKAN) - } // namespace SkiaOutputSurfaceImplOnGpu::OffscreenSurface::OffscreenSurface() = default; @@ -484,10 +294,6 @@ promise_texture_ = {}; } -SkiaOutputSurfaceImplOnGpu::SurfaceWrapper::SurfaceWrapper() = default; - -SkiaOutputSurfaceImplOnGpu::SurfaceWrapper::~SurfaceWrapper() = default; - SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu( gpu::SurfaceHandle surface_handle, scoped_refptr<gpu::gles2::FeatureInfo> feature_info, @@ -625,17 +431,17 @@ CreateSkSurfaceForGL(); } else { #if BUILDFLAG(ENABLE_VULKAN) - if (!vulkan_surface_) { + if (!output_device_) { if (surface_handle_ == gpu::kNullSurfaceHandle) { - vulkan_surface_ = - std::make_unique<OffscreenVulkanSurface>(gr_context()); + output_device_ = + std::make_unique<SkiaOutputDeviceOffscreen>(gr_context()); } else { - vulkan_surface_ = std::make_unique<OnScreenVulkanSurface>( + output_device_ = std::make_unique<SkiaOutputDeviceVulkan>( vulkan_context_provider_, surface_handle_); } } - vulkan_surface_->Reshape(size); - sk_surface_ = vulkan_surface_->DrawSurface(); + output_device_->Reshape(size); + sk_surface_ = output_device_->DrawSurface(); #else NOTREACHED(); #endif @@ -709,10 +515,13 @@ swap_end = base::TimeTicks::Now(); } else { #if BUILDFLAG(ENABLE_VULKAN) - DCHECK(vulkan_surface_); + DCHECK(output_device_); OnSwapBuffers(); - auto params = vulkan_surface_->SwapBuffers(); - sk_surface_ = vulkan_surface_->DrawSurface(); + gpu::SwapBuffersCompleteParams params; + params.swap_response.swap_start = base::TimeTicks::Now(); + params.swap_response.result = output_device_->SwapBuffers(); + params.swap_response.swap_end = base::TimeTicks::Now(); + sk_surface_ = output_device_->DrawSurface(); DidSwapBuffersComplete(params); buffer_presented_callback_.Run(gfx::PresentationFeedback( params.swap_response.swap_end, base::TimeDelta(), 0 /* flag */));
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index df68a30..f1d81d8 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -59,6 +59,7 @@ class DirectContextProvider; class GLRendererCopier; class GpuServiceImpl; +class SkiaOutputDevice; class TextureDeleter; class VulkanContextProvider; @@ -160,7 +161,6 @@ bool was_context_lost() { return context_state_->context_lost(); } class ScopedUseContextProvider; - class SurfaceWrapper; void SetCapabilitiesForTesting( const OutputSurface::Capabilities& capabilities) { @@ -237,7 +237,7 @@ const gl::GLVersionInfo* gl_version_info_ = nullptr; OutputSurface::Capabilities capabilities_; - std::unique_ptr<SurfaceWrapper> vulkan_surface_; + std::unique_ptr<SkiaOutputDevice> output_device_; // Offscreen surfaces for render passes. It can only be accessed on GPU // thread.
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc index 314431a5..fa5d9f6 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -234,12 +234,6 @@ // Not needed in non-OOP-D mode. } -void DirectLayerTreeFrameSink::DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) { - // TODO(samans): Implement this method once the plumbing for latency info also - // works for non-OOP-D. -} - void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAck( const std::vector<ReturnedResource>& resources) { // Submitting a CompositorFrame can synchronously draw and dispatch a frame
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h index e84c1bd..2188e41 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -85,8 +85,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override; void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override; - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override; private: // mojom::CompositorFrameSinkClient implementation:
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index 8a6d9ff..2c1e82aa 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -294,11 +294,6 @@ #endif } -void RootCompositorFrameSinkImpl::DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) { - display_client_->DidSwapAfterSnapshotRequestReceived(latency_info); -} - void RootCompositorFrameSinkImpl::DisplayDidDrawAndSwap() {} BeginFrameSource* RootCompositorFrameSinkImpl::begin_frame_source() {
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h index e14dcbd..1fab14d62 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -96,8 +96,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override; void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override; - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override; BeginFrameSource* begin_frame_source();
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index 5a0220f8..8862040 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -1418,9 +1418,9 @@ display_support().SubmitCompositorFrame( display_id.local_surface_id(), - MakeCompositorFrame({parent_id1}, empty_surface_ranges(), - std::vector<TransferableResource>(), - MakeDefaultDeadline())); + MakeCompositorFrame( + {parent_id1}, {SurfaceRange(base::nullopt, parent_id1)}, + std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(display_surface()->HasPendingFrame()); EXPECT_FALSE(display_surface()->HasActiveFrame()); @@ -1441,7 +1441,7 @@ // scheduling a deadline and without waiting for dependencies to resolve. parent_support().SubmitCompositorFrame( parent_id1.local_surface_id(), - MakeCompositorFrame({child_id1}, empty_surface_ranges(), + MakeCompositorFrame({child_id1}, {SurfaceRange(base::nullopt, child_id1)}, std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_FALSE(parent_surface()->has_deadline()); @@ -1459,7 +1459,7 @@ display_support().SubmitCompositorFrame( display_id.local_surface_id(), - MakeCompositorFrame({parent_id}, empty_surface_ranges(), + MakeCompositorFrame({parent_id}, {SurfaceRange(base::nullopt, parent_id)}, std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(display_surface()->HasPendingFrame()); @@ -1481,9 +1481,9 @@ // surface and so it gets a separate deadline. child_support1().SubmitCompositorFrame( child_id.local_surface_id(), - MakeCompositorFrame({arbitrary_id}, empty_surface_ranges(), - std::vector<TransferableResource>(), - MakeDefaultDeadline())); + MakeCompositorFrame( + {arbitrary_id}, {SurfaceRange(base::nullopt, arbitrary_id)}, + std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(child_surface1()->HasPendingFrame()); EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->has_deadline()); @@ -1494,7 +1494,7 @@ // be late and activate immediately. parent_support().SubmitCompositorFrame( parent_id.local_surface_id(), - MakeCompositorFrame({child_id}, empty_surface_ranges(), + MakeCompositorFrame({child_id}, {SurfaceRange(base::nullopt, child_id)}, std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_FALSE(parent_surface()->HasPendingFrame()); @@ -1673,8 +1673,8 @@ } // This test verifies that a child inherits its deadline from its dependent -// parent (embedder) surface. -TEST_F(SurfaceSynchronizationTest, DeadlineInheritance) { +// parent (embedder) if the deadline is shorter than child's deadline. +TEST_F(SurfaceSynchronizationTest, InheritShorterDeadline) { const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1); const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1); @@ -1684,7 +1684,7 @@ parent_support().SubmitCompositorFrame( parent_id1.local_surface_id(), MakeCompositorFrame( - {child_id1}, empty_surface_ranges(), + {child_id1}, {SurfaceRange(base::nullopt, child_id1)}, std::vector<TransferableResource>(), FrameDeadline(Now(), 2, BeginFrameArgs::DefaultInterval(), true))); @@ -1724,9 +1724,54 @@ EXPECT_FALSE(child_surface1()->has_deadline()); } +// This test verifies that in case of A embedding B embedding C, if the deadline +// of A is longer than the deadline of B, B's deadline is not extended. +TEST_F(SurfaceSynchronizationTest, ChildDeadlineNotExtendedByInheritance) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); + const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); + + // Parent blocks on Child1 with a deadline of 10. + parent_support().SubmitCompositorFrame( + parent_id.local_surface_id(), + MakeCompositorFrame({child_id1}, empty_surface_ranges(), + std::vector<TransferableResource>(), + MakeDeadline(10))); + + // Child1 blocks on Child2 with a deadline of 2. + child_support1().SubmitCompositorFrame( + child_id1.local_surface_id(), + MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)}, + std::vector<TransferableResource>(), + MakeDeadline(2))); + + // Both Parent and Child1 should be blocked because Child2 doesn't exist. + EXPECT_FALSE(parent_surface()->HasActiveFrame()); + EXPECT_TRUE(parent_surface()->HasPendingFrame()); + EXPECT_FALSE(child_surface1()->HasActiveFrame()); + EXPECT_TRUE(child_surface1()->HasPendingFrame()); + + // Send one BeginFrame. Both Parent and Child1 should be still blocked because + // Child2 still doesn't exist and Child1's deadline is 2. + SendNextBeginFrame(); + EXPECT_FALSE(parent_surface()->HasActiveFrame()); + EXPECT_TRUE(parent_surface()->HasPendingFrame()); + EXPECT_FALSE(child_surface1()->HasActiveFrame()); + EXPECT_TRUE(child_surface1()->HasPendingFrame()); + + // Send one more BeginFrame. Child1 should activate by deadline, and parent + // will consequenctly activates. This wouldn't happen if Child1's deadline was + // extended to match Parent's deadline. + SendNextBeginFrame(); + EXPECT_TRUE(parent_surface()->HasActiveFrame()); + EXPECT_FALSE(parent_surface()->HasPendingFrame()); + EXPECT_TRUE(child_surface1()->HasActiveFrame()); + EXPECT_FALSE(child_surface1()->HasPendingFrame()); +} + // This test verifies that all surfaces within a dependency chain will -// ultimately inherit the same deadline even if the grandchild is available -// before the child. +// ultimately inherit the parent's shorter deadline even if the grandchild is +// available before the child. TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) { const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); @@ -1735,7 +1780,7 @@ display_support().SubmitCompositorFrame( display_id.local_surface_id(), - MakeCompositorFrame({parent_id}, empty_surface_ranges(), + MakeCompositorFrame({parent_id}, {SurfaceRange(base::nullopt, parent_id)}, std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(display_surface()->HasPendingFrame()); @@ -1749,9 +1794,9 @@ // surface and so it gets a separate deadline. child_support1().SubmitCompositorFrame( child_id.local_surface_id(), - MakeCompositorFrame({arbitrary_id}, empty_surface_ranges(), - std::vector<TransferableResource>(), - MakeDefaultDeadline())); + MakeCompositorFrame( + {arbitrary_id}, {SurfaceRange(base::nullopt, arbitrary_id)}, + std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(child_surface1()->HasPendingFrame()); EXPECT_FALSE(child_surface1()->HasActiveFrame()); EXPECT_TRUE(child_surface1()->has_deadline()); @@ -1761,7 +1806,7 @@ // assume the same deadline. parent_support().SubmitCompositorFrame( parent_id.local_surface_id(), - MakeCompositorFrame({child_id}, empty_surface_ranges(), + MakeCompositorFrame({child_id}, {SurfaceRange(base::nullopt, child_id)}, std::vector<TransferableResource>(), MakeDefaultDeadline())); EXPECT_TRUE(parent_surface()->HasPendingFrame());
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 50175d92..5c2be9f 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -72,15 +72,6 @@ deadline_ = std::move(deadline); } -void Surface::InheritActivationDeadlineFrom(Surface* surface) { - TRACE_EVENT1("viz", "Surface::InheritActivationDeadlineFrom", "FrameSinkId", - surface_id().frame_sink_id().ToString()); - DCHECK(deadline_); - DCHECK(surface->deadline_); - - deadline_->InheritFrom(*surface->deadline_); -} - void Surface::SetPreviousFrameSurface(Surface* surface) { DCHECK(surface && (HasActiveFrame() || HasPendingFrame())); previous_frame_surface_id_ = surface->surface_id(); @@ -224,8 +215,6 @@ uint64_t frame_index, base::ScopedClosureRunner frame_rejected_callback, PresentedCallback presented_callback) { - late_activation_dependencies_.clear(); - if (frame.size_in_pixels() != surface_info_.size_in_pixels() || frame.device_scale_factor() != surface_info_.device_scale_factor()) { TRACE_EVENT_INSTANT0("viz", "Surface invariants violation", @@ -382,7 +371,6 @@ // If a frame is being activated because of a deadline, then clear its set // of blockers. - late_activation_dependencies_ = std::move(activation_dependencies_); activation_dependencies_.clear(); frame_sink_id_dependencies_.clear(); ActivatePendingFrame(duration); @@ -453,8 +441,11 @@ SurfaceAllocationGroup* end_allocation_group = surface_manager_->GetOrCreateAllocationGroupForSurfaceId( surface_range.end()); - if (end_allocation_group) + if (end_allocation_group) { new_referenced_allocation_groups.push_back(end_allocation_group); + end_allocation_group->UpdateLastReferencedSurfaceAndMaybeActivate( + surface_range.end()); + } // Only reference the allocation group for the start of SurfaceRange if the // current referenced surface is a part of it. if (surface_range.HasDifferentEmbedTokens() && @@ -463,8 +454,11 @@ SurfaceAllocationGroup* start_allocation_group = surface_manager_->GetOrCreateAllocationGroupForSurfaceId( *surface_range.start()); - if (start_allocation_group) + if (start_allocation_group) { new_referenced_allocation_groups.push_back(start_allocation_group); + start_allocation_group->UpdateLastReferencedSurfaceAndMaybeActivate( + *surface_range.start()); + } } } UpdateReferencedAllocationGroups(std::move(new_referenced_allocation_groups)); @@ -534,6 +528,17 @@ FrameDeadline Surface::ResolveFrameDeadline( const CompositorFrame& current_frame) { + // If there is an embedder of this surface that has already activated, that + // means the embedder doesn't wish to block on this surface, i.e. either it + // had a zero deadline or its deadline has already passed. If we don't have an + // active frame already, active this frame immediately so we have something to + // show. + if (!HasActiveFrame() && + allocation_group_->GetLastReferencedSurfaceId().IsSameOrNewerThan( + surface_id())) { + return FrameDeadline::MakeZero(); + } + const base::Optional<uint32_t>& default_deadline = surface_manager_->activation_deadline_in_frames(); const FrameDeadline& deadline = current_frame.metadata.deadline; @@ -807,4 +812,12 @@ MarkAsDrawn(); } +void Surface::ActivatePendingFrameForInheritedDeadline() { + DCHECK(HasPendingFrame()); + // Deadline inheritance implies that this surface was blocking the embedder, + // so there shouldn't be an active frame. + DCHECK(!HasActiveFrame()); + ActivatePendingFrameForDeadline(base::nullopt); +} + } // namespace viz
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index 3422f1c1..b87e274 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -106,13 +106,6 @@ return deadline_->deadline_for_testing(); } - // Inherits the same deadline as the one specified by |surface|. A deadline - // may be set further out in order to avoid doing unnecessary work while a - // parent surface is blocked on dependencies. A deadline may be shortened - // in order to minimize guttering (by unblocking children blocked on their - // grandchildren sooner). - void InheritActivationDeadlineFrom(Surface* surface); - void SetPreviousFrameSurface(Surface* surface); // Increments the reference count on resources specified by |resources|. @@ -194,13 +187,6 @@ return activation_dependencies_; } - // Returns the set of activation dependencies that have been ignored because - // the last CompositorFrame was activated due to a deadline. Late - // dependencies activate immediately when they arrive. - const base::flat_set<SurfaceId>& late_activation_dependencies() const { - return late_activation_dependencies_; - } - bool HasActiveFrame() const { return active_frame_data_.has_value(); } bool HasPendingFrame() const { return pending_frame_data_.has_value(); } bool HasUndrawnActiveFrame() const { @@ -231,6 +217,10 @@ // Called when this surface is embedded by another Surface's CompositorFrame. void OnSurfaceDependencyAdded(); + // Called when the embedder of this surface has been activated and therefore + // this surface should activate too by deadline inheritance. + void ActivatePendingFrameForInheritedDeadline(); + private: struct SequenceNumbers { uint32_t parent_sequence_number = 0u; @@ -324,7 +314,6 @@ const bool block_activation_on_parent_; base::flat_set<SurfaceId> activation_dependencies_; - base::flat_set<SurfaceId> late_activation_dependencies_; // A map from FrameSinkIds of SurfaceIds that this surface depends on for // activation to the latest local_id associated with the given FrameSinkId
diff --git a/components/viz/service/surfaces/surface_allocation_group.cc b/components/viz/service/surfaces/surface_allocation_group.cc index 42b7d64e..33edcfa 100644 --- a/components/viz/service/surfaces/surface_allocation_group.cc +++ b/components/viz/service/surfaces/surface_allocation_group.cc
@@ -50,6 +50,24 @@ MaybeMarkForDestruction(); } +void SurfaceAllocationGroup::UpdateLastReferencedSurfaceAndMaybeActivate( + const SurfaceId& surface_id) { + DCHECK_EQ(submitter_, surface_id.frame_sink_id()); + DCHECK_EQ(embed_token_, surface_id.local_surface_id().embed_token()); + if (last_referenced_surface_id_.is_valid() && + last_referenced_surface_id_.IsSameOrNewerThan(surface_id)) { + return; + } + last_referenced_surface_id_ = surface_id; + auto it = FindLatestSurfaceUpTo(surface_id); + if (it != surfaces_.end() && !(*it)->HasActiveFrame()) + (*it)->ActivatePendingFrameForInheritedDeadline(); +} + +const SurfaceId& SurfaceAllocationGroup::GetLastReferencedSurfaceId() { + return last_referenced_surface_id_; +} + Surface* SurfaceAllocationGroup::FindLatestActiveSurfaceInRange( const SurfaceRange& range) const { // If the embed token of the end of the SurfaceRange matches that of this @@ -57,10 +75,10 @@ // end, then check that it's not older than start. if (range.end().local_surface_id().embed_token() == embed_token_) { DCHECK_EQ(submitter_, range.end().frame_sink_id()); - Surface* result = FindOlderOrEqual(range.end()); - if (result && - (!range.start() || !range.start()->IsNewerThan(result->surface_id()))) { - return result; + auto it = FindLatestActiveSurfaceUpTo(range.end()); + if (it != surfaces_.end() && + (!range.start() || !range.start()->IsNewerThan((*it)->surface_id()))) { + return *it; } else { return nullptr; } @@ -94,22 +112,23 @@ embedder->OnChildActivatedForActiveFrame(surface->surface_id()); } -Surface* SurfaceAllocationGroup::FindOlderOrEqual( +std::vector<Surface*>::const_iterator +SurfaceAllocationGroup::FindLatestSurfaceUpTo( const SurfaceId& surface_id) const { DCHECK_EQ(submitter_, surface_id.frame_sink_id()); DCHECK_EQ(embed_token_, surface_id.local_surface_id().embed_token()); // Return early if there are no surfaces in this group. if (surfaces_.empty()) - return nullptr; + return surfaces_.end(); // If even the first surface is newer than |surface_id|, we can't find a // surface that is older than or equal to |surface_id|. if (surfaces_[0]->surface_id().IsNewerThan(surface_id)) - return nullptr; + return surfaces_.end(); - // Perform a binary search the find the latest active surface that is older - // than or equal to |surface_id|. + // Perform a binary search the find the latest surface that is older than or + // equal to |surface_id|. int begin = 0; int end = surfaces_.size(); while (end - begin > 1) { @@ -120,17 +139,27 @@ begin = avg; } - // We have found the latest surface. Now keep iterating back until we find an - // active surface. Normally, there is only one pending surface at a time, so - // this shouldn't take more than two iterations. - for (; begin >= 0; --begin) { - if (surfaces_[begin]->HasActiveFrame()) - return surfaces_[begin]; + return surfaces_.begin() + begin; +} + +std::vector<Surface*>::const_iterator +SurfaceAllocationGroup::FindLatestActiveSurfaceUpTo( + const SurfaceId& surface_id) const { + // Start from the last older or equal surface and keep iterating back until we + // find an active surface. Normally, there is only one pending surface at a + // time this shouldn't take more than two iterations. + auto it = FindLatestSurfaceUpTo(surface_id); + + if (it == surfaces_.end()) + return surfaces_.end(); + + for (; it >= surfaces_.begin(); --it) { + if ((*it)->HasActiveFrame()) + return it; } - // No active surface was found, so return null. - DCHECK_EQ(-1, begin); - return nullptr; + // No active surface was found. + return surfaces_.end(); } void SurfaceAllocationGroup::MaybeMarkForDestruction() {
diff --git a/components/viz/service/surfaces/surface_allocation_group.h b/components/viz/service/surfaces/surface_allocation_group.h index 8434dee..6b3d08f 100644 --- a/components/viz/service/surfaces/surface_allocation_group.h +++ b/components/viz/service/surfaces/surface_allocation_group.h
@@ -59,6 +59,15 @@ // surface in this allocation group. void UnregisterActiveEmbedder(Surface* surface); + // Called by an active embedder when its CompositorFrame references a surface + // in this allocation group. |surface_id| or the last surface prior to it will + // be forcefully activated due to deadline inheritance. + void UpdateLastReferencedSurfaceAndMaybeActivate(const SurfaceId& surface_id); + + // Returns the last SurfaceId in this allocation group that was ever + // referenced. + const SurfaceId& GetLastReferencedSurfaceId(); + // Returns the latest active surface in the given range that is a part of this // allocation group. The embed token of at least one end of the range must // match the embed token of this group. @@ -74,9 +83,16 @@ } private: - // Helper method for FindLatestActiveSurfaceInRange. Returns the latest active - // surface whose SurfaceId is older than or equal to |surface_id|. - Surface* FindOlderOrEqual(const SurfaceId& surface_id) const; + // Returns an iterator to the latest surface in |surfaces_| whose SurfaceId is + // older than or equal to |surface_id|. The returned surface may not be active + // yet. + std::vector<Surface*>::const_iterator FindLatestSurfaceUpTo( + const SurfaceId& surface_id) const; + + // Returns an iterator to the latest active surface in |surfaces_| whose + // SurfaceId is older than or equal to |surface_id|. + std::vector<Surface*>::const_iterator FindLatestActiveSurfaceUpTo( + const SurfaceId& surface_id) const; // Notifies SurfaceManager if this allocation group is ready for destruction // (see IsReadyToDestroy() for the requirements). @@ -104,6 +120,10 @@ // ready to be destroyed. SurfaceManager* const surface_manager_; + // The last SurfaceId of this allocation group that was ever referenced by an + // active embedder. + SurfaceId last_referenced_surface_id_; + DISALLOW_COPY_AND_ASSIGN(SurfaceAllocationGroup); };
diff --git a/components/viz/service/surfaces/surface_dependency_deadline.cc b/components/viz/service/surfaces/surface_dependency_deadline.cc index 67097d6..b2d05f1 100644 --- a/components/viz/service/surfaces/surface_dependency_deadline.cc +++ b/components/viz/service/surfaces/surface_dependency_deadline.cc
@@ -51,22 +51,6 @@ return duration; } -void SurfaceDependencyDeadline::InheritFrom( - const SurfaceDependencyDeadline& other) { - if (*this == other) - return; - - base::Optional<base::TimeDelta> duration = Cancel(); - last_begin_frame_args_ = other.last_begin_frame_args_; - begin_frame_source_ = other.begin_frame_source_; - deadline_ = other.deadline_; - if (deadline_) { - if (!duration) - start_time_ = tick_clock_->NowTicks(); - begin_frame_source_->AddObserver(this); - } -} - bool SurfaceDependencyDeadline::operator==( const SurfaceDependencyDeadline& other) const { return begin_frame_source_ == other.begin_frame_source_ &&
diff --git a/components/viz/service/surfaces/surface_dependency_deadline.h b/components/viz/service/surfaces/surface_dependency_deadline.h index 61ce0c0..4601b6e1 100644 --- a/components/viz/service/surfaces/surface_dependency_deadline.h +++ b/components/viz/service/surfaces/surface_dependency_deadline.h
@@ -42,9 +42,6 @@ return deadline_; } - // Takes on the same BeginFrameSource and deadline as |other|. - void InheritFrom(const SurfaceDependencyDeadline& other); - bool operator==(const SurfaceDependencyDeadline& other) const; bool operator!=(const SurfaceDependencyDeadline& other) const { return !(*this == other);
diff --git a/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc b/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc index 9df70c0..567ee25e 100644 --- a/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc +++ b/components/viz/service/surfaces/surface_dependency_deadline_unittest.cc
@@ -136,64 +136,4 @@ EXPECT_TRUE(deadline()->has_deadline()); } -// This test verifies that inheriting a deadline with no pre-existing deadline -// sets up the start time of the event to the time of inheritance. -TEST_F(SurfaceDependencyDeadlineTest, InheritDeadline) { - FrameDeadline frame_deadline = MakeDefaultDeadline(); - SendLateBeginFrame(1u); - EXPECT_TRUE(deadline()->Set(frame_deadline)); - EXPECT_TRUE(deadline()->has_deadline()); - - SendLateBeginFrame(1u); - EXPECT_FALSE(deadline2()->has_deadline()); - deadline2()->InheritFrom(*deadline()); - EXPECT_TRUE(deadline()->has_deadline()); - EXPECT_EQ(deadline()->deadline_for_testing(), - deadline2()->deadline_for_testing()); - - base::Optional<base::TimeDelta> duration1 = deadline()->Cancel(); - base::Optional<base::TimeDelta> duration2 = deadline2()->Cancel(); - ASSERT_TRUE(duration1.has_value()); - ASSERT_TRUE(duration2.has_value()); - - // We inject time on BeginFrameSource::AddObserver and in practice we cannot - // know the exact difference in duration between two events a priori so we - // just verify that the first event was longer than the second. - EXPECT_GT(duration1, duration2); -} - -// This test verifies that if an active deadline object inherits a deadline -// from another object, it does not inherit the start time of the event. -TEST_F(SurfaceDependencyDeadlineTest, InheritDeadlineWithActiveDeadline) { - { - FrameDeadline frame_deadline = MakeDefaultDeadline(); - SendLateBeginFrame(1u); - EXPECT_TRUE(deadline()->Set(frame_deadline)); - EXPECT_TRUE(deadline()->has_deadline()); - } - - { - FrameDeadline frame_deadline = MakeDefaultDeadline(); - SendLateBeginFrame(1u); - // deadline2's start time is later than deadline2. - EXPECT_TRUE(deadline2()->Set(frame_deadline)); - EXPECT_TRUE(deadline2()->has_deadline()); - } - - deadline()->InheritFrom(*deadline2()); - EXPECT_TRUE(deadline()->has_deadline()); - EXPECT_EQ(deadline()->deadline_for_testing(), - deadline2()->deadline_for_testing()); - - base::Optional<base::TimeDelta> duration1 = deadline()->Cancel(); - base::Optional<base::TimeDelta> duration2 = deadline2()->Cancel(); - ASSERT_TRUE(duration1.has_value()); - ASSERT_TRUE(duration2.has_value()); - - // We inject time on BeginFrameSource::AddObserver and in practice we cannot - // know the exact difference in duration between two events a priori so we - // just verify that the first event was longer than the second. - EXPECT_GT(duration1, duration2); -} - } // namespace viz
diff --git a/components/viz/service/surfaces/surface_dependency_tracker.cc b/components/viz/service/surfaces/surface_dependency_tracker.cc index 55542b4..0f06d6e 100644 --- a/components/viz/service/surfaces/surface_dependency_tracker.cc +++ b/components/viz/service/surfaces/surface_dependency_tracker.cc
@@ -32,11 +32,6 @@ void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { DCHECK(surface->HasPendingFrame()); - if (IsSurfaceLate(surface)) { - ActivateLateSurfaceSubtree(surface); - return; - } - // Activation dependencies that aren't currently known to the surface manager // or do not have an active CompositorFrame block this frame. for (const SurfaceId& surface_id : surface->activation_dependencies()) { @@ -46,8 +41,6 @@ surface->surface_id()); } } - - UpdateSurfaceDeadline(surface); } bool SurfaceDependencyTracker::HasSurfaceBlockedOn( @@ -58,10 +51,6 @@ } void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { - if (!surface->late_activation_dependencies().empty()) - surfaces_with_missing_dependencies_.insert(surface->surface_id()); - else - surfaces_with_missing_dependencies_.erase(surface->surface_id()); NotifySurfaceIdAvailable(surface->surface_id()); // We treat an activation (by deadline) as being the equivalent of a parent // embedding the surface. @@ -133,8 +122,6 @@ } void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { - surfaces_with_missing_dependencies_.erase(surface->surface_id()); - base::flat_set<FrameSinkId> removed_dependencies; for (const SurfaceId& surface_id : surface->activation_dependencies()) removed_dependencies.insert(surface_id.frame_sink_id()); @@ -155,63 +142,6 @@ OnSurfaceDependencyAdded(SurfaceId::MaxSequenceId(frame_sink_id)); } -void SurfaceDependencyTracker::ActivateLateSurfaceSubtree(Surface* surface) { - DCHECK(surface->HasPendingFrame()); - - base::flat_set<SurfaceId> late_dependencies( - surface->activation_dependencies()); - for (const SurfaceId& surface_id : late_dependencies) { - Surface* dependency = surface_manager_->GetSurfaceForId(surface_id); - if (dependency && dependency->HasPendingFrame()) - ActivateLateSurfaceSubtree(dependency); - } - - surface->ActivatePendingFrameForDeadline(base::nullopt); -} - -void SurfaceDependencyTracker::UpdateSurfaceDeadline(Surface* surface) { - DCHECK(surface->HasPendingFrame()); - - // Inherit the deadline from the first parent blocked on this surface. - auto it = blocked_surfaces_from_dependency_.find( - surface->surface_id().frame_sink_id()); - if (it != blocked_surfaces_from_dependency_.end()) { - const base::flat_set<SurfaceId>& dependent_parent_ids = it->second; - for (const SurfaceId& parent_id : dependent_parent_ids) { - Surface* parent = surface_manager_->GetSurfaceForId(parent_id); - if (parent && parent->has_deadline() && - parent->activation_dependencies().count(surface->surface_id())) { - surface->InheritActivationDeadlineFrom(parent); - break; - } - } - } - - DCHECK(!surface_manager_->activation_deadline_in_frames() || - surface->has_deadline()); - - // Recursively propagate the newly set deadline to children. - base::flat_set<SurfaceId> activation_dependencies( - surface->activation_dependencies()); - for (const SurfaceId& surface_id : activation_dependencies) { - Surface* dependency = surface_manager_->GetSurfaceForId(surface_id); - if (dependency && dependency->HasPendingFrame()) - UpdateSurfaceDeadline(dependency); - } -} - -bool SurfaceDependencyTracker::IsSurfaceLate(Surface* surface) { - for (const SurfaceId& surface_id : surfaces_with_missing_dependencies_) { - Surface* activated_surface = surface_manager_->GetSurfaceForId(surface_id); - DCHECK(activated_surface->HasActiveFrame()); - if (activated_surface->late_activation_dependencies().count( - surface->surface_id())) { - return true; - } - } - return false; -} - void SurfaceDependencyTracker::NotifySurfaceIdAvailable( const SurfaceId& surface_id) { auto it = blocked_surfaces_from_dependency_.find(surface_id.frame_sink_id());
diff --git a/components/viz/service/surfaces/surface_dependency_tracker.h b/components/viz/service/surfaces/surface_dependency_tracker.h index e8fbd88..eacb163 100644 --- a/components/viz/service/surfaces/surface_dependency_tracker.h +++ b/components/viz/service/surfaces/surface_dependency_tracker.h
@@ -51,19 +51,6 @@ void OnFrameSinkInvalidated(const FrameSinkId& frame_sink_id); private: - // If |surface| has a dependent embedder frame, then it inherits the parent's - // deadline and propagates that deadline to children. - void UpdateSurfaceDeadline(Surface* surface); - - // Activates this |surface| and its entire dependency tree. - void ActivateLateSurfaceSubtree(Surface* surface); - - // Indicates whether |surface| is late. A surface is late if it hasn't had its - // first activation before a embedder is forced to activate its own - // CompositorFrame. A surface may no longer be considered late if the set - // of activation dependencies for dependent surfaces change. - bool IsSurfaceLate(Surface* surface); - // Informs all Surfaces with pending frames blocked on the provided // |surface_id| that there is now an active frame available in Surface // corresponding to |surface_id|. @@ -81,10 +68,6 @@ std::unordered_map<FrameSinkId, base::flat_set<SurfaceId>, FrameSinkIdHash> surfaces_blocked_on_parent_by_frame_sink_id_; - // The set of SurfaceIds corresponding to Surfaces that have active - // CompositorFrames with missing dependencies. - base::flat_set<SurfaceId> surfaces_with_missing_dependencies_; - DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyTracker); };
diff --git a/components/viz/test/fake_display_client.cc b/components/viz/test/fake_display_client.cc index 6c7d89a..9f41365 100644 --- a/components/viz/test/fake_display_client.cc +++ b/components/viz/test/fake_display_client.cc
@@ -9,9 +9,6 @@ FakeDisplayClient::FakeDisplayClient() : binding_(this) {} FakeDisplayClient::~FakeDisplayClient() = default; -void FakeDisplayClient::DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>&) {} - mojom::DisplayClientPtr FakeDisplayClient::BindInterfacePtr() { mojom::DisplayClientPtr ptr; binding_.Bind(MakeRequest(&ptr));
diff --git a/components/viz/test/fake_display_client.h b/components/viz/test/fake_display_client.h index 3ac840f..c9b55eb 100644 --- a/components/viz/test/fake_display_client.h +++ b/components/viz/test/fake_display_client.h
@@ -21,9 +21,6 @@ mojom::DisplayClientPtr BindInterfacePtr(); // mojom::DisplayClient implementation. - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>&) override; - #if defined(OS_MACOSX) void OnDisplayReceivedCALayerParams( const gfx::CALayerParams& ca_layer_params) override;
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc index ca59fcd..799d0b1 100644 --- a/components/viz/test/fake_skia_output_surface.cc +++ b/components/viz/test/fake_skia_output_surface.cc
@@ -4,6 +4,8 @@ #include "components/viz/test/fake_skia_output_surface.h" +#include <utility> + #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "components/viz/common/frame_sinks/copy_output_request.h" @@ -146,6 +148,7 @@ sk_sp<SkImage> FakeSkiaOutputSurface::MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); NOTIMPLEMENTED();
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h index 0d90c4f..5827cdb 100644 --- a/components/viz/test/fake_skia_output_surface.h +++ b/components/viz/test/fake_skia_output_surface.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_TEST_FAKE_SKIA_OUTPUT_SURFACE_H_ #include <memory> +#include <utility> #include <vector> #include "base/containers/flat_map.h" @@ -57,6 +58,7 @@ sk_sp<SkImage> MakePromiseSkImageFromYUV( std::vector<ResourceMetadata> metadatas, SkYUVColorSpace yuv_color_space, + sk_sp<SkColorSpace> dst_color_space, bool has_alpha) override; void SkiaSwapBuffers(OutputSurfaceFrame frame) override; SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
diff --git a/components/viz/test/mock_display_client.h b/components/viz/test/mock_display_client.h index ae05c43..4bc4d39f8 100644 --- a/components/viz/test/mock_display_client.h +++ b/components/viz/test/mock_display_client.h
@@ -21,8 +21,6 @@ mojom::DisplayClientPtr BindInterfacePtr(); // mojom::DisplayClient implementation. - MOCK_METHOD1(DidSwapAfterSnapshotRequestReceived, - void(const std::vector<ui::LatencyInfo>&)); #if defined(OS_MACOSX) MOCK_METHOD1(OnDisplayReceivedCALayerParams, void(const gfx::CALayerParams&)); #endif
diff --git a/components/viz/test/test_context_support.cc b/components/viz/test/test_context_support.cc index bf92ee2..e0640c4 100644 --- a/components/viz/test/test_context_support.cc +++ b/components/viz/test/test_context_support.cc
@@ -132,6 +132,11 @@ NOTIMPLEMENTED(); return 0; } +bool TestContextSupport::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const { + NOTIMPLEMENTED(); + return false; +} bool TestContextSupport::HasGrContextSupport() const { return true;
diff --git a/components/viz/test/test_context_support.h b/components/viz/test/test_context_support.h index c69c4437..e42596f13 100644 --- a/components/viz/test/test_context_support.h +++ b/components/viz/test/test_context_support.h
@@ -77,6 +77,8 @@ void DeleteTransferCacheEntry(uint32_t entry_type, uint32_t entry_id) override; unsigned int GetTransferBufferFreeSize() const override; + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const override; bool HasGrContextSupport() const override; void SetGrContext(GrContext* gr) override; void WillCallGLFromSkia() override;
diff --git a/components/viz/test/test_layer_tree_frame_sink.h b/components/viz/test/test_layer_tree_frame_sink.h index e54b0ec1..ae98278 100644 --- a/components/viz/test/test_layer_tree_frame_sink.h +++ b/components/viz/test/test_layer_tree_frame_sink.h
@@ -119,8 +119,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override; void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override; - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override {} const std::set<SharedBitmapId>& owned_bitmaps() const { return owned_bitmaps_;
diff --git a/content/browser/DEPS b/content/browser/DEPS index 2167d47..893be17 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -104,7 +104,6 @@ "+third_party/blink/public/platform/web_text_input_type.h", "+third_party/blink/public/platform/mac/web_scrollbar_theme.h", "+third_party/blink/public/platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom.h", - "+third_party/blink/public/platform/modules/idle/idle_manager.mojom.h", "+third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h", "+third_party/blink/public/platform/modules/notifications/web_notification_constants.h", "+third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h", @@ -137,11 +136,7 @@ "+third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h", "+third_party/blink/public/platform/modules/notifications/notification_service.mojom.h", "+third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom.h", - "+third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h", - "+third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h", "+third_party/blink/public/platform/modules/websockets/websocket.mojom.h", - "+third_party/blink/public/web/commit_result.mojom.h", - "+third_party/blink/public/web/devtools_frontend.mojom.h", # DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!! # See https://sites.google.com/a/chromium.org/dev/developers/content-module
diff --git a/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/content/browser/accessibility/accessibility_auralinux_browsertest.cc index 15340ebf..ab4aad7 100644 --- a/content/browser/accessibility/accessibility_auralinux_browsertest.cc +++ b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -232,6 +232,10 @@ } } +#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 30, 0) +#define ATK_230 +#endif + IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest, TestCharacterExtentsWithInvalidArguments) { AtkText* atk_text = SetUpSampleParagraph(); @@ -247,12 +251,14 @@ EXPECT_EQ(0, width); EXPECT_EQ(0, height); +#ifdef ATK_230 atk_text_get_character_extents(atk_text, invalid_offset, &x, &y, &width, &height, ATK_XY_PARENT); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, width); EXPECT_EQ(0, height); +#endif // ATK_230 atk_text_get_character_extents(atk_text, invalid_offset, &x, &y, &width, &height, ATK_XY_WINDOW); @@ -271,12 +277,14 @@ EXPECT_EQ(0, width); EXPECT_EQ(0, height); +#ifdef ATK_230 atk_text_get_character_extents(atk_text, invalid_offset, &x, &y, &width, &height, ATK_XY_PARENT); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0, width); EXPECT_EQ(0, height); +#endif // ATK_230 atk_text_get_character_extents(atk_text, invalid_offset, &x, &y, &width, &height, ATK_XY_WINDOW); @@ -289,7 +297,9 @@ AtkCoordType kCoordinateTypes[] = { ATK_XY_SCREEN, ATK_XY_WINDOW, +#ifdef ATK_230 ATK_XY_PARENT, +#endif // ATK_230 }; IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
diff --git a/content/browser/accessibility/accessibility_event_recorder_uia_win.cc b/content/browser/accessibility/accessibility_event_recorder_uia_win.cc index ecf52314..a18af4c7 100644 --- a/content/browser/accessibility/accessibility_event_recorder_uia_win.cc +++ b/content/browser/accessibility/accessibility_event_recorder_uia_win.cc
@@ -168,7 +168,6 @@ // remaining events to our owner. { base::AutoLock lock{on_event_lock_}; - CHECK_LE(event_logs_.size(), 2u); if (event_logs_.size() == 1) { // Only received events on a single thread... perhaps the bug was fixed? // Forward all events. @@ -202,6 +201,27 @@ owner_->OnEvent(*it1++); while (it2 < events_thread2.end()) owner_->OnEvent(*it2++); + } else { + // Typically we'll get events on exactly two threads (one directly from + // UIA, the second from RPC), but sometimes RPC will split its events + // across different threads. + // + // Unfortunately, there is no robust method of eliminating duplicates in + // this case. Tests with intentional duplicates could run afoul of this + // logic in rare scenarios; it is recommended that intentionally + // duplicated events be avoided in tests, when possible. + std::vector<std::string> combined; + for (auto&& log : event_logs_) + combined.insert(combined.end(), log.second.begin(), log.second.end()); + std::sort(combined.begin(), combined.end()); + + std::string last_event; + for (auto&& event : combined) { + if (last_event != event) + owner_->OnEvent(last_event = event); + else + last_event = {}; + } } }
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc index 5f444cea..3f8627d 100644 --- a/content/browser/accessibility/accessibility_win_browsertest.cc +++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -2794,7 +2794,6 @@ // This test simulates a scenario where RenderWidgetHostViewAura::SetSize // is not called again after its window is added to the root window. // Ensure that we still get a legacy HWND for accessibility. - ASSERT_TRUE(embedded_test_server()->Start()); WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); @@ -2806,13 +2805,13 @@ // RenderWidgetHostViewAura with a null parent view. web_contents_view_aura->set_init_rwhv_with_null_parent_for_testing(true); - // Navigate to a new page and wait for the accessibility tree to load. - AccessibilityNotificationWaiter waiter(shell()->web_contents(), - ui::kAXModeComplete, + // Enable accessibility. + AccessibilityNotificationWaiter waiter(web_contents, ui::kAXModeComplete, ax::mojom::Event::kLoadComplete); + + // Navigate to a new page. NavigateToURL(shell(), embedded_test_server()->GetURL( "/accessibility/html/article.html")); - waiter.WaitForNotification(); // At this point the root of the accessibility tree shouldn't have an HWND // because we never gave a parent window to the RWHVA. @@ -2825,6 +2824,8 @@ // an HWND for accessibility now. web_contents_view->GetNativeView()->AddChild( web_contents->GetRenderWidgetHostView()->GetNativeView()); + // The load event will only fire after the page is attached. + waiter.WaitForNotification(); ASSERT_NE(nullptr, manager->GetParentHWND()); } @@ -3242,4 +3243,5 @@ EXPECT_EQ(VT_BOOL, result.type()); EXPECT_EQ(VARIANT_FALSE, result.ptr()->boolVal); } + } // namespace content
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 1d7c18b..fe236ed1 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -142,15 +142,11 @@ } bool BrowserAccessibility::IsTextOnlyObject() const { - return GetRole() == ax::mojom::Role::kStaticText || - GetRole() == ax::mojom::Role::kLineBreak || - GetRole() == ax::mojom::Role::kInlineTextBox; + return node_ && node_->IsText(); } bool BrowserAccessibility::IsLineBreakObject() const { - return GetRole() == ax::mojom::Role::kLineBreak || - (IsTextOnlyObject() && PlatformGetParent() && - PlatformGetParent()->GetRole() == ax::mojom::Role::kLineBreak); + return node_ && node_->IsLineBreak(); } BrowserAccessibility* BrowserAccessibility::PlatformGetChild( @@ -824,7 +820,7 @@ } bool BrowserAccessibility::IsClickable() const { - return ui::IsClickable(GetRole()); + return ui::IsClickable(GetData()); } bool BrowserAccessibility::IsPlainTextField() const {
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index e2e9c54..761b7832 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -515,9 +515,7 @@ strings.push_back(name); } - if (GetData().GetNameFrom() != ax::mojom::NameFrom::kPlaceholder && - GetData().GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom) != - static_cast<int32_t>(ax::mojom::DescriptionFrom::kPlaceholder)) { + if (GetData().GetNameFrom() != ax::mojom::NameFrom::kPlaceholder) { base::string16 placeholder = GetString16Attribute(ax::mojom::StringAttribute::kPlaceholder); if (!placeholder.empty())
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 8df04f44f..17dc627 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -1380,14 +1380,6 @@ ax::mojom::StringAttribute::kName); } - ax::mojom::DescriptionFrom descriptionFrom = - static_cast<ax::mojom::DescriptionFrom>( - owner_->GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom)); - if (descriptionFrom == ax::mojom::DescriptionFrom::kPlaceholder) { - return NSStringForStringAttribute(owner_, - ax::mojom::StringAttribute::kDescription); - } - return NSStringForStringAttribute(owner_, ax::mojom::StringAttribute::kPlaceholder); }
diff --git a/content/browser/accessibility/browser_accessibility_position.cc b/content/browser/accessibility/browser_accessibility_position.cc index 8d11df28..9eedf6d 100644 --- a/content/browser/accessibility/browser_accessibility_position.cc +++ b/content/browser/accessibility/browser_accessibility_position.cc
@@ -98,12 +98,6 @@ return manager->GetFromID(node_id); } -int BrowserAccessibilityPosition::MaxTextOffset() const { - if (IsNullPosition()) - return INVALID_OFFSET; - return static_cast<int>(GetInnerText().length()); -} - // On some platforms, most objects are represented in the text of their parents // with a special (embedded object) character and not with their actual text // contents.
diff --git a/content/browser/accessibility/browser_accessibility_position.h b/content/browser/accessibility/browser_accessibility_position.h index 536e8d7..1cdfb28 100644 --- a/content/browser/accessibility/browser_accessibility_position.h +++ b/content/browser/accessibility/browser_accessibility_position.h
@@ -42,7 +42,6 @@ void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override; BrowserAccessibility* GetNodeInTree(AXTreeID tree_id, int32_t node_id) const override; - int MaxTextOffset() const override; int MaxTextOffsetInParent() const override; bool IsInWhiteSpace() const override; std::vector<int32_t> GetWordStartOffsets() const override;
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc index e935e7c..f4ce89ed 100644 --- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc +++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -542,4 +542,66 @@ TestLocalizedLandmarkType(16, ax::mojom::Role::kSearch, "search"); } +IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest, + TooltipStringAttributeMutuallyExclusiveOfNameFromTitle) { + const char url_str[] = + "data:text/html," + "<!doctype html>" + "<input type='text' title='title'>" + "<input type='text' title='title' aria-labelledby='inputlabel'>" + "<div id='inputlabel'>aria-labelledby</div>"; + GURL url(url_str); + NavigateToURL(shell(), url); + + const ui::AXTree& tree = GetAXTree(); + const ui::AXNode* root = tree.root(); + const ui::AXNode* input1 = root->ChildAtIndex(0); + const ui::AXNode* input2 = root->ChildAtIndex(1); + + EXPECT_EQ(static_cast<int>(ax::mojom::NameFrom::kTitle), + GetIntAttr(input1, ax::mojom::IntAttribute::kNameFrom)); + EXPECT_STREQ("title", + GetAttr(input1, ax::mojom::StringAttribute::kName).c_str()); + EXPECT_STREQ("", + GetAttr(input1, ax::mojom::StringAttribute::kTooltip).c_str()); + + EXPECT_EQ(static_cast<int>(ax::mojom::NameFrom::kRelatedElement), + GetIntAttr(input2, ax::mojom::IntAttribute::kNameFrom)); + EXPECT_STREQ("aria-labelledby", + GetAttr(input2, ax::mojom::StringAttribute::kName).c_str()); + EXPECT_STREQ("title", + GetAttr(input2, ax::mojom::StringAttribute::kTooltip).c_str()); +} + +IN_PROC_BROWSER_TEST_F( + CrossPlatformAccessibilityBrowserTest, + PlaceholderStringAttributeMutuallyExclusiveOfNameFromPlaceholder) { + const char url_str[] = + "data:text/html," + "<!doctype html>" + "<input type='text' placeholder='placeholder'>" + "<input type='text' placeholder='placeholder' aria-label='label'>"; + GURL url(url_str); + NavigateToURL(shell(), url); + + const ui::AXTree& tree = GetAXTree(); + const ui::AXNode* root = tree.root(); + const ui::AXNode* group = root->ChildAtIndex(0); + const ui::AXNode* input1 = group->ChildAtIndex(0); + const ui::AXNode* input2 = group->ChildAtIndex(1); + + using ax::mojom::StringAttribute; + + EXPECT_EQ(static_cast<int>(ax::mojom::NameFrom::kPlaceholder), + GetIntAttr(input1, ax::mojom::IntAttribute::kNameFrom)); + EXPECT_STREQ("placeholder", GetAttr(input1, StringAttribute::kName).c_str()); + EXPECT_STREQ("", GetAttr(input1, StringAttribute::kPlaceholder).c_str()); + + EXPECT_EQ(static_cast<int>(ax::mojom::NameFrom::kAttribute), + GetIntAttr(input2, ax::mojom::IntAttribute::kNameFrom)); + EXPECT_STREQ("label", GetAttr(input2, StringAttribute::kName).c_str()); + EXPECT_STREQ("placeholder", + GetAttr(input2, StringAttribute::kPlaceholder).c_str()); +} + } // namespace content
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index 9e1db80..72196c3 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -543,8 +543,18 @@ RunEventTest(FILE_PATH_LITERAL("tbody-focus.html")); } +// Even with the deflaking in WaitForAccessibilityTreeToContainNodeWithName, +// this test is still flaky on Windows. +// TODO(aboxhall, dmazzoni, meredithl): re-enable with better fix for above. +#if defined(OS_WIN) +#define MAYBE_AccessibilityEventsAriaSelectedChanged \ + DISABLED_AccessibilityEventsAriaSelectedChanged +#else +#define MAYBE_AccessibilityEventsAriaSelectedChanged \ + AccessibilityEventsAriaSelectedChanged +#endif IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - AccessibilityEventsAriaSelectedChanged) { + MAYBE_AccessibilityEventsAriaSelectedChanged) { RunEventTest(FILE_PATH_LITERAL("aria-selected-changed.html")); }
diff --git a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc index 241e5fa6..be09e2e 100644 --- a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc +++ b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -136,8 +136,9 @@ EXPECT_EQ(ax_child_frame_root->PlatformGetParent(), ax_iframe); } +// TODO(aboxhall): Flaky test, discuss with dmazzoni IN_PROC_BROWSER_TEST_F(MAYBE_SitePerProcessAccessibilityBrowserTest, - TwoCrossSiteNavigations) { + DISABLED_TwoCrossSiteNavigations) { // Enable full accessibility for all current and future WebContents. BrowserAccessibilityState::GetInstance()->EnableAccessibility();
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc index 6a50fbf9..0476075 100644 --- a/content/browser/appcache/appcache_subresource_url_factory.cc +++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -366,10 +366,19 @@ network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + // TODO(943887): Replace HasSecurityState() call with something that can + // preserve security state after process shutdown. The security state check + // is a temporary solution to avoid crashes when this method is run after the + // process associated with |appcache_host_->process_id()| has been destroyed. + // It temporarily restores the old behavior of always allowing access if the + // process is gone. + // See https://crbug.com/910287 for details. + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (request.request_initiator.has_value() && !request.request_initiator.value().opaque() && appcache_host_ && - !ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin( - appcache_host_->process_id(), request.request_initiator.value())) { + !policy->CanAccessDataForOrigin(appcache_host_->process_id(), + request.request_initiator.value()) && + policy->HasSecurityState(appcache_host_->process_id())) { const char* scheme_exception = GetContentClient() ->browser()
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc index 8bf8c6a..acc8941 100644 --- a/content/browser/appcache/appcache_update_url_loader_request.cc +++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -58,7 +58,8 @@ loader_factory_getter_->GetNetworkFactoryWithCORBEnabled() ->CreateLoaderAndStart( mojo::MakeRequest(&url_loader_), -1, -1, - network::mojom::kURLLoadOptionNone, request_, std::move(client), + network::mojom::kURLLoadOptionSendSSLInfoWithResponse, request_, + std::move(client), net::MutableNetworkTrafficAnnotationTag(kAppCacheTrafficAnnotation)); }
diff --git a/content/browser/broadcast_channel/broadcast_channel_provider.cc b/content/browser/broadcast_channel/broadcast_channel_provider.cc index ba5a5d85..8a8f6c69 100644 --- a/content/browser/broadcast_channel/broadcast_channel_provider.cc +++ b/content/browser/broadcast_channel/broadcast_channel_provider.cc
@@ -79,7 +79,15 @@ blink::mojom::BroadcastChannelClientAssociatedRequest connection) { RenderProcessHostId process_id = bindings_.dispatch_context(); auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); - if (!policy->CanAccessDataForOrigin(process_id, origin)) { + + // TODO(943887): Replace HasSecurityState() call with something that can + // preserve security state after process shutdown. The security state check + // is a temporary solution to avoid crashes when this method is run after the + // process associated with |process_id| has been destroyed. It temporarily + // restores the old behavior of always allowing access if the process is gone. + // See https://crbug.com/943027 for details. + if (!policy->CanAccessDataForOrigin(process_id, origin) && + policy->HasSecurityState(process_id)) { mojo::ReportBadMessage("BROADCAST_CHANNEL_INVALID_ORIGIN"); return; }
diff --git a/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc b/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc index 619c792..f2ef2b2c 100644 --- a/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc +++ b/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
@@ -147,16 +147,15 @@ auto buffer = base::MakeRefCounted<network::MojoToNetIOBuffer>( pending_read_.get(), bytes_to_read); - net::CompletionCallback cache_write_callback = - base::AdaptCallbackForRepeating( - base::BindOnce(&CacheStorageBlobToDiskCache::DidWriteDataToEntry, - weak_ptr_factory_.GetWeakPtr(), bytes_to_read)); + net::CompletionOnceCallback cache_write_callback = + base::BindOnce(&CacheStorageBlobToDiskCache::DidWriteDataToEntry, + weak_ptr_factory_.GetWeakPtr(), bytes_to_read); - int rv = entry_->WriteData(disk_cache_body_index_, cache_entry_offset_, - buffer.get(), bytes_to_read, cache_write_callback, - true /* truncate */); + int rv = entry_->WriteData( + disk_cache_body_index_, cache_entry_offset_, buffer.get(), bytes_to_read, + std::move(cache_write_callback), true /* truncate */); if (rv != net::ERR_IO_PENDING) - std::move(cache_write_callback).Run(rv); + CacheStorageBlobToDiskCache::DidWriteDataToEntry(bytes_to_read, rv); } } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index e91bb9be..a1dd242 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -46,7 +46,7 @@ #include "content/public/common/referrer_type_converters.h" #include "crypto/hmac.h" #include "crypto/symmetric_key.h" -#include "net/base/completion_callback.h" +#include "net/base/completion_repeating_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" @@ -270,7 +270,10 @@ base::MakeRefCounted<net::IOBufferWithSize>( entry->GetDataSize(CacheStorageCache::INDEX_HEADERS)); - net::CompletionCallback read_header_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |callback| is not + // copyable. + net::CompletionRepeatingCallback read_header_callback = base::AdaptCallbackForRepeating(base::BindOnce( ReadMetadataDidReadMetadata, entry, std::move(callback), buffer)); @@ -994,7 +997,11 @@ // There is no need to scan the entire backend, just open the exact // URL. disk_cache::Entry** entry_ptr = &query_cache_context->enumerated_entry; - net::CompletionCallback open_entry_callback = + + // Create a callback that is copyable, even though it can only be called + // once. BindRepeating() cannot be used directly because + // |query_cache_context| is not copyable. + net::CompletionRepeatingCallback open_entry_callback = base::AdaptCallbackForRepeating(base::BindOnce( &CacheStorageCache::QueryCacheDidOpenFastPath, weak_ptr_factory_.GetWeakPtr(), std::move(query_cache_context))); @@ -1048,7 +1055,11 @@ disk_cache::Backend::Iterator& iterator = *query_cache_context->backend_iterator; disk_cache::Entry** enumerated_entry = &query_cache_context->enumerated_entry; - net::CompletionCallback open_entry_callback = + + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |query_cache_context| is + // not copyable. + net::CompletionRepeatingCallback open_entry_callback = base::AdaptCallbackForRepeating(base::BindOnce( &CacheStorageCache::QueryCacheFilterEntry, weak_ptr_factory_.GetWeakPtr(), std::move(query_cache_context))); @@ -1378,11 +1389,16 @@ std::unique_ptr<disk_cache::Entry*> scoped_entry_ptr( new disk_cache::Entry*()); disk_cache::Entry** entry_ptr = scoped_entry_ptr.get(); - net::CompletionCallback open_entry_callback = base::AdaptCallbackForRepeating( - base::BindOnce(&CacheStorageCache::WriteSideDataDidOpenEntry, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - expected_response_time, trace_id, buffer, buf_len, - std::move(scoped_entry_ptr))); + + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |callback| and + // |scoped_entry_ptr| are not copyable. + net::CompletionRepeatingCallback open_entry_callback = + base::AdaptCallbackForRepeating( + base::BindOnce(&CacheStorageCache::WriteSideDataDidOpenEntry, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + expected_response_time, trace_id, buffer, buf_len, + std::move(scoped_entry_ptr))); // Use LOWEST priority here as writing side data is less important than // loading resources on the page. @@ -1444,7 +1460,10 @@ if (ShouldPadResourceSize(response.get())) side_data_size_before_write = entry->GetDataSize(INDEX_SIDE_DATA); - net::CompletionCallback write_side_data_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |callback|, |entry| and + // |response| are not copyable. + net::CompletionRepeatingCallback write_side_data_callback = base::AdaptCallbackForRepeating(base::BindOnce( &CacheStorageCache::WriteSideDataDidWrite, weak_ptr_factory_.GetWeakPtr(), std::move(callback), std::move(entry), @@ -1581,7 +1600,10 @@ const blink::mojom::FetchAPIRequest& request_ = *(put_context->request); disk_cache::Backend* backend_ptr = backend_.get(); - net::CompletionCallback create_entry_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |scoped_entry_ptr| and + // |put_context| are not copyable. + net::CompletionRepeatingCallback create_entry_callback = base::AdaptCallbackForRepeating(base::BindOnce( &CacheStorageCache::PutDidCreateEntry, weak_ptr_factory_.GetWeakPtr(), std::move(scoped_entry_ptr), std::move(put_context))); @@ -1654,7 +1676,10 @@ // Get a temporary copy of the entry pointer before passing it in base::Bind. disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get(); - net::CompletionCallback write_headers_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |put_context| is not + // copyable. + net::CompletionRepeatingCallback write_headers_callback = base::AdaptCallbackForRepeating( base::BindOnce(&CacheStorageCache::PutDidWriteHeaders, weak_ptr_factory_.GetWeakPtr(), std::move(put_context), @@ -1778,7 +1803,10 @@ void CacheStorageCache::CalculateCacheSizePadding( SizePaddingCallback got_sizes_callback) { - net::Int64CompletionCallback got_size_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |got_sizes_callback| is not + // copyable. + net::Int64CompletionRepeatingCallback got_size_callback = base::AdaptCallbackForRepeating(base::BindOnce( &CacheStorageCache::CalculateCacheSizePaddingGotSize, weak_ptr_factory_.GetWeakPtr(), std::move(got_sizes_callback))); @@ -1826,7 +1854,7 @@ } void CacheStorageCache::CalculateCacheSize( - const net::Int64CompletionCallback& callback) { + const net::Int64CompletionRepeatingCallback& callback) { int64_t rv = backend_->CalculateSizeOfAllEntries(callback); if (rv != net::ERR_IO_PENDING) callback.Run(rv); @@ -2100,7 +2128,10 @@ // Temporary pointer so that backend_ptr can be Pass()'d in Bind below. ScopedBackendPtr* backend = backend_ptr.get(); - net::CompletionCallback create_cache_callback = + // Create a callback that is copyable, even though it can only be called once. + // BindRepeating() cannot be used directly because |callback| and + // |backend_ptr| are not copyable. + net::CompletionRepeatingCallback create_cache_callback = base::AdaptCallbackForRepeating( base::BindOnce(&CacheStorageCache::CreateBackendDidCreate, weak_ptr_factory_.GetWeakPtr(), std::move(callback),
diff --git a/content/browser/devtools/devtools_frontend_host_impl.h b/content/browser/devtools/devtools_frontend_host_impl.h index 43f03d2d..8b53bcd 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.h +++ b/content/browser/devtools/devtools_frontend_host_impl.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "content/public/browser/devtools_frontend_host.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/blink/public/web/devtools_frontend.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_frontend.mojom.h" namespace content {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index b4d72bc..9bea6bc 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -395,7 +395,8 @@ if (handle->frame_tree_node() != frame_tree_node_) return; navigation_handles_.erase(handle); - NotifyNavigated(); + if (handle->HasCommitted()) + NotifyNavigated(); // UpdateFrameHost may destruct |this|. scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
diff --git a/content/browser/dom_storage/session_storage_area_impl.cc b/content/browser/dom_storage/session_storage_area_impl.cc index 10e5815..a415043a 100644 --- a/content/browser/dom_storage/session_storage_area_impl.cc +++ b/content/browser/dom_storage/session_storage_area_impl.cc
@@ -133,7 +133,9 @@ void SessionStorageAreaImpl::CreateNewMap( NewMapType map_type, const base::Optional<std::string>& delete_all_source) { - shared_data_map_->RemoveBindingReference(); + bool bound = IsBound(); + if (bound) + shared_data_map_->RemoveBindingReference(); switch (map_type) { case NewMapType::FORKED: shared_data_map_ = SessionStorageDataMap::CreateClone( @@ -152,7 +154,8 @@ break; } } - shared_data_map_->AddBindingReference(); + if (bound) + shared_data_map_->AddBindingReference(); } } // namespace content
diff --git a/content/browser/dom_storage/session_storage_area_impl_unittest.cc b/content/browser/dom_storage/session_storage_area_impl_unittest.cc index 3b1552fa..2a71674c 100644 --- a/content/browser/dom_storage/session_storage_area_impl_unittest.cc +++ b/content/browser/dom_storage/session_storage_area_impl_unittest.cc
@@ -414,4 +414,53 @@ ss_leveldb_impl1 = nullptr; } +TEST_F(SessionStorageAreaImplTest, DeleteAllWithoutBindingOnShared) { + EXPECT_CALL(listener_, + OnDataMapCreation(StdStringToUint8Vector("0"), testing::_)) + .Times(1); + + auto ss_leveldb_impl1 = std::make_unique<SessionStorageAreaImpl>( + metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), test_origin1_, + SessionStorageDataMap::CreateFromDisk( + &listener_, + metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_) + ->second[test_origin1_], + leveldb_database_.get()), + GetRegisterNewAreaMapCallback()); + + // Perform a shallow clone. + std::vector<leveldb::mojom::BatchedOperationPtr> save_operations; + metadata_.RegisterShallowClonedNamespace( + metadata_.GetOrCreateNamespaceEntry(test_namespace_id1_), + metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_), + &save_operations); + leveldb_database_->Write(std::move(save_operations), base::DoNothing()); + auto ss_leveldb_impl2 = ss_leveldb_impl1->Clone( + metadata_.GetOrCreateNamespaceEntry(test_namespace_id2_)); + + // Same maps are used. + EXPECT_EQ(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map()); + + // The |DeleteAll| call will fork the maps, and the observer should see a + // DeleteAll. + EXPECT_CALL(listener_, + OnDataMapCreation(StdStringToUint8Vector("1"), testing::_)) + .Times(1); + // There should be no commits, as we don't actually have to change any data. + // |ss_leveldb_impl1| should just switch to a new, empty map. + EXPECT_CALL(listener_, OnCommitResult(DatabaseError::OK)).Times(0); + EXPECT_TRUE(test::DeleteAllSync(ss_leveldb_impl1.get(), "source")); + + // The maps were forked on the above call. + EXPECT_NE(ss_leveldb_impl1->data_map(), ss_leveldb_impl2->data_map()); + + EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0"))) + .Times(1); + EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("1"))) + .Times(1); + + ss_leveldb_impl1 = nullptr; + ss_leveldb_impl2 = nullptr; +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index c5c8289..697dc4929 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1329,6 +1329,8 @@ frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded( expected_pending_entry_id); + net_error_ = status.error_code; + // If the request was canceled by the user do not show an error page. if (status.error_code == net::ERR_ABORTED) { frame_tree_node_->ResetNavigationRequest(false, true); @@ -1380,7 +1382,6 @@ common_params_.url); has_stale_copy_in_cache_ = status.exists_in_cache; - net_error_ = status.error_code; if (skip_throttles) { // The NavigationHandle shouldn't be notified about renderer-debug URLs.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 191e3f29..74bc623 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -156,6 +156,7 @@ #include "media/audio/audio_manager.h" #include "media/base/media_switches.h" #include "media/base/user_input_monitor.h" +#include "media/learning/common/value.h" #include "media/media_buildflags.h" #include "media/mojo/interfaces/remoting.mojom.h" #include "media/mojo/services/media_interface_provider.h" @@ -189,7 +190,7 @@ #include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h" -#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h" #include "ui/accessibility/ax_tree.h" #include "ui/accessibility/ax_tree_id_registry.h" #include "ui/accessibility/ax_tree_update.h" @@ -4076,6 +4077,13 @@ // This callback is only executed when Create() is called, during // which the lifetime of the |delegate_| is guaranteed. base::Unretained(delegate_)), + base::BindRepeating( + [](RenderFrameHostImpl* frame) { + return ::media::learning::FeatureValue( + frame->GetLastCommittedOrigin().host()); + }, + // Same as above. + base::Unretained(this)), std::move(save_stats_cb))); if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 5454bce..5100ff4 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -65,20 +65,20 @@ #include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "third_party/blink/public/common/frame/user_activation_update_type.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" +#include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h" #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h" #include "third_party/blink/public/mojom/presentation/presentation.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" #include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h" #include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" #include "third_party/blink/public/platform/web_focus_type.h" #include "third_party/blink/public/platform/web_insecure_request_policy.h" #include "third_party/blink/public/platform/web_scroll_types.h" #include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h" -#include "third_party/blink/public/web/commit_result.mojom.h" #include "third_party/blink/public/web/web_text_direction.h" #include "third_party/blink/public/web/web_tree_scope_type.h" #include "ui/accessibility/ax_action_handler.h"
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index ad9bf0b..5116c5e 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1791,7 +1791,7 @@ CreateProxiesForNewRenderFrameHost(old_instance, new_instance); speculative_render_frame_host_ = - CreateRenderFrame(new_instance, delegate_->IsHidden(), nullptr); + CreateRenderFrame(new_instance, delegate_->IsHidden()); // If RenderViewHost was created along with the speculative RenderFrameHost, // ensure that RenderViewCreated is fired for it. It is important to do this @@ -1808,18 +1808,9 @@ std::unique_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame( SiteInstance* instance, - bool hidden, - int* view_routing_id_ptr) { - int32_t widget_routing_id = MSG_ROUTING_NONE; - RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance); - + bool hidden) { CHECK(instance); - std::unique_ptr<RenderFrameHostImpl> new_render_frame_host; - bool success = true; - if (view_routing_id_ptr) - *view_routing_id_ptr = MSG_ROUTING_NONE; - // We are creating a pending or speculative RFH here. We should never create // it in the same SiteInstance as our current RFH. CHECK_NE(render_frame_host_->GetSiteInstance(), instance); @@ -1830,60 +1821,48 @@ // TODO(ajwong): When RVH no longer owns a RWH, this logic should be // simplified as the decision to create a RWH will be centralized here. // https://crbug.com/545684 - if (frame_tree_node_->parent() && - frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() != - instance) { + FrameTreeNode* parent = frame_tree_node_->parent(); + int32_t widget_routing_id = MSG_ROUTING_NONE; + if (parent && parent->current_frame_host()->GetSiteInstance() != instance) widget_routing_id = instance->GetProcess()->GetNextRoutingID(); - } - new_render_frame_host = CreateRenderFrameHost( - instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden, - false); - RenderViewHostImpl* render_view_host = - new_render_frame_host->render_view_host(); + std::unique_ptr<RenderFrameHostImpl> new_render_frame_host = + CreateRenderFrameHost(instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, + widget_routing_id, hidden, false); + DCHECK_EQ(new_render_frame_host->GetSiteInstance(), instance); // Prevent the process from exiting while we're trying to navigate in it. new_render_frame_host->GetProcess()->AddPendingView(); + RenderViewHostImpl* render_view_host = + new_render_frame_host->render_view_host(); if (frame_tree_node_->IsMainFrame()) { - success = InitRenderView(render_view_host, proxy); + if (!InitRenderView(render_view_host, GetRenderFrameProxyHost(instance))) + return nullptr; // If we are reusing the RenderViewHost and it doesn't already have a // RenderWidgetHostView, we need to create one if this is the main frame. if (!render_view_host->GetWidget()->GetView()) delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host); + + // Don't show the main frame's view until we get a DidNavigate from it. + // Only the RenderViewHost for the top-level RenderFrameHost has a + // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes + // will be created later and hidden. + if (render_view_host->GetWidget()->GetView()) + render_view_host->GetWidget()->GetView()->Hide(); } else { DCHECK(render_view_host->IsRenderViewLive()); } - if (success) { - if (frame_tree_node_->IsMainFrame()) { - // Don't show the main frame's view until we get a DidNavigate from it. - // Only the RenderViewHost for the top-level RenderFrameHost has a - // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes - // will be created later and hidden. - if (render_view_host->GetWidget()->GetView()) - render_view_host->GetWidget()->GetView()->Hide(); - } - // RenderViewHost for |instance| might exist prior to calling - // CreateRenderFrame. In such a case, InitRenderView will not create the - // RenderFrame in the renderer process and it needs to be done - // explicitly. - DCHECK(new_render_frame_host); - success = InitRenderFrame(new_render_frame_host.get()); - } + // RenderViewHost for |instance| might exist prior to calling + // CreateRenderFrame. In such a case, InitRenderView will not create the + // RenderFrame in the renderer process and it needs to be done + // explicitly. + if (!InitRenderFrame(new_render_frame_host.get())) + return nullptr; - if (success) { - if (view_routing_id_ptr) - *view_routing_id_ptr = render_view_host->GetRoutingID(); - } - - // Return the new RenderFrameHost on successful creation. - if (success) { - DCHECK(new_render_frame_host->GetSiteInstance() == instance); - return new_render_frame_host; - } - return nullptr; + return new_render_frame_host; } int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h index 14d66dc..f2ba4419 100644 --- a/content/browser/frame_host/render_frame_host_manager.h +++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -292,13 +292,9 @@ void DidChangeOpener(int opener_routing_id, SiteInstance* source_site_instance); - // Creates and initializes a RenderFrameHost. If |view_routing_id_ptr| - // is not nullptr it will be set to the routing id of the view associated with - // the frame. - std::unique_ptr<RenderFrameHostImpl> CreateRenderFrame( - SiteInstance* instance, - bool hidden, - int* view_routing_id_ptr); + // Creates and initializes a RenderFrameHost. + std::unique_ptr<RenderFrameHostImpl> CreateRenderFrame(SiteInstance* instance, + bool hidden); // Helper method to create and initialize a RenderFrameProxyHost and return // its routing id.
diff --git a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h index e455d1ea..49189ae 100644 --- a/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_arrays_and_structs_autogen.h
@@ -18,6 +18,22 @@ GPU_FEATURE_TYPE_ACCELERATED_WEBGL, }; +const GpuControlList::More kMoreForEntry1_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry2[1] = { GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, }; @@ -29,10 +45,42 @@ nullptr, }; +const GpuControlList::More kMoreForEntry2_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry3[1] = { GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, }; +const GpuControlList::More kMoreForEntry3_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry4[2] = { GPU_FEATURE_TYPE_ACCELERATED_WEBGL2, GPU_FEATURE_TYPE_ACCELERATED_WEBGL, @@ -45,10 +93,42 @@ nullptr, }; +const GpuControlList::More kMoreForEntry4_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry5[1] = { GPU_FEATURE_TYPE_ACCELERATED_WEBGL, }; +const GpuControlList::More kMoreForEntry5_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const GpuControlList::GLStrings kGLStringsForGpuManagerTestingEntry5Exception0 = { nullptr, @@ -57,6 +137,22 @@ nullptr, }; +const GpuControlList::More kMoreForEntry5_572251052Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry6[12] = { GPU_FEATURE_TYPE_FLASH_STAGE3D, GPU_FEATURE_TYPE_GPU_COMPOSITING, @@ -72,10 +168,42 @@ GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE, }; +const GpuControlList::More kMoreForEntry6_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuManagerTestingEntry7[1] = { GPU_FEATURE_TYPE_ACCELERATED_WEBGL, }; +const GpuControlList::More kMoreForEntry7_572251052 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + } // namespace gpu #endif // CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_TESTING_ARRAYS_AND_STRUCTS_AUTOGEN_H_
diff --git a/content/browser/gpu/gpu_data_manager_testing_autogen.cc b/content/browser/gpu/gpu_data_manager_testing_autogen.cc index c20dee7..b224be9 100644 --- a/content/browser/gpu/gpu_data_manager_testing_autogen.cc +++ b/content/browser/gpu/gpu_data_manager_testing_autogen.cc
@@ -41,7 +41,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry1_572251052, // more data }, 0, // exceptions count nullptr, // exceptions @@ -71,7 +71,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry2_572251052, // more data }, 0, // exceptions count nullptr, // exceptions @@ -101,7 +101,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry3_572251052, // more data }, 0, // exceptions count nullptr, // exceptions @@ -131,7 +131,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry4_572251052, // more data }, 0, // exceptions count nullptr, // exceptions @@ -161,7 +161,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry5_572251052, // more data }, base::size(kExceptionsForEntry5), // exceptions count kExceptionsForEntry5, // exceptions @@ -191,7 +191,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry6_572251052, // more data }, 0, // exceptions count nullptr, // exceptions @@ -221,7 +221,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry7_572251052, // more data }, 0, // exceptions count nullptr, // exceptions
diff --git a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h index b33ca71..4d60314 100644 --- a/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h +++ b/content/browser/gpu/gpu_data_manager_testing_exceptions_autogen.h
@@ -27,7 +27,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry5_572251052Exception0, // more data }, };
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc index 3fa00d9..71fab54 100644 --- a/content/browser/gpu/gpu_internals_ui.cc +++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -275,9 +275,21 @@ ui::IsCompositingManagerPresent() ? "Yes" : "No")); } #endif - std::string direct_rendering = gpu_info.direct_rendering ? "Yes" : "No"; - basic_info->Append( - NewDescriptionValuePair("Direct rendering", direct_rendering)); + std::string direct_rendering_version; + if (gpu_info.direct_rendering_version == "1") { + direct_rendering_version = "indirect"; + } else if (gpu_info.direct_rendering_version == "2") { + direct_rendering_version = "direct but version unknown"; + } else if (base::StartsWith(gpu_info.direct_rendering_version, "2.", + base::CompareCase::INSENSITIVE_ASCII)) { + direct_rendering_version = gpu_info.direct_rendering_version; + base::ReplaceFirstSubstringAfterOffset(&direct_rendering_version, 0, "2.", + "DRI"); + } else { + direct_rendering_version = "unknown"; + } + basic_info->Append(NewDescriptionValuePair("Direct rendering version", + direct_rendering_version)); std::string reset_strategy = base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy);
diff --git a/content/browser/idle/idle_manager.h b/content/browser/idle/idle_manager.h index 2f8a9b0..68cd45e9 100644 --- a/content/browser/idle/idle_manager.h +++ b/content/browser/idle/idle_manager.h
@@ -16,7 +16,7 @@ #include "base/timer/timer.h" #include "content/browser/idle/idle_monitor.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom.h" #include "ui/base/idle/idle.h" #include "url/origin.h"
diff --git a/content/browser/idle/idle_manager_unittest.cc b/content/browser/idle/idle_manager_unittest.cc index cd717f03..50c0348c 100644 --- a/content/browser/idle/idle_manager_unittest.cc +++ b/content/browser/idle/idle_manager_unittest.cc
@@ -25,7 +25,7 @@ #include "services/service_manager/public/cpp/connector.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom.h" using blink::mojom::IdleManagerPtr; using blink::mojom::IdleMonitorPtr;
diff --git a/content/browser/idle/idle_monitor.h b/content/browser/idle/idle_monitor.h index 7609854..08f53ff 100644 --- a/content/browser/idle/idle_monitor.h +++ b/content/browser/idle/idle_monitor.h
@@ -14,9 +14,10 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "content/common/content_export.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/connection_error_callback.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom.h" #include "ui/base/idle/idle.h" #include "url/origin.h"
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index f994f8cb..9c978fa4 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -134,7 +134,7 @@ void IndexedDBFactoryImpl::RemoveDatabaseFromMaps( const IndexedDBDatabase::Identifier& identifier) { - const auto& it = database_map_.find(identifier); + auto it = database_map_.find(identifier); DCHECK(it != database_map_.end()); IndexedDBDatabase* database = it->second; database_map_.erase(it); @@ -165,8 +165,10 @@ void IndexedDBFactoryImpl::ReleaseBackingStore(const Origin& origin, bool immediate) { + if (!base::ContainsKey(backing_store_map_, origin)) + return; if (immediate) { - const auto& it = backing_stores_with_active_blobs_.find(origin); + auto it = backing_stores_with_active_blobs_.find(origin); if (it != backing_stores_with_active_blobs_.end()) { it->second->active_blob_registry()->ForceShutdown(); backing_stores_with_active_blobs_.erase(it); @@ -201,6 +203,8 @@ } void IndexedDBFactoryImpl::MaybeStartPreCloseTasks(const Origin& origin) { + if (!base::ContainsKey(backing_store_map_, origin)) + return; // Another reference may have been created since the maybe-close was posted, // so it is necessary to check again. if (!HasLastBackingStoreReference(origin)) @@ -267,7 +271,12 @@ } void IndexedDBFactoryImpl::MaybeCloseBackingStore(const Origin& origin) { - backing_store_map_[origin]->SetPreCloseTaskList(nullptr); + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) + return; + + IndexedDBBackingStore* backing_store = it->second.get(); + backing_store->SetPreCloseTaskList(nullptr); // Another reference may have opened since the maybe-close was posted, so it // is necessary to check again. if (HasLastBackingStoreReference(origin)) @@ -275,11 +284,12 @@ } void IndexedDBFactoryImpl::CloseBackingStore(const Origin& origin) { - const auto& it = backing_store_map_.find(origin); - DCHECK(it != backing_store_map_.end()); + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) + return; // Stop the timer and pre close tasks (if they are running) - this may happen // if the timer was started and then a forced close occurs. - scoped_refptr<IndexedDBBackingStore>& backing_store = it->second; + IndexedDBBackingStore* backing_store = it->second.get(); backing_store->close_timer()->Stop(); backing_store->SetPreCloseTaskList(nullptr); @@ -291,24 +301,20 @@ bool IndexedDBFactoryImpl::HasLastBackingStoreReference( const Origin& origin) const { - IndexedDBBackingStore* ptr; - { - // Scope so that the implicit scoped_refptr<> is freed. - const auto& it = backing_store_map_.find(origin); - DCHECK(it != backing_store_map_.end()); - ptr = it->second.get(); - } - return ptr->HasOneRef(); + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) + return false; + return it->second->HasOneRef(); } leveldb::Status IndexedDBFactoryImpl::AbortTransactions(const Origin& origin) { - const scoped_refptr<IndexedDBBackingStore>& backing_store = - backing_store_map_[origin]; - if (!backing_store) { + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) { return leveldb::Status::IOError( "Internal error opening backing store for " "indexedDB.abortTransactions."); } + IndexedDBBackingStore* backing_store = it->second.get(); leveldb::Status get_names_status; IndexedDBMetadataCoding metadata_coding; @@ -374,9 +380,9 @@ // context (which nominally owns this factory) is destroyed during thread // termination the timers must be stopped so that this factory and the // stores can be disposed of. - for (const auto& it : backing_store_map_) { - it.second->close_timer()->Stop(); - it.second->SetPreCloseTaskList(nullptr); + for (const auto& origin_backing_store_pair : backing_store_map_) { + origin_backing_store_pair.second->close_timer()->Stop(); + origin_backing_store_pair.second->SetPreCloseTaskList(nullptr); } backing_store_map_.clear(); backing_stores_with_active_blobs_.clear(); @@ -389,13 +395,13 @@ return; if (blobs_outstanding) { DCHECK(!backing_stores_with_active_blobs_.count(origin)); - const auto& it = backing_store_map_.find(origin); + auto it = backing_store_map_.find(origin); if (it != backing_store_map_.end()) backing_stores_with_active_blobs_.insert(*it); else DCHECK(false); } else { - const auto& it = backing_stores_with_active_blobs_.find(origin); + auto it = backing_stores_with_active_blobs_.find(origin); if (it != backing_stores_with_active_blobs_.end()) { backing_stores_with_active_blobs_.erase(it); ReleaseBackingStore(origin, false /* immediate */); @@ -498,7 +504,7 @@ bool force_close) { IDB_TRACE("IndexedDBFactoryImpl::DeleteDatabase"); IndexedDBDatabase::Identifier unique_identifier(origin, name); - const auto& it = database_map_.find(unique_identifier); + auto it = database_map_.find(unique_identifier); if (it != database_map_.end()) { // If there are any connections to the database, directly delete the // database. @@ -594,14 +600,14 @@ base::OnceCallback<void(leveldb::Status)> callback, const Origin& origin) { IDB_TRACE("IndexedDBFactoryImpl::AbortTransactionsAndCompactDatabase"); - const scoped_refptr<IndexedDBBackingStore>& backing_store = - backing_store_map_[origin]; - if (!backing_store) { + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) { std::move(callback).Run(leveldb::Status::IOError( "Internal error opening backing store for " "indexedDB.abortTransactionsAndCompactDatabase.")); return; } + IndexedDBBackingStore* backing_store = it->second.get(); leveldb::Status status = AbortTransactions(origin); backing_store->Compact(); std::move(callback).Run(status); @@ -611,7 +617,7 @@ base::OnceCallback<void(leveldb::Status)> callback, const Origin& origin) { IDB_TRACE("IndexedDBFactoryImpl::AbortTransactionsForDatabase"); - if (!backing_store_map_[origin]) { + if (!base::ContainsKey(backing_store_map_, origin)) { std::move(callback).Run( leveldb::Status::IOError("Internal error opening backing store for " "indexedDB.abortTransactionsForDatabase.")); @@ -669,7 +675,7 @@ bool IndexedDBFactoryImpl::IsBackingStorePendingClose( const Origin& origin) const { - const auto& it = backing_store_map_.find(origin); + auto it = backing_store_map_.find(origin); if (it == backing_store_map_.end()) return false; return it->second->close_timer()->IsRunning() || @@ -682,7 +688,7 @@ bool /* disk_full */> IndexedDBFactoryImpl::OpenBackingStore(const Origin& origin, const base::FilePath& data_directory) { - const auto& it2 = backing_store_map_.find(origin); + auto it2 = backing_store_map_.find(origin); scoped_refptr<IndexedDBBackingStore> backing_store; if (it2 != backing_store_map_.end()) { // Grab a refptr so the completion of the preclose task list doesn't close @@ -834,12 +840,12 @@ } int64_t IndexedDBFactoryImpl::GetInMemoryDBSize(const Origin& origin) const { - const auto& it = backing_store_map_.find(origin); + auto it = backing_store_map_.find(origin); // Origin won't be present in map if it has been deleted. if (it == backing_store_map_.end()) return 0; - const scoped_refptr<IndexedDBBackingStore>& backing_store = it->second; + IndexedDBBackingStore* backing_store = it->second.get(); int64_t level_db_size = 0; leveldb::Status s = GetDBSizeFromEnv(backing_store->db()->env(), "/", &level_db_size); @@ -851,10 +857,10 @@ base::Time IndexedDBFactoryImpl::GetLastModified( const url::Origin& origin) const { - const auto& it = backing_store_map_.find(origin); - DCHECK(it != backing_store_map_.end()); - - const scoped_refptr<IndexedDBBackingStore>& backing_store = it->second; + auto it = backing_store_map_.find(origin); + if (it == backing_store_map_.end()) + return base::Time(); + IndexedDBBackingStore* backing_store = it->second.get(); return backing_store->db()->LastModified(); }
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index 03ee6e7..5e242df 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -1032,11 +1032,11 @@ // This class allows intercepting the OpenLocalStorage method and changing // the parameters to the real implementation of it. -class StoragePartitonInterceptor +class StoragePartitionInterceptor : public blink::mojom::StoragePartitionServiceInterceptorForTesting, public RenderProcessHostObserver { public: - StoragePartitonInterceptor( + StoragePartitionInterceptor( RenderProcessHostImpl* rph, blink::mojom::StoragePartitionServiceRequest request, const url::Origin& origin_to_inject) @@ -1089,7 +1089,7 @@ url::Origin origin_to_inject_; - DISALLOW_COPY_AND_ASSIGN(StoragePartitonInterceptor); + DISALLOW_COPY_AND_ASSIGN(StoragePartitionInterceptor); }; void CreateTestStoragePartitionService( @@ -1098,7 +1098,7 @@ blink::mojom::StoragePartitionServiceRequest request) { // This object will register as RenderProcessHostObserver, so it will // clean itself automatically on process exit. - new StoragePartitonInterceptor(rph, std::move(request), origin_to_inject); + new StoragePartitionInterceptor(rph, std::move(request), origin_to_inject); } // Verify that an isolated renderer process cannot read localStorage of an
diff --git a/content/browser/pointer_lock_browsertest.cc b/content/browser/pointer_lock_browsertest.cc index 6f21c02..54e1db34f 100644 --- a/content/browser/pointer_lock_browsertest.cc +++ b/content/browser/pointer_lock_browsertest.cc
@@ -164,31 +164,43 @@ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host()); - // Request a pointer lock on the root frame's body. - EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()")); - - // Root frame should have been granted pointer lock. - EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body")); - // Add a mouse move event listener to the root frame. EXPECT_TRUE(ExecJs( root, "var x; var y; var mX; var mY; document.addEventListener('mousemove', " "function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});")); + // Send a mouse move to root frame before lock to set last mouse position. blink::WebMouseEvent mouse_event( blink::WebInputEvent::kMouseMove, blink::WebInputEvent::kNoModifiers, blink::WebInputEvent::GetStaticTimeStampForTests()); - mouse_event.SetPositionInWidget(10, 11); - mouse_event.movement_x = 12; - mouse_event.movement_y = 13; + mouse_event.SetPositionInWidget(6, 7); + mouse_event.movement_x = 8; + mouse_event.movement_y = 9; router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo()); // Make sure that the renderer handled the input event. MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost()); root_observer.Wait(); - EXPECT_EQ("[10,11,12,13]", EvalJs(root, "JSON.stringify([x,y,mX,mY])")); + EXPECT_EQ("[6,7,8,9]", EvalJs(root, "JSON.stringify([x,y,mX,mY])")); + + // Request a pointer lock on the root frame's body. + EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()")); + + // Root frame should have been granted pointer lock. + EXPECT_EQ(true, EvalJs(root, "document.pointerLockElement == document.body")); + + mouse_event.SetPositionInWidget(10, 11); + mouse_event.movement_x = 12; + mouse_event.movement_y = 13; + router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo()); + + // Make sure that the renderer handled the input event. + root_observer.Wait(); + + // Locked event has same coordinates as before locked. + EXPECT_EQ("[6,7,12,13]", EvalJs(root, "JSON.stringify([x,y,mX,mY])")); // Release pointer lock on root frame. EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()")); @@ -222,7 +234,8 @@ MainThreadFrameObserver child_observer(child_view->GetRenderWidgetHost()); child_observer.Wait(); - EXPECT_EQ("[14,15,16,17]", EvalJs(child, "JSON.stringify([x,y,mX,mY])")); + // This is the first event to child render, so the coordinates is (0, 0) + EXPECT_EQ("[0,0,16,17]", EvalJs(child, "JSON.stringify([x,y,mX,mY])")); } // Tests that the browser will not unlock the pointer if a RenderWidgetHostView @@ -383,6 +396,27 @@ WaitForHitTestDataOrChildSurfaceReady(child->current_frame_host()); + // Add a mouse move event listener to the root frame. + EXPECT_TRUE(ExecJs( + root, + "var x; var y; var dX; var dY; document.addEventListener('mousemove', " + "function(e) {x = e.x; y = e.y; mX = e.movementX; mY = e.movementY;});")); + + // Send a mouse move to root frame before lock to set last mouse position. + blink::WebMouseEvent mouse_event( + blink::WebInputEvent::kMouseMove, blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::GetStaticTimeStampForTests()); + mouse_event.SetPositionInWidget(6, 7); + mouse_event.movement_x = 8; + mouse_event.movement_y = 9; + router->RouteMouseEvent(root_view, &mouse_event, ui::LatencyInfo()); + + // Make sure that the renderer handled the input event. + MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost()); + root_observer.Wait(); + + EXPECT_EQ("[6,7,8,9]", EvalJs(root, "JSON.stringify([x,y,mX,mY])")); + // Request a pointer lock on the root frame's body. EXPECT_TRUE(ExecJs(root, "document.body.requestPointerLock()")); @@ -394,7 +428,6 @@ root, "var x; var y; var dX; var dY; document.addEventListener('mousewheel', " "function(e) {x = e.x; y = e.y; dX = e.deltaX; dY = e.deltaY;});")); - MainThreadFrameObserver root_observer(root_view->GetRenderWidgetHost()); root_observer.Wait(); blink::WebMouseWheelEvent wheel_event( @@ -420,7 +453,8 @@ // Make sure that the renderer handled the input event. root_observer.Wait(); - EXPECT_EQ("[10,11,12,13]", EvalJs(root, "JSON.stringify([x, y, dX, dY])")); + // Locked event has same coordinates as before locked. + EXPECT_EQ("[6,7,12,13]", EvalJs(root, "JSON.stringify([x, y, dX, dY])")); // Release pointer lock on root frame. EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()")); @@ -456,7 +490,8 @@ // Make sure that the renderer handled the input event. child_observer.Wait(); - EXPECT_EQ("[14,15,16,17]", EvalJs(child, "JSON.stringify([x, y, dX, dY])")); + // This is the first event to child render, so the coordinates is (0, 0) + EXPECT_EQ("[0,0,16,17]", EvalJs(child, "JSON.stringify([x, y, dX, dY])")); } IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWidgetHidden) {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 5cc6309..2ecee561 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -651,6 +651,8 @@ } root_window_ = root_window; + if (base::FeatureList::IsEnabled(features::kForce60HzRefreshRate)) + root_window_->SetForce60HzRefreshRate(); root_window_->SetLayer(root_layer ? root_layer : cc::Layer::Create()); root_window_->GetLayer()->SetBounds(size_); if (!readback_layer_tree_) {
diff --git a/content/browser/renderer_host/frame_connector_delegate.h b/content/browser/renderer_host/frame_connector_delegate.h index 5f494de..aaa3944 100644 --- a/content/browser/renderer_host/frame_connector_delegate.h +++ b/content/browser/renderer_host/frame_connector_delegate.h
@@ -273,7 +273,8 @@ // ViewportIntersection() can return a reference. gfx::Rect viewport_intersection_rect_; gfx::Rect compositor_visible_rect_; - blink::FrameOcclusionState occlusion_state_ = blink::kUnknownOcclusionState; + blink::FrameOcclusionState occlusion_state_ = + blink::FrameOcclusionState::kUnknown; ScreenInfo screen_info_; gfx::Size local_frame_size_in_dip_;
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc index 023f030..99219ba 100644 --- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc +++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -662,9 +662,9 @@ ui::GestureEvent scroll_end(scroll_end_position.x(), scroll_end_position.y(), 0, ui::EventTimeForNow(), scroll_end_details); parent_view->OnGestureEvent(&scroll_end); + EXPECT_FALSE(selection_controller_test_api.temporarily_hidden()); EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE, parent_view->selection_controller()->active_status()); - EXPECT_FALSE(selection_controller_test_api.temporarily_hidden()); EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning()); // 3) Send touch-end.
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index 559132c..cfe1c2f 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -62,10 +62,6 @@ constexpr const char* kDepthVideoDeviceId = "stub_device_1 (depth)"; constexpr media::VideoCaptureApi kStubCaptureApi = media::VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE; -constexpr double kStubFocalLengthX = 135.0; -constexpr double kStubFocalLengthY = 135.6; -constexpr double kStubDepthNear = 0.0; -constexpr double kStubDepthFar = 65.535; void AudioInputDevicesEnumerated(base::Closure quit_closure, media::AudioDeviceDescriptions* out, @@ -287,16 +283,6 @@ media::VideoCaptureDeviceInfo info; info.descriptor.device_id = device_id; info.descriptor.capture_api = kStubCaptureApi; - if (device_id == kDepthVideoDeviceId) { - info.descriptor.camera_calibration.emplace(); - info.descriptor.camera_calibration->focal_length_x = - kStubFocalLengthX; - info.descriptor.camera_calibration->focal_length_y = - kStubFocalLengthY; - info.descriptor.camera_calibration->depth_near = - kStubDepthNear; - info.descriptor.camera_calibration->depth_far = kStubDepthFar; - } result.push_back(info); } base::ResetAndReturn(&result_callback).Run(result); @@ -507,15 +493,6 @@ // one audio and one depth video stream. EXPECT_EQ(host_->audio_devices_.size(), 1u); EXPECT_EQ(host_->video_devices_.size(), 1u); - // host_->video_devices_[0] contains the information about generated video - // stream device (the depth device). - const base::Optional<blink::CameraCalibration> calibration = - host_->video_devices_[0].camera_calibration; - EXPECT_TRUE(calibration); - EXPECT_EQ(calibration->focal_length_x, kStubFocalLengthX); - EXPECT_EQ(calibration->focal_length_y, kStubFocalLengthY); - EXPECT_EQ(calibration->depth_near, kStubDepthNear); - EXPECT_EQ(calibration->depth_far, kStubDepthFar); } // This test generates two streams with video only using the same render frame
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index b183d35..9bb3b80 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -263,6 +263,28 @@ return devices; } +void FinalizeGetMediaDeviceIDForHMAC( + blink::MediaDeviceType type, + const std::string& salt, + const url::Origin& security_origin, + const std::string& source_id, + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::OnceCallback<void(const base::Optional<std::string>&)> callback, + const MediaDeviceEnumeration& enumeration) { + DCHECK(type == blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT || + type == blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT); + for (const auto& device : enumeration[type]) { + if (MediaStreamManager::DoesMediaDeviceIDMatchHMAC( + salt, security_origin, source_id, device.device_id)) { + task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), device.device_id)); + return; + } + } + task_runner->PostTask(FROM_HERE, + base::BindOnce(std::move(callback), base::nullopt)); +} + } // namespace // MediaStreamManager::DeviceRequest represents a request to either enumerate @@ -2123,6 +2145,29 @@ } // static +void MediaStreamManager::GetMediaDeviceIDForHMAC( + blink::MediaStreamType stream_type, + std::string salt, + url::Origin security_origin, + std::string hmac_device_id, + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::OnceCallback<void(const base::Optional<std::string>&)> callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(stream_type == blink::MEDIA_DEVICE_AUDIO_CAPTURE || + stream_type == blink::MEDIA_DEVICE_VIDEO_CAPTURE); + MediaStreamManager* msm = g_media_stream_manager_tls_ptr.Pointer()->Get(); + blink::MediaDeviceType device_type = ConvertToMediaDeviceType(stream_type); + MediaDevicesManager::BoolDeviceTypes requested_types; + requested_types[device_type] = true; + msm->media_devices_manager()->EnumerateDevices( + requested_types, + base::BindOnce(&FinalizeGetMediaDeviceIDForHMAC, device_type, + std::move(salt), std::move(security_origin), + std::move(hmac_device_id), std::move(task_runner), + std::move(callback))); +} + +// static bool MediaStreamManager::IsOriginAllowed(int render_process_id, const url::Origin& origin) { if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( @@ -2168,13 +2213,6 @@ info.video_facing, info.group_id); } - if (stream_type != blink::MEDIA_DEVICE_VIDEO_CAPTURE) - return devices; - - for (auto& device : devices) { - device.camera_calibration = - video_capture_manager()->GetCameraCalibration(device.id); - } return devices; }
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index b260970..5152f7e 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -300,6 +300,18 @@ const std::string& device_guid, const std::string& raw_unique_id); + // Convenience method to get the raw device ID from the HMAC |hmac_device_id| + // for the given |security_origin| and |salt|. |stream_type| must be + // blink::MEDIA_DEVICE_AUDIO_CAPTURE or blink::MEDIA_DEVICE_VIDEO_CAPTURE. + // The result will be returned via |callback| on the given |task_runner|. + static void GetMediaDeviceIDForHMAC( + blink::MediaStreamType stream_type, + std::string salt, + url::Origin security_origin, + std::string hmac_device_id, + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::OnceCallback<void(const base::Optional<std::string>&)> callback); + // Returns true if the renderer process identified with |render_process_id| // is allowed to access |origin|. static bool IsOriginAllowed(int render_process_id, const url::Origin& origin);
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index 7a35143..92258b85 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -65,6 +65,7 @@ namespace { const char kMockSalt[] = ""; +const char kFakeDeviceIdPrefix[] = "fake_device_id_"; // This class mocks the audio manager and overrides some methods to ensure that // we can run our tests on the buildbots. @@ -88,7 +89,7 @@ for (size_t i = 0; i < num_input_devices_; i++) { device_names->push_back(media::AudioDeviceName( std::string("fake_device_name_") + base::NumberToString(i), - std::string("fake_device_id_") + base::NumberToString(i))); + std::string(kFakeDeviceIdPrefix) + base::NumberToString(i))); } } @@ -103,7 +104,7 @@ for (size_t i = 0; i < num_output_devices_; i++) { device_names->push_back(media::AudioDeviceName( std::string("fake_device_name_") + base::NumberToString(i), - std::string("fake_device_id_") + base::NumberToString(i))); + std::string(kFakeDeviceIdPrefix) + base::NumberToString(i))); } } @@ -687,4 +688,35 @@ video_device.session_id); } +TEST_F(MediaStreamManagerTest, GetMediaDeviceIDForHMAC) { + const char kSalt[] = "my salt"; + const url::Origin kOrigin = url::Origin::Create(GURL("http://example.com")); + const std::string kExistingRawDeviceId = + std::string(kFakeDeviceIdPrefix) + "0"; + const std::string kExistingHmacDeviceId = + MediaStreamManager::GetHMACForMediaDeviceID(kSalt, kOrigin, + kExistingRawDeviceId); + + MediaStreamManager::GetMediaDeviceIDForHMAC( + blink::MEDIA_DEVICE_AUDIO_CAPTURE, kSalt, kOrigin, kExistingHmacDeviceId, + base::SequencedTaskRunnerHandle::Get(), + base::BindOnce( + [](const std::string& expected_raw_device_id, + const base::Optional<std::string>& raw_device_id) { + ASSERT_TRUE(raw_device_id.has_value()); + EXPECT_EQ(*raw_device_id, expected_raw_device_id); + }, + kExistingRawDeviceId)); + base::RunLoop().RunUntilIdle(); + + const std::string kNonexistingHmacDeviceId = "does not exist"; + MediaStreamManager::GetMediaDeviceIDForHMAC( + blink::MEDIA_DEVICE_AUDIO_CAPTURE, kSalt, kOrigin, + kNonexistingHmacDeviceId, base::SequencedTaskRunnerHandle::Get(), + base::BindOnce([](const base::Optional<std::string>& raw_device_id) { + EXPECT_FALSE(raw_device_id.has_value()); + })); + base::RunLoop().RunUntilIdle(); +} + } // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index 2ac11f0d..dd07849 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -860,14 +860,6 @@ return new_controller; } -base::Optional<blink::CameraCalibration> -VideoCaptureManager::GetCameraCalibration(const std::string& device_id) { - media::VideoCaptureDeviceInfo* info = GetDeviceInfoById(device_id); - if (!info) - return base::Optional<blink::CameraCalibration>(); - return info->descriptor.camera_calibration; -} - #if defined(OS_ANDROID) void VideoCaptureManager::OnApplicationStateChange( base::android::ApplicationState state) {
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h index b269bb6..5ba6b7c5 100644 --- a/content/browser/renderer_host/media/video_capture_manager.h +++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -189,13 +189,6 @@ void OnDeviceLaunchAborted() override; void OnDeviceConnectionLost(VideoCaptureController* controller) override; - // Retrieves camera calibration information for a particular device. Returns - // nullopt_t if the |device_id| is not found or camera calibration information - // is not available for the device. Camera calibration is cached during - // device(s) enumeration. - base::Optional<blink::CameraCalibration> GetCameraCalibration( - const std::string& device_id); - private: class CaptureDeviceStartRequest;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 2f18a9e9..19cb147 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2448,11 +2448,6 @@ return is_keep_alive_ref_count_disabled_; } -void RenderProcessHostImpl::PurgeAndSuspend() { - TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::PurgeAndSuspend"); - GetRendererInterface()->ProcessPurgeAndSuspend(); -} - void RenderProcessHostImpl::Resume() {} mojom::Renderer* RenderProcessHostImpl::GetRendererInterface() {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 42e540c6..4cde04b 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -217,7 +217,6 @@ RenderProcessHost::KeepAliveClientType) override; void DisableKeepAliveRefCount() override; bool IsKeepAliveRefCountDisabled() override; - void PurgeAndSuspend() override; void Resume() override; mojom::Renderer* GetRendererInterface() override; void CreateURLLoaderFactory( @@ -510,7 +509,7 @@ private: friend class ChildProcessLauncherBrowserTest_ChildSpawnFail_Test; friend class VisitRelayingRenderProcessHost; - friend class StoragePartitonInterceptor; + friend class StoragePartitionInterceptor; class ConnectionFilterController; class ConnectionFilterImpl;
diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm b/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm index a709455..7df9ee6 100644 --- a/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm +++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
@@ -222,14 +222,7 @@ } void RenderWidgetHostNSViewBridgeLocal::SetCursorLocked(bool locked) { - if (locked) { - CGAssociateMouseAndMouseCursorPosition(NO); - [NSCursor hide]; - } else { - // Unlock position of mouse cursor and unhide it. - CGAssociateMouseAndMouseCursorPosition(YES); - [NSCursor unhide]; - } + [cocoa_view_ setCursorLocked:locked]; } void RenderWidgetHostNSViewBridgeLocal::ShowDictionaryOverlayForSelection() {
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.h b/content/browser/renderer_host/render_widget_host_view_cocoa.h index 12e531d..5cfbbeb 100644 --- a/content/browser/renderer_host/render_widget_host_view_cocoa.h +++ b/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -194,6 +194,10 @@ // Whether the pen's tip is in contact with the stylus digital tablet. bool has_pen_contact_; + + bool mouse_locked_; + gfx::PointF last_mouse_screen_position_; + gfx::PointF mouse_locked_screen_position_; } @property(nonatomic, assign) NSRange markedRange; @@ -250,6 +254,9 @@ - (void)lockKeyboard:(base::Optional<base::flat_set<ui::DomCode>>)keysToLock; - (void)unlockKeyboard; +// Cursorlock methods. +- (void)setCursorLocked:(BOOL)locked; + // Methods previously marked as private. - (id)initWithClient:(content::mojom::RenderWidgetHostNSViewClient*)client withClientHelper:(content::RenderWidgetHostNSViewClientHelper*)clientHelper;
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/content/browser/renderer_host/render_widget_host_view_cocoa.mm index ed18a0a..d04130dc 100644 --- a/content/browser/renderer_host/render_widget_host_view_cocoa.mm +++ b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -617,6 +617,7 @@ if (!send_touch) { WebMouseEvent event = WebMouseEventBuilder::Build(theEvent, self, pointerType_); + last_mouse_screen_position_ = event.PositionInScreen(); clientHelper_->RouteOrProcessMouseEvent(event); } else { WebTouchEvent event = WebTouchEventBuilder::Build(theEvent, self); @@ -646,6 +647,26 @@ lockedKeys_.reset(); } +- (void)setCursorLocked:(BOOL)locked { + mouse_locked_ = locked; + if (mouse_locked_) { + CGAssociateMouseAndMouseCursorPosition(NO); + NSRect bound = [self bounds]; + bound = [[self window] convertRectToScreen:bound]; + mouse_locked_screen_position_ = last_mouse_screen_position_; + CGDisplayMoveCursorToPoint(CGMainDisplayID(), + NSMakePoint(NSMidX(bound), NSMidY(bound))); + [NSCursor hide]; + } else { + // Unlock position of mouse cursor and unhide it. + CGAssociateMouseAndMouseCursorPosition(YES); + CGDisplayMoveCursorToPoint(CGMainDisplayID(), + NSMakePoint(mouse_locked_screen_position_.x(), + mouse_locked_screen_position_.y())); + [NSCursor unhide]; + } +} + // CommandDispatcherTarget implementation: - (BOOL)isKeyLocked:(NSEvent*)event { int keyCode = [event keyCode];
diff --git a/content/browser/scheduler/browser_task_executor.cc b/content/browser/scheduler/browser_task_executor.cc index 9fd9441..09c494c7 100644 --- a/content/browser/scheduler/browser_task_executor.cc +++ b/content/browser/scheduler/browser_task_executor.cc
@@ -300,9 +300,11 @@ return browser_ui_thread_scheduler_->GetTaskRunner(QueueType::kBootstrap); case BrowserTaskType::kNavigation: - // Note we currently ignore the priority for navigation tasks. + case BrowserTaskType::kPreconnect: + // Note we currently ignore the priority for navigation and preconnection + // tasks. return browser_ui_thread_scheduler_->GetTaskRunner( - QueueType::kNavigation); + QueueType::kNavigationAndPreconnection); case BrowserTaskType::kDefault: // Defer to traits.priority() below.
diff --git a/content/browser/scheduler/browser_ui_thread_scheduler.cc b/content/browser/scheduler/browser_ui_thread_scheduler.cc index 72810d7a..921d667 100644 --- a/content/browser/scheduler/browser_ui_thread_scheduler.cc +++ b/content/browser/scheduler/browser_ui_thread_scheduler.cc
@@ -35,9 +35,9 @@ task_queues_[QueueType::kBootstrap]->SetQueuePriority( base::sequence_manager::TaskQueue::kHighestPriority); - // Navigation tasks are also important during startup so prioritize them - // too. - task_queues_[QueueType::kNavigation]->SetQueuePriority( + // Navigation and preconnection tasks are also important during startup so + // prioritize them too. + task_queues_[QueueType::kNavigationAndPreconnection]->SetQueuePriority( base::sequence_manager::TaskQueue::kHighPriority); } }
diff --git a/content/browser/scheduler/browser_ui_thread_task_queue.cc b/content/browser/scheduler/browser_ui_thread_task_queue.cc index 2164a6f..3f87e34 100644 --- a/content/browser/scheduler/browser_ui_thread_task_queue.cc +++ b/content/browser/scheduler/browser_ui_thread_task_queue.cc
@@ -26,8 +26,8 @@ return "best_effort_tq"; case QueueType::kBootstrap: return "bootstrap_tq"; - case QueueType::kNavigation: - return "navigation_tq"; + case QueueType::kNavigationAndPreconnection: + return "navigation_and_preconnection_tq"; case QueueType::kDefault: return "default_tq"; case QueueType::kUserBlocking:
diff --git a/content/browser/scheduler/browser_ui_thread_task_queue.h b/content/browser/scheduler/browser_ui_thread_task_queue.h index d2c456c..389b288 100644 --- a/content/browser/scheduler/browser_ui_thread_task_queue.h +++ b/content/browser/scheduler/browser_ui_thread_task_queue.h
@@ -42,8 +42,8 @@ // For tasks on the critical path up to issuing the initial navigation. kBootstrap, - // For navigation related tasks. - kNavigation, + // For navigation and preconnection related tasks. + kNavigationAndPreconnection, // A generic high priority queue. Long term we should replace this with // additional semantic annotations.
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc index 0fbce527..b6fba02d 100644 --- a/content/browser/service_worker/embedded_worker_test_helper.cc +++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -131,7 +131,6 @@ NOTREACHED(); } void SetSchedulerKeepActive(bool keep_active) override { NOTREACHED(); } - void ProcessPurgeAndSuspend() override { NOTREACHED(); } void SetIsLockedToSite() override { NOTREACHED(); } void EnableV8LowMemoryMode() override { NOTREACHED(); }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index c03b3bf..6317b97 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -602,7 +602,9 @@ gfx::Rect GetCompositingRect() const { return compositing_rect_; } gfx::Rect GetViewportIntersection() const { return viewport_intersection_; } - bool GetOccludedOrObscured() const { return occluded_or_obscured_; } + blink::FrameOcclusionState GetOcclusionState() const { + return occlusion_state_; + } void Wait() { DCHECK(!run_loop_); @@ -622,9 +624,10 @@ private: ~UpdateViewportIntersectionMessageFilter() override {} - void OnUpdateViewportIntersection(const gfx::Rect& viewport_intersection, - const gfx::Rect& compositing_rect, - bool occluded_or_obscured) { + void OnUpdateViewportIntersection( + const gfx::Rect& viewport_intersection, + const gfx::Rect& compositing_rect, + blink::FrameOcclusionState occlusion_state) { // The message is going to be posted to UI thread after // OnUpdateViewportIntersection returns. This additional post on the IO // thread guarantees that by the time OnUpdateViewportIntersectionOnUI runs, @@ -634,25 +637,26 @@ base::BindOnce(&UpdateViewportIntersectionMessageFilter:: OnUpdateViewportIntersectionPostOnIO, this, viewport_intersection, compositing_rect, - occluded_or_obscured)); + occlusion_state)); } void OnUpdateViewportIntersectionPostOnIO( const gfx::Rect& viewport_intersection, const gfx::Rect& compositing_rect, - bool occluded_or_obscured) { + blink::FrameOcclusionState occlusion_state) { base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(&UpdateViewportIntersectionMessageFilter:: OnUpdateViewportIntersectionOnUI, this, viewport_intersection, compositing_rect, - occluded_or_obscured)); + occlusion_state)); } - void OnUpdateViewportIntersectionOnUI(const gfx::Rect& viewport_intersection, - const gfx::Rect& compositing_rect, - bool occluded_or_obscured) { + void OnUpdateViewportIntersectionOnUI( + const gfx::Rect& viewport_intersection, + const gfx::Rect& compositing_rect, + blink::FrameOcclusionState occlusion_state) { viewport_intersection_ = viewport_intersection; compositing_rect_ = compositing_rect; - occluded_or_obscured_ = occluded_or_obscured; + occlusion_state_ = occlusion_state; msg_received_ = true; if (run_loop_) run_loop_->Quit(); @@ -661,7 +665,8 @@ bool msg_received_; gfx::Rect compositing_rect_; gfx::Rect viewport_intersection_; - bool occluded_or_obscured_ = false; + blink::FrameOcclusionState occlusion_state_ = + blink::FrameOcclusionState::kUnknown; DISALLOW_COPY_AND_ASSIGN(UpdateViewportIntersectionMessageFilter); };
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 3ae2cd8..0c15633 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -357,92 +357,6 @@ } // namespace -// A class to observe windows that are mirroring the WebContentsView's host -// window. It keeps track of the occlusion state for each of these mirror -// windows and requests an update for the webcontent visibility if any of their -// occlusion state changes. -class WebContentsViewAura::MirrorWindowObserver : public aura::WindowObserver { - public: - explicit MirrorWindowObserver(WebContentsViewAura* view) : view_(view) {} - ~MirrorWindowObserver() override { - for (auto* mirror_window : mirror_windows_) { - DCHECK(mirror_window->HasObserver(this)); - mirror_window->RemoveObserver(this); - } - } - - // Starts observing the list of windows provided by |mirror_windows|. Results - // in removing itself as an observer from all other windows. Triggers a - // request to update web content visibilty based on the occlusion state of the - // newly added windows. - void UpdateMirrorWindowList( - const std::vector<aura::Window*>* mirror_windows) { - for (auto* mirror_window : mirror_windows_) { - DCHECK(mirror_window->HasObserver(this)); - mirror_window->RemoveObserver(this); - } - - mirror_windows_.clear(); - visible_mirror_windows_.clear(); - - if (!mirror_windows) { - view_->UpdateWebContentsVisibility(); - return; - } - - // Add self as an observer to the list of mirror windows. - for (auto* mirror_window : *mirror_windows) { - auto insert_result = mirror_windows_.insert(mirror_window); - if (insert_result.second) - mirror_window->AddObserver(this); - - if (mirror_window->occlusion_state() == - aura::Window::OcclusionState::VISIBLE) { - visible_mirror_windows_.insert(mirror_window); - } - } - view_->UpdateWebContentsVisibility(); - } - - // Returns true if there are any mirror windows that this class is observing - // that has their occlusion state set to VISIBLE. - bool HasVisibleMirrorWindow() const { return visible_mirror_windows_.size(); } - - private: - // aura::WindowObserver: - void OnWindowDestroyed(aura::Window* mirror_window) override { - mirror_windows_.erase(mirror_window); - visible_mirror_windows_.erase(mirror_window); - } - - // aura::WindowObserver: - void OnWindowOcclusionChanged(aura::Window* mirror_window) override { - auto it = visible_mirror_windows_.find(mirror_window); - if (mirror_window->occlusion_state() == - aura::Window::OcclusionState::VISIBLE && - it == visible_mirror_windows_.end()) { - visible_mirror_windows_.insert(mirror_window); - } else if (mirror_window->occlusion_state() != - aura::Window::OcclusionState::VISIBLE && - it != visible_mirror_windows_.end()) { - visible_mirror_windows_.erase(it); - } else { - return; - } - view_->UpdateWebContentsVisibility(); - } - - // Subset of |mirror_windows_| that are currently VISIBLE. - base::flat_set<aura::Window*> visible_mirror_windows_; - - // Set of mirror windows that this class is observing. - base::flat_set<aura::Window*> mirror_windows_; - - WebContentsViewAura* view_; - - DISALLOW_COPY_AND_ASSIGN(MirrorWindowObserver); -}; - class WebContentsViewAura::WindowObserver : public aura::WindowObserver, public aura::WindowTreeHostObserver { public: @@ -507,21 +421,6 @@ window->GetHost()->RemoveObserver(this); } - void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) override { - if (key == aura::client::kMirrorWindowList) { - if (!view_->mirror_window_observer_) { - view_->mirror_window_observer_ = - std::make_unique<MirrorWindowObserver>(view_); - } - const std::vector<aura::Window*>* mirror_window_list = - window->GetProperty(aura::client::kMirrorWindowList); - view_->mirror_window_observer_->UpdateMirrorWindowList( - mirror_window_list); - } - } - // Overridden WindowTreeHostObserver: void OnHostMovedInPixels(aura::WindowTreeHost* host, const gfx::Point& new_origin_in_pixels) override { @@ -834,11 +733,8 @@ } Visibility WebContentsViewAura::GetVisibility() const { - if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE || - (mirror_window_observer_ && - mirror_window_observer_->HasVisibleMirrorWindow())) { + if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE) return Visibility::VISIBLE; - } if (window_->occlusion_state() == aura::Window::OcclusionState::OCCLUDED) return Visibility::OCCLUDED;
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index c917d91..a1395da 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -63,7 +63,6 @@ private: class WindowObserver; - class MirrorWindowObserver; ~WebContentsViewAura() override; @@ -191,8 +190,6 @@ std::unique_ptr<WindowObserver> window_observer_; - std::unique_ptr<MirrorWindowObserver> mirror_window_observer_; - // The WebContentsImpl whose contents we display. WebContentsImpl* web_contents_;
diff --git a/content/browser/web_contents/web_contents_view_aura_unittest.cc b/content/browser/web_contents/web_contents_view_aura_unittest.cc index 74b88e8..426ffbfe 100644 --- a/content/browser/web_contents/web_contents_view_aura_unittest.cc +++ b/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -25,7 +25,6 @@ namespace { constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20); -constexpr gfx::Rect kMirrorWindowBounds = gfx::Rect(20, 0, 20, 20); } // namespace class WebContentsViewAuraTest : public RenderViewHostTestHarness { @@ -43,15 +42,10 @@ occluding_window_.reset(aura::test::CreateTestWindowWithDelegateAndType( nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(), false)); - - mirror_window_.reset(aura::test::CreateTestWindowWithDelegateAndType( - nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kMirrorWindowBounds, - nullptr, false)); } void TearDown() override { occluding_window_.reset(); - mirror_window_.reset(); RenderViewHostTestHarness::TearDown(); } @@ -62,33 +56,9 @@ aura::Window* GetNativeView() { return web_contents()->GetNativeView(); } - void EnableMirrorWindow(aura::Window* target_window) { - auto* mirror_window_list = new std::vector<aura::Window*>; - mirror_window_list->push_back(mirror_window_.get()); - target_window->SetProperty(aura::client::kMirrorWindowList, - mirror_window_list); - } - - void DisableMirrorWindow(aura::Window* target_window) { - target_window->ClearProperty(aura::client::kMirrorWindowList); - } - - void ShowMirrorWindow() { - aura::test::WindowTestApi(mirror_window_.get()) - .SetOcclusionState(aura::Window::OcclusionState::VISIBLE); - } - - void HideMirrorWindow() { - aura::test::WindowTestApi(mirror_window_.get()) - .SetOcclusionState(aura::Window::OcclusionState::HIDDEN); - } - // |occluding_window_| occludes |web_contents()| when it's shown. std::unique_ptr<aura::Window> occluding_window_; - // |mirror_window_| mirrors |web_contents()|. - std::unique_ptr<aura::Window> mirror_window_; - private: DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); }; @@ -120,163 +90,4 @@ EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE); } -TEST_F(WebContentsViewAuraTest, MirrorWindowForHiddenView) { - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - root_window()->Hide(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - ShowMirrorWindow(); - EnableMirrorWindow(GetNativeView()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - HideMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - root_window()->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(GetNativeView()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - root_window()->Hide(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); -} - -TEST_F(WebContentsViewAuraTest, MirrorWindowForOccludedView) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion); - - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - occluding_window_->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - EnableMirrorWindow(GetNativeView()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(GetNativeView()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); -} - -TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewParent) { - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - root_window()->Hide(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - root_window()->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - HideMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); -} - -TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewParent) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion); - - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - occluding_window_->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); -} - -TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewHost) { - // Make root_window() the host of GetNativeView(), and introduce an - // |intermediate_window| in the hierarchy between root_window() and - // GetNativeView(). - std::unique_ptr<aura::Window> intermediate_window( - aura::test::CreateTestWindowWithDelegateAndType( - nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(), - false)); - GetNativeView()->SetProperty(aura::client::kHostWindowKey, root_window()); - intermediate_window->AddChild(GetNativeView()); - root_window()->StackChildAtBottom(intermediate_window.get()); - intermediate_window->Show(); - - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - root_window()->Hide(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); - - root_window()->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - HideMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); -} - -TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewHost) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion); - - // Make root_window() the host of GetNativeView(), and introduce an - // |intermediate_window| in the hierarchy between root_window() and - // GetNativeView(). - std::unique_ptr<aura::Window> intermediate_window( - aura::test::CreateTestWindowWithDelegateAndType( - nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(), - false)); - GetNativeView()->SetProperty(aura::client::kHostWindowKey, root_window()); - intermediate_window->AddChild(GetNativeView()); - root_window()->StackChildAtBottom(intermediate_window.get()); - intermediate_window->Show(); - - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - occluding_window_->Show(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - EnableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); - - ShowMirrorWindow(); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); - - DisableMirrorWindow(root_window()); - EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); -} - } // namespace content
diff --git a/content/browser/webauth/authenticator_common.h b/content/browser/webauth/authenticator_common.h index 63c1d28e..7f19f167 100644 --- a/content/browser/webauth/authenticator_common.h +++ b/content/browser/webauth/authenticator_common.h
@@ -24,7 +24,7 @@ #include "device/fido/fido_constants.h" #include "device/fido/fido_transport_protocol.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" #include "url/origin.h" namespace base {
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h index 8a5d32c..97151dc0 100644 --- a/content/browser/webauth/authenticator_impl.h +++ b/content/browser/webauth/authenticator_impl.h
@@ -24,7 +24,7 @@ #include "device/fido/fido_constants.h" #include "device/fido/fido_transport_protocol.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" #include "url/origin.h" namespace base {
diff --git a/content/browser/webauth/authenticator_type_converters.h b/content/browser/webauth/authenticator_type_converters.h index ef27077..534270b 100644 --- a/content/browser/webauth/authenticator_type_converters.h +++ b/content/browser/webauth/authenticator_type_converters.h
@@ -16,7 +16,7 @@ #include "device/fido/public_key_credential_rp_entity.h" #include "device/fido/public_key_credential_user_entity.h" #include "mojo/public/cpp/bindings/type_converter.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" // TODO(hongjunchoi): Remove type converters and instead expose mojo interface // directly from device/fido service.
diff --git a/content/browser/webauth/scoped_virtual_authenticator_environment.h b/content/browser/webauth/scoped_virtual_authenticator_environment.h index 7a7450c..a74ba14 100644 --- a/content/browser/webauth/scoped_virtual_authenticator_environment.h +++ b/content/browser/webauth/scoped_virtual_authenticator_environment.h
@@ -16,7 +16,7 @@ #include "device/fido/fido_discovery_factory.h" #include "device/fido/virtual_fido_device.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h" namespace content {
diff --git a/content/browser/webauth/virtual_authenticator.h b/content/browser/webauth/virtual_authenticator.h index fe8ecc17..bcf5a2c 100644 --- a/content/browser/webauth/virtual_authenticator.h +++ b/content/browser/webauth/virtual_authenticator.h
@@ -14,7 +14,7 @@ #include "device/fido/fido_transport_protocol.h" #include "device/fido/virtual_fido_device.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h" namespace content {
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc index 6a055f3..9b460c26 100644 --- a/content/browser/webauth/webauth_browsertest.cc +++ b/content/browser/webauth/webauth_browsertest.cc
@@ -45,7 +45,7 @@ #include "services/service_manager/public/cpp/connector.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" namespace content {
diff --git a/content/browser/webrtc/webrtc_depth_capture_browsertest.cc b/content/browser/webrtc/webrtc_depth_capture_browsertest.cc index 6ac469b..cecf03e 100644 --- a/content/browser/webrtc/webrtc_depth_capture_browsertest.cc +++ b/content/browser/webrtc/webrtc_depth_capture_browsertest.cc
@@ -18,10 +18,6 @@ static const char kGetDepthStreamAndCallCreateImageBitmap[] = "getDepthStreamAndCallCreateImageBitmap"; -static const char kGetDepthStreamAndCameraCalibration[] = - "getDepthStreamAndCameraCalibration"; -static const char kGetBothStreamsAndCheckForFeaturesPresence[] = - "getBothStreamsAndCheckForFeaturesPresence"; static const char kGetStreamsByVideoKind[] = "getStreamsByVideoKind"; static const char kGetStreamsByVideoKindNoDepth[] = "getStreamsByVideoKindNoDepth"; @@ -89,47 +85,6 @@ } IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest, - GetDepthStreamAndCameraCalibration) { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendSwitchASCII("--enable-blink-features", - "MediaCaptureDepth"); - - ASSERT_TRUE(embedded_test_server()->Start()); - - GURL url( - embedded_test_server()->GetURL("/media/getusermedia-depth-capture.html")); - NavigateToURL(shell(), url); - - ExecuteJavascriptAndWaitForOk(base::StringPrintf( - "%s({video: true});", kGetDepthStreamAndCameraCalibration)); -} - -#if defined(OS_ANDROID) -// Flaky on android: https://crbug.com/734558 -#define MAYBE_GetBothStreamsAndCheckForFeaturesPresence \ - DISABLED_GetBothStreamsAndCheckForFeaturesPresence -#else -#define MAYBE_GetBothStreamsAndCheckForFeaturesPresence \ - GetBothStreamsAndCheckForFeaturesPresence -#endif - -IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest, - MAYBE_GetBothStreamsAndCheckForFeaturesPresence) { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendSwitchASCII("--enable-blink-features", - "MediaCaptureDepth"); - - ASSERT_TRUE(embedded_test_server()->Start()); - - GURL url( - embedded_test_server()->GetURL("/media/getusermedia-depth-capture.html")); - NavigateToURL(shell(), url); - - ExecuteJavascriptAndWaitForOk(base::StringPrintf( - "%s({video: true});", kGetBothStreamsAndCheckForFeaturesPresence)); -} - -IN_PROC_BROWSER_TEST_F(WebRtcTwoDeviceDepthCaptureBrowserTest, GetStreamsByVideoKind) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII("--enable-blink-features",
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index e278eaf2..8406b09 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -20,6 +20,7 @@ import "services/service_manager/public/mojom/interface_provider.mojom"; import "services/viz/public/interfaces/compositing/surface_id.mojom"; import "third_party/blink/public/mojom/blob/blob_url_store.mojom"; +import "third_party/blink/public/mojom/commit_result/commit_result.mojom"; import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom"; import "third_party/blink/public/mojom/frame/lifecycle.mojom"; import "third_party/blink/public/mojom/frame/navigation_initiator.mojom"; @@ -30,10 +31,9 @@ import "third_party/blink/public/mojom/referrer.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom"; -import "third_party/blink/public/web/commit_result.mojom"; import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; import "third_party/blink/public/mojom/portal/portal.mojom"; -import "third_party/blink/public/web/window_features.mojom"; +import "third_party/blink/public/mojom/window_features/window_features.mojom"; import "ui/base/mojo/window_open_disposition.mojom"; import "url/mojom/url.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom";
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 364be52..5ea1818 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -155,8 +155,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::FrameVisibility, blink::mojom::FrameVisibility::kMaxValue) IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::FrameOcclusionState, - blink::kUnknownOcclusionState, - blink::kMaxOcclusionState) + blink::FrameOcclusionState::kUnknown, + blink::FrameOcclusionState::kMaxValue) IPC_STRUCT_TRAITS_BEGIN(content::NavigationDownloadPolicy) IPC_STRUCT_TRAITS_MEMBER(observed_types)
diff --git a/content/common/input/input_handler.mojom b/content/common/input/input_handler.mojom index 4978308..749a04b1 100644 --- a/content/common/input/input_handler.mojom +++ b/content/common/input/input_handler.mojom
@@ -9,7 +9,7 @@ import "mojo/public/mojom/base/string16.mojom"; import "mojo/public/mojom/base/time.mojom"; import "services/ws/public/mojom/ime/ime.mojom"; -import "third_party/blink/public/web/selection_menu_behavior.mojom"; +import "third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom"; import "ui/events/mojo/event.mojom"; import "ui/events/mojo/event_constants.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom";
diff --git a/content/common/navigation_client.mojom b/content/common/navigation_client.mojom index 0641972..ece3b603 100644 --- a/content/common/navigation_client.mojom +++ b/content/common/navigation_client.mojom
@@ -13,7 +13,7 @@ import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom"; -import "third_party/blink/public/web/commit_result.mojom"; +import "third_party/blink/public/mojom/commit_result/commit_result.mojom"; // See src/content/common/navigation_params.h [Native]
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 2796abe..1e6c409 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -261,9 +261,6 @@ // If set to true, then the scheduler should not freeze the renderer. SetSchedulerKeepActive(bool keep_active); - // Tells the renderer process to purge and suspend. - ProcessPurgeAndSuspend(); - // Tells the renderer process that it has been locked to a site (i.e., a // scheme plus eTLD+1, such as https://google.com), or to a more specific // origin.
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 851f662c..19db0b6c 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -78,8 +78,8 @@ "//skia/public/interfaces:interfaces_java", "//third_party/android_deps:com_android_support_support_annotations_java", "//third_party/android_deps:com_android_support_support_compat_java", - "//third_party/blink/public:android_mojo_bindings_java", "//third_party/blink/public:blink_headers_java", + "//third_party/blink/public/mojom:android_mojo_bindings_java", "//third_party/blink/public/mojom:mojom_core_java", "//third_party/blink/public/mojom:mojom_platform_java", "//third_party/blink/public/mojom:speech_recognition_error_code_java", @@ -477,8 +477,8 @@ "//third_party/android_deps:com_android_support_support_annotations_java", "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", - "//third_party/blink/public:android_mojo_bindings_java", "//third_party/blink/public:blink_headers_java", + "//third_party/blink/public/mojom:android_mojo_bindings_java", "//third_party/hamcrest:hamcrest_java", "//third_party/jsr-305:jsr_305_javalib", "//third_party/junit", @@ -583,7 +583,7 @@ "//base:base_junit_test_support", "//media/mojo/interfaces:interfaces_java", "//mojo/public/java:bindings_java", - "//third_party/blink/public:android_mojo_bindings_java", + "//third_party/blink/public/mojom:android_mojo_bindings_java", "//ui/android:ui_java", "//ui/gfx/geometry/mojo:mojo_java", ]
diff --git a/content/public/android/java/src/org/chromium/content/browser/TtsPlatformImpl.java b/content/public/android/java/src/org/chromium/content/browser/TtsPlatformImpl.java index d7bf9d5..2cbb018 100644 --- a/content/public/android/java/src/org/chromium/content/browser/TtsPlatformImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/TtsPlatformImpl.java
@@ -9,11 +9,12 @@ import android.speech.tts.UtteranceProgressListener; import org.chromium.base.ContextUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.task.AsyncTask; +import org.chromium.base.task.PostTask; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.util.ArrayList; import java.util.HashMap; @@ -27,7 +28,7 @@ * * Threading model note: all calls from C++ must happen on the UI thread. * Callbacks from Android may happen on a different thread, so we always - * use ThreadUtils.runOnUiThread when calling back to C++. + * use PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, ...) when calling back to C++. */ @JNINamespace("content") class TtsPlatformImpl { @@ -77,7 +78,7 @@ mNativeTtsPlatformImplAndroid = nativeTtsPlatformImplAndroid; mTextToSpeech = new TextToSpeech(ContextUtils.getApplicationContext(), status -> { if (status == TextToSpeech.SUCCESS) { - ThreadUtils.runOnUiThread(() -> initialize()); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> initialize()); } }); addOnUtteranceProgressListener(); @@ -191,7 +192,7 @@ * Post a task to the UI thread to send the TTS "end" event. */ protected void sendEndEventOnUiThread(final String utteranceId) { - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { if (mNativeTtsPlatformImplAndroid != 0) { nativeOnEndEvent(mNativeTtsPlatformImplAndroid, Integer.parseInt(utteranceId)); } @@ -202,7 +203,7 @@ * Post a task to the UI thread to send the TTS "error" event. */ protected void sendErrorEventOnUiThread(final String utteranceId) { - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { if (mNativeTtsPlatformImplAndroid != 0) { nativeOnErrorEvent(mNativeTtsPlatformImplAndroid, Integer.parseInt(utteranceId)); } @@ -213,7 +214,7 @@ * Post a task to the UI thread to send the TTS "start" event. */ protected void sendStartEventOnUiThread(final String utteranceId) { - ThreadUtils.runOnUiThread(() -> { + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { if (mNativeTtsPlatformImplAndroid != 0) { nativeOnStartEvent(mNativeTtsPlatformImplAndroid, Integer.parseInt(utteranceId)); }
diff --git a/content/public/app/content_browser_manifest.cc b/content/public/app/content_browser_manifest.cc index 6ab9ef0..f9cdef1 100644 --- a/content/public/app/content_browser_manifest.cc +++ b/content/public/app/content_browser_manifest.cc
@@ -200,7 +200,6 @@ "autofill.mojom.AutofillDriver", "autofill.mojom.PasswordManagerDriver", "blink.mojom.AnchorElementMetricsHost", - "blink.mojom.AudioContextManager", "blink.mojom.Authenticator", "blink.mojom.BackgroundFetchService", "blink.mojom.CacheStorage",
diff --git a/content/public/browser/browser_task_traits.h b/content/public/browser/browser_task_traits.h index dab15e14f..f90334b 100644 --- a/content/public/browser/browser_task_traits.h +++ b/content/public/browser/browser_task_traits.h
@@ -35,6 +35,9 @@ // Navigation related tasks. kNavigation, + // A subset of network tasks related to preconnection. + kPreconnect, + // Used to validate values in Java kBrowserTaskType_Last };
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 00902fa..42b673a 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -55,7 +55,7 @@ #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/renderer_preference_watcher.mojom-forward.h" #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-forward.h" -#include "third_party/blink/public/web/window_features.mojom-forward.h" +#include "third_party/blink/public/mojom/window_features/window_features.mojom-forward.h" #include "ui/accessibility/ax_mode.h" #include "ui/base/page_transition_types.h" #include "ui/base/window_open_disposition.h"
diff --git a/content/public/browser/media_device_id.cc b/content/public/browser/media_device_id.cc index 769af476f..8a7651e 100644 --- a/content/public/browser/media_device_id.cc +++ b/content/public/browser/media_device_id.cc
@@ -4,6 +4,7 @@ #include "content/public/browser/media_device_id.h" #include "base/strings/string_util.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "content/browser/browser_main_loop.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "media/audio/audio_device_description.h" @@ -38,6 +39,18 @@ device_id); } +void GetMediaDeviceIDForHMAC( + blink::MediaStreamType stream_type, + std::string salt, + url::Origin security_origin, + std::string hmac_device_id, + base::OnceCallback<void(const base::Optional<std::string>&)> callback) { + MediaStreamManager::GetMediaDeviceIDForHMAC( + stream_type, std::move(salt), std::move(security_origin), + std::move(hmac_device_id), base::SequencedTaskRunnerHandle::Get(), + std::move(callback)); +} + bool IsValidDeviceId(const std::string& device_id) { constexpr int hash_size = 64; // 32 bytes * 2 char/byte hex encoding if (media::AudioDeviceDescription::IsDefaultDevice(device_id) ||
diff --git a/content/public/browser/media_device_id.h b/content/public/browser/media_device_id.h index 5a921f9..6d3b1ce 100644 --- a/content/public/browser/media_device_id.h +++ b/content/public/browser/media_device_id.h
@@ -34,12 +34,24 @@ const std::string& device_guid, const std::string& raw_unique_id); +// This function is deprecated. Use the callback version below instead. CONTENT_EXPORT bool GetMediaDeviceIDForHMAC(blink::MediaStreamType stream_type, const std::string& salt, const url::Origin& security_origin, const std::string& source_id, std::string* device_id); +// Returns the raw device ID for the given HMAC |hmac_device_id| for the given +// |security_origin| and |salt|. The result is passed via |callback| on the +// task runner where this function is called. If |hmac_device_id| is not a +// valid device ID nullopt is returned. +CONTENT_EXPORT void GetMediaDeviceIDForHMAC( + blink::MediaStreamType stream_type, + std::string salt, + url::Origin security_origin, + std::string hmac_device_id, + base::OnceCallback<void(const base::Optional<std::string>&)> callback); + CONTENT_EXPORT bool IsValidDeviceId(const std::string& device_id); } // namespace content
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 7463db06..60a7dc42 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -401,9 +401,6 @@ // Returns true if DisableKeepAliveRefCount() was called. virtual bool IsKeepAliveRefCountDisabled() = 0; - // Purges and suspends the renderer process. - virtual void PurgeAndSuspend() = 0; - // Resumes the renderer process. virtual void Resume() = 0;
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index a3f06f2..7b8ed92 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -154,8 +154,6 @@ "isolated_world_ids.h", "javascript_dialog_type.h", "main_function_params.h", - "manifest_util.cc", - "manifest_util.h", "menu_item.cc", "menu_item.h", "mhtml_generation_params.cc",
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index 062a1ea..d1d0913c 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h
@@ -20,13 +20,13 @@ #include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" +#include "third_party/blink/public/mojom/window_features/window_features.mojom.h" #include "third_party/blink/public/platform/web_drag_operation.h" #include "third_party/blink/public/platform/web_history_scroll_restoration_type.h" #include "third_party/blink/public/platform/web_point.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_security_style.h" #include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/web/window_features.mojom.h" #include "ui/accessibility/ax_event.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_relative_bounds.h"
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index a09878d..dfd9705 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -368,20 +368,6 @@ const base::Feature kPrioritizeBootstrapTasks = { "PrioritizeBootstrapTasks", base::FEATURE_ENABLED_BY_DEFAULT}; -// Enables Purge+Throttle on platforms except Android and MacOS. -// (Android) Purge+Throttle depends on TabManager, but TabManager doesn't -// support Android. Enable after Android is supported. -// (MacOS X) Enable after Purge+Throttle handles memory pressure signals -// send by OS correctly. -const base::Feature kPurgeAndSuspend { - "PurgeAndSuspend", -#if defined(OS_MACOSX) || defined(OS_ANDROID) - base::FEATURE_DISABLED_BY_DEFAULT -#else - base::FEATURE_ENABLED_BY_DEFAULT -#endif -}; - // Enable raster-inducing scroll. const base::Feature kRasterInducingScroll{"RasterInducingScroll", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -712,6 +698,10 @@ const base::Feature kWarmUpNetworkProcess{"WarmUpNetworkProcess", base::FEATURE_DISABLED_BY_DEFAULT}; +// Force display to tick at ~60Hz refresh rate. +const base::Feature kForce60HzRefreshRate{"Force60HzRefreshRate", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls whether the WebNFC API is enabled: // https://w3c.github.io/web-nfc/ const base::Feature kWebNfc{"WebNFC", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 12c931b..b6859bba 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -89,7 +89,6 @@ CONTENT_EXPORT extern const base::Feature kPrioritizeBootstrapTasks; CONTENT_EXPORT extern const base::Feature kProcessSharingWithStrictSiteInstances; -CONTENT_EXPORT extern const base::Feature kPurgeAndSuspend; CONTENT_EXPORT extern const base::Feature kRasterInducingScroll; CONTENT_EXPORT extern const base::Feature kRenderDocumentForMainFrame; CONTENT_EXPORT extern const base::Feature kRenderDocumentForSubframe; @@ -156,6 +155,7 @@ CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility; CONTENT_EXPORT extern const base::Feature kBackgroundMediaRendererHasModerateBinding; +CONTENT_EXPORT extern const base::Feature kForce60HzRefreshRate; CONTENT_EXPORT extern const base::Feature kHideIncorrectlySizedFullscreenFrames; CONTENT_EXPORT extern const base::Feature kWarmUpNetworkProcess; CONTENT_EXPORT extern const base::Feature kWebNfc;
diff --git a/content/public/renderer/window_features_converter.h b/content/public/renderer/window_features_converter.h index dbc78a7..aafc913f 100644 --- a/content/public/renderer/window_features_converter.h +++ b/content/public/renderer/window_features_converter.h
@@ -6,8 +6,8 @@ #define CONTENT_PUBLIC_RENDERER_WINDOW_FEATURES_CONVERTER_H_ #include "content/common/content_export.h" +#include "third_party/blink/public/mojom/window_features/window_features.mojom.h" #include "third_party/blink/public/web/web_window_features.h" -#include "third_party/blink/public/web/window_features.mojom.h" namespace content {
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/JavaScriptUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/JavaScriptUtils.java index 2850c44..6161837 100644 --- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/JavaScriptUtils.java +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/JavaScriptUtils.java
@@ -9,6 +9,8 @@ import org.junit.Assert; import org.chromium.base.ThreadUtils; +import org.chromium.base.task.PostTask; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper; @@ -45,12 +47,8 @@ Assert.assertFalse("Executing JavaScript should be done from the test thread, " + " not the UI thread", ThreadUtils.runningOnUiThread()); - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - helper.evaluateJavaScriptForTests(webContents, code); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> helper.evaluateJavaScriptForTests(webContents, code)); helper.waitUntilHasValue(timeout, timeoutUnits); Assert.assertTrue("Failed to retrieve JavaScript evaluation results.", helper.hasValue()); return helper.getJsonResultAndClear(); @@ -73,11 +71,7 @@ * Executes the given snippet of JavaScript code but does not wait for the result. */ public static void executeJavaScript(final WebContents webContents, final String code) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - webContents.evaluateJavaScriptForTests(code, null); - } - }); + PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, + () -> webContents.evaluateJavaScriptForTests(code, null)); } }
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index b946a64c..300fb46 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -1938,10 +1938,8 @@ main_frame_manager->GetRoot(), name)) { AccessibilityNotificationWaiter accessibility_waiter( main_frame, ax::mojom::Event::kNone); - for (FrameTreeNode* node : frame_tree->Nodes()) { - accessibility_waiter.ListenToAdditionalFrame( - node->current_frame_host()); - } + for (FrameTreeNode* node : frame_tree->Nodes()) + accessibility_waiter.ListenToAdditionalFrame(node->current_frame_host()); content::BrowserPluginGuestManager* guest_manager = web_contents_impl->GetBrowserContext()->GetGuestManager(); @@ -1951,7 +1949,10 @@ &accessibility_waiter)); } - accessibility_waiter.WaitForNotification(); + // This loop is racy, so check after a timeout in case the notification came + // in while we were resetting the AccessibilityNotificationWaiter. + accessibility_waiter.WaitForNotificationWithTimeout( + base::TimeDelta::FromMilliseconds(200)); main_frame_manager = main_frame->browser_accessibility_manager(); } }
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 48b6543..57529dd9 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -396,8 +396,6 @@ return false; } -void MockRenderProcessHost::PurgeAndSuspend() {} - void MockRenderProcessHost::Resume() {} mojom::Renderer* MockRenderProcessHost::GetRendererInterface() {
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index b6d205c..55e86b8 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -143,7 +143,6 @@ void DecrementKeepAliveRefCount(KeepAliveClientType) override; void DisableKeepAliveRefCount() override; bool IsKeepAliveRefCountDisabled() override; - void PurgeAndSuspend() override; void Resume() override; mojom::Renderer* GetRendererInterface() override; void CreateURLLoaderFactory(
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc index 7ddf0c62..f9e7ea4 100644 --- a/content/public/test/test_browser_thread_bundle.cc +++ b/content/public/test/test_browser_thread_bundle.cc
@@ -31,32 +31,28 @@ namespace content { TestBrowserThreadBundle::~TestBrowserThreadBundle() { - // To ensure a clean teardown, each thread's message loop must be flushed - // just before the thread is destroyed. But stopping a fake thread does not - // automatically flush the message loop, so we have to do it manually. - // See http://crbug.com/247525 for discussion. - base::RunLoop().RunUntilIdle(); - io_thread_->Stop(); - base::RunLoop().RunUntilIdle(); - ui_thread_->Stop(); - base::RunLoop().RunUntilIdle(); + // This is required to ensure we run all remaining MessageLoop and + // TaskScheduler tasks in an atomic step. This is a bit different than + // production where the main thread is not flushed after it's done running + // but this approach is preferred in unit tests as running more tasks can + // merely uncover more issues (e.g. if a bad tasks is posted but never + // blocked upon it could make a test flaky whereas by flushing we guarantee + // it will blow up). + RunUntilIdle(); - // Skip the following steps when RunAllTasksUntilIdle might result in a hang - // (ExecutionMode::QUEUED) or for MainThreadType::MOCK_TIME where we haven't - // enforced there being no pending tasks. - if (main_thread_type() != MainThreadType::MOCK_TIME && - execution_control_mode() != ExecutionMode::QUEUED) { - // This is required to ensure we run all remaining MessageLoop and - // TaskScheduler tasks in an atomic step. This is a bit different than - // production where the main thread is not flushed after it's done running - // but this approach is preferred in unit tests as running more tasks can - // merely uncover more issues (e.g. if a bad tasks is posted but never - // blocked upon it could make a test flaky whereas by flushing we guarantee - // it will blow up). - RunAllTasksUntilIdle(); - CHECK(MainThreadIsIdle()) << sequence_manager()->DescribeAllPendingTasks(); + // When REAL_IO_THREAD, we need to stop the IO thread explicitly and flush + // again. + if (real_io_thread_) { + io_thread_->Stop(); + RunUntilIdle(); } + // The only way this check can fail after RunUntilIdle() is if a test is + // running its own base::Thread's. Such tests should make sure to coalesce + // independent threads before this point. + // TODO(crbug.com/938126): Enable this CHECK once flaky tests have been fixed. + // CHECK(MainThreadIsIdle()) << sequence_manager()->DescribeAllPendingTasks(); + BrowserTaskExecutor::ResetForTesting(); // Run DestructionObservers before our fake threads go away to ensure
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 623b95e..764808f 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -553,12 +553,17 @@ if (!web_description.IsEmpty()) { TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDescription, web_description.Utf8()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom, - static_cast<int32_t>(description_from)); + dst->SetDescriptionFrom(description_from); AddIntListAttributeFromWebObjects( ax::mojom::IntListAttribute::kDescribedbyIds, description_objects, dst); } + blink::WebString web_title = src.Title(name_from); + if (!web_title.IsEmpty()) { + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kTooltip, + web_title.Utf8()); + } + if (src.ValueDescription().length()) { TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue, src.ValueDescription().Utf8());
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index 5b0cd7c..ec7e2231 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -692,7 +692,6 @@ break; case ax::mojom::Action::kSetValue: target.SetValue(blink::WebString::FromUTF8(data.value)); - HandleAXEvent(target, ax::mojom::Event::kValueChanged); break; case ax::mojom::Action::kShowContextMenu: target.ShowContextMenu(); @@ -723,6 +722,9 @@ } break; case ax::mojom::Action::kSignalEndOfTest: + // Wait for 100ms to allow pending events to come in + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); + HandleAXEvent(root, ax::mojom::Event::kEndOfTest); break; }
diff --git a/content/renderer/accessibility/render_accessibility_impl_browsertest.cc b/content/renderer/accessibility/render_accessibility_impl_browsertest.cc index 22eac1f..c1758309 100644 --- a/content/renderer/accessibility/render_accessibility_impl_browsertest.cc +++ b/content/renderer/accessibility/render_accessibility_impl_browsertest.cc
@@ -292,7 +292,7 @@ ExecuteJavaScriptForTests( "document.getElementById('B').style.visibility = 'hidden';"); // Force layout now. - ExecuteJavaScriptForTests("document.getElementById('B').offsetLeft;"); + root_obj.UpdateLayoutAndCheckValidity(); // Send a childrenChanged on "A". sink_->ClearMessages(); @@ -328,17 +328,19 @@ EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); - // Show node "B", then send a childrenChanged on "A". - ExecuteJavaScriptForTests( - "document.getElementById('B').style.visibility = 'visible';"); - ExecuteJavaScriptForTests("document.getElementById('B').offsetLeft;"); - - sink_->ClearMessages(); WebDocument document = GetMainFrame()->GetDocument(); WebAXObject root_obj = WebAXObject::FromWebDocument(document); WebAXObject node_a = root_obj.ChildAt(0); + WebAXObject node_c = node_a.ChildAt(0); + + // Show node "B", then send a childrenChanged on "A". + ExecuteJavaScriptForTests( + "document.getElementById('B').style.visibility = 'visible';"); + + root_obj.UpdateLayoutAndCheckValidity(); + sink_->ClearMessages(); + WebAXObject node_b = node_a.ChildAt(0); - WebAXObject node_c = node_b.ChildAt(0); render_accessibility().HandleAXEvent(node_a, ax::mojom::Event::kChildrenChanged); @@ -415,14 +417,16 @@ EXPECT_TRUE(mock_annotator().image_processors_[0].is_bound()); EXPECT_EQ(1u, mock_annotator().callbacks_.size()); - // Show node "B". - ExecuteJavaScriptForTests( - "document.getElementById('B').style.visibility = 'visible';"); - - sink_->ClearMessages(); WebDocument document = GetMainFrame()->GetDocument(); WebAXObject root_obj = WebAXObject::FromWebDocument(document); ASSERT_FALSE(root_obj.IsNull()); + + // Show node "B". + ExecuteJavaScriptForTests( + "document.getElementById('B').style.visibility = 'visible';"); + sink_->ClearMessages(); + root_obj.UpdateLayoutAndCheckValidity(); + // This should update the annotations of all images on the page, including the // already visible one. render_accessibility().MarkWebAXObjectDirty(root_obj, true /* subtree */);
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index 04a2129b..443b3de1 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -175,8 +175,6 @@ void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override {} void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override {} - void DidSwapAfterSnapshotRequestReceived( - const std::vector<ui::LatencyInfo>& latency_info) override {} }; // TODO(danakj): These don't to be stored in unique_ptrs when OutputSurface
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index df64a06..16621a8 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -663,10 +663,6 @@ response_override = extra_data->TakeNavigationResponseOverrideOwnership(); } - // Navigation requests should not go through here. - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - // TODO(domfarolino): Retrieve the referrer in the form of a referrer member // instead of the header field. See https://crbug.com/850813. GURL referrer_url( @@ -750,7 +746,8 @@ resource_request->fetch_request_context_type = static_cast<int>(GetRequestContextTypeForWebURLRequest(request)); - resource_request->fetch_frame_type = request.GetFrameType(); + resource_request->fetch_frame_type = + network::mojom::RequestContextFrameType::kNone; resource_request->request_body = GetRequestBodyForWebURLRequest(request).get(); resource_request->keepalive = request.GetKeepalive();
diff --git a/content/renderer/loader/web_url_request_util.cc b/content/renderer/loader/web_url_request_util.cc index da6ad97..27a8bd2 100644 --- a/content/renderer/loader/web_url_request_util.cc +++ b/content/renderer/loader/web_url_request_util.cc
@@ -206,8 +206,6 @@ } ResourceType WebURLRequestToResourceType(const WebURLRequest& request) { - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); return RequestContextToResourceType(request.GetRequestContext()); }
diff --git a/content/renderer/manifest/manifest_parser.cc b/content/renderer/manifest/manifest_parser.cc index fe4cca4..0b93647 100644 --- a/content/renderer/manifest/manifest_parser.cc +++ b/content/renderer/manifest/manifest_parser.cc
@@ -14,9 +14,9 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" -#include "content/public/common/manifest_util.h" #include "content/renderer/manifest/manifest_uma_util.h" #include "net/base/mime_util.h" +#include "third_party/blink/public/common/manifest/manifest_util.h" #include "third_party/blink/public/platform/web_icon_sizes_parser.h" #include "third_party/blink/public/platform/web_size.h" #include "third_party/blink/public/platform/web_string.h" @@ -247,7 +247,7 @@ return blink::kWebDisplayModeUndefined; blink::WebDisplayMode display_enum = - WebDisplayModeFromString(base::UTF16ToUTF8(display.string())); + blink::WebDisplayModeFromString(base::UTF16ToUTF8(display.string())); if (display_enum == blink::kWebDisplayModeUndefined) AddErrorInfo("unknown 'display' value ignored."); return display_enum; @@ -262,7 +262,7 @@ return blink::kWebScreenOrientationLockDefault; blink::WebScreenOrientationLockType orientation_enum = - WebScreenOrientationLockTypeFromString( + blink::WebScreenOrientationLockTypeFromString( base::UTF16ToUTF8(orientation.string())); if (orientation_enum == blink::kWebScreenOrientationLockDefault) AddErrorInfo("unknown 'orientation' value ignored.");
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/content/renderer/media_capture_from_element/canvas_capture_handler.cc index f19a522f..537b69c 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler.cc +++ b/content/renderer/media_capture_from_element/canvas_capture_handler.cc
@@ -33,6 +33,18 @@ namespace content { +namespace { + +// Return the gfx::ColorSpace that the pixels resulting from calling +// ConvertToYUVFrame on |image| will be in. +gfx::ColorSpace GetImageYUVColorSpace(sk_sp<SkImage> image) { + // TODO: Determine the ColorSpace::MatrixID and ColorSpace::RangeID that the + // calls to libyuv are assuming. + return gfx::ColorSpace(); +} + +} // namespace + // Implementation VideoCapturerSource that is owned by // MediaStreamVideoCapturerSource and delegates the Start/Stop calls to // CanvasCaptureHandler. @@ -176,7 +188,7 @@ static_cast<const uint8_t*>(pixmap.addr(0, 0)), gfx::Size(pixmap.width(), pixmap.height()), pixmap.rowBytes(), pixmap.colorType()), - timestamp, image->refColorSpace()); + timestamp, GetImageYUVColorSpace(image)); return; } @@ -269,7 +281,7 @@ is_opaque, false /* flip */, temp_argb_frame->visible_data(VideoFrame::kARGBPlane), image_size, temp_argb_frame->stride(VideoFrame::kARGBPlane), kN32_SkColorType), - timestamp, image->refColorSpace()); + timestamp, GetImageYUVColorSpace(image)); } void CanvasCaptureHandler::ReadARGBPixelsAsync( @@ -325,16 +337,12 @@ const bool result = backend_texture.getGLTextureInfo(&texture_info); DCHECK(result); DCHECK(context_provider->GetGLHelper()); - const gpu::MailboxHolder& mailbox_holder = - context_provider->GetGLHelper()->ProduceMailboxHolderFromTexture( - texture_info.fID); - DCHECK_EQ(static_cast<int>(texture_info.fTarget), GL_TEXTURE_2D); viz::ReadbackYUVInterface* const yuv_reader = context_provider->GetGLHelper()->GetReadbackPipelineYUV( surface_origin != kTopLeft_GrSurfaceOrigin); yuv_reader->ReadbackYUV( - mailbox_holder.mailbox, mailbox_holder.sync_token, image_size, - gfx::Rect(image_size), output_frame->stride(media::VideoFrame::kYPlane), + texture_info.fID, image_size, gfx::Rect(image_size), + output_frame->stride(media::VideoFrame::kYPlane), output_frame->visible_data(media::VideoFrame::kYPlane), output_frame->stride(media::VideoFrame::kUPlane), output_frame->visible_data(media::VideoFrame::kUPlane), @@ -361,7 +369,7 @@ } // Let |image| fall out of scope after we are done reading. const bool is_opaque = image->isOpaque(); - const auto color_space = image->refColorSpace(); + const auto color_space = GetImageYUVColorSpace(image); image = nullptr; SendFrame( @@ -383,7 +391,7 @@ DLOG(ERROR) << "Couldn't read SkImage using async callback"; return; } - SendFrame(yuv_frame, this_frame_ticks, image->refColorSpace()); + SendFrame(yuv_frame, this_frame_ticks, GetImageYUVColorSpace(image)); } scoped_refptr<media::VideoFrame> CanvasCaptureHandler::ConvertToYUVFrame( @@ -447,7 +455,7 @@ void CanvasCaptureHandler::SendFrame(scoped_refptr<VideoFrame> video_frame, base::TimeTicks this_frame_ticks, - sk_sp<SkColorSpace> color_space) { + const gfx::ColorSpace& color_space) { DCHECK(main_render_thread_checker_.CalledOnValidThread()); // If this function is called asynchronously, |delegate_| might have been @@ -458,8 +466,8 @@ if (!first_frame_ticks_) first_frame_ticks_ = this_frame_ticks; video_frame->set_timestamp(this_frame_ticks - *first_frame_ticks_); - if (color_space) - video_frame->set_color_space(gfx::ColorSpace(*color_space)); + if (color_space.IsValid()) + video_frame->set_color_space(color_space); last_frame_ = video_frame; io_task_runner_->PostTask(
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler.h b/content/renderer/media_capture_from_element/canvas_capture_handler.h index 9e40d165..38cec53 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler.h +++ b/content/renderer/media_capture_from_element/canvas_capture_handler.h
@@ -101,7 +101,7 @@ SkColorType source_color_type); void SendFrame(scoped_refptr<media::VideoFrame> video_frame, base::TimeTicks this_frame_ticks, - sk_sp<SkColorSpace> color_space); + const gfx::ColorSpace& color_space); void AddVideoCapturerSourceToVideoTrack( std::unique_ptr<media::VideoCapturerSource> source,
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc index e09dbf6..1c0031b 100644 --- a/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc +++ b/content/renderer/media_capture_from_element/canvas_capture_handler_unittest.cc
@@ -120,7 +120,6 @@ video_frame->visible_data(media::VideoFrame::kAPlane); EXPECT_EQ(kTestAlphaValue, a_plane[0]); } - EXPECT_TRUE(video_frame->ColorSpace().IsValid()); } blink::WebMediaStreamTrack track_;
diff --git a/content/renderer/navigation_state.cc b/content/renderer/navigation_state.cc index bdf0236..f6ae1a96 100644 --- a/content/renderer/navigation_state.cc +++ b/content/renderer/navigation_state.cc
@@ -10,7 +10,7 @@ #include "content/common/frame_messages.h" #include "content/public/common/navigation_policy.h" #include "content/renderer/internal_document_state_data.h" -#include "third_party/blink/public/web/commit_result.mojom.h" +#include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h" namespace content {
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1fac3bcf..d2c7852 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5214,7 +5214,7 @@ custom_user_agent = old_extra_data->custom_user_agent(); if (!custom_user_agent.IsNull()) { if (custom_user_agent.IsEmpty()) - request.ClearHTTPHeaderField("User-Agent"); + request.ClearHttpHeaderField("User-Agent"); else request.SetHTTPHeaderField("User-Agent", custom_user_agent); }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 435b6e6..a2118cf2 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -77,6 +77,7 @@ #include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" +#include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h" @@ -86,7 +87,6 @@ #include "third_party/blink/public/platform/web_focus_type.h" #include "third_party/blink/public/platform/web_loading_behavior_flag.h" #include "third_party/blink/public/platform/web_media_player.h" -#include "third_party/blink/public/web/commit_result.mojom.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_frame_load_type.h"
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 05d9cd6..59cef91 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -223,8 +223,7 @@ // TODO(samans): Investigate if it is safe to delay creation of this // object until a FrameSinkId is provided. parent_local_surface_id_allocator_( - std::make_unique<viz::ParentLocalSurfaceIdAllocator>()), - last_occlusion_state_(blink::kUnknownOcclusionState) { + std::make_unique<viz::ParentLocalSurfaceIdAllocator>()) { std::pair<RoutingIDProxyMap::iterator, bool> result = g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this)); CHECK(result.second) << "Inserting a duplicate item.";
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 337e978..61b5118 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -337,7 +337,8 @@ gfx::Rect last_intersection_rect_; gfx::Rect last_compositor_visible_rect_; - blink::FrameOcclusionState last_occlusion_state_; + blink::FrameOcclusionState last_occlusion_state_ = + blink::FrameOcclusionState::kUnknown; #if defined(USE_AURA) std::unique_ptr<MusEmbeddedFrame> mus_embedded_frame_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 822c12e..01be438 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1664,48 +1664,6 @@ process_state_ = process_state; } -void RenderThreadImpl::ProcessPurgeAndSuspend() { - if (!RendererIsHidden()) - return; - - if (!base::FeatureList::IsEnabled(features::kPurgeAndSuspend)) - return; - - if (base::MemoryPressureListener::AreNotificationsSuppressed()) - return; - - base::MemoryPressureListener::NotifyMemoryPressure( - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); - needs_to_record_first_active_paint_ = true; - - RendererMemoryMetrics memory_metrics; - if (!GetRendererMemoryMetrics(&memory_metrics)) - return; - - purge_and_suspend_memory_metrics_ = memory_metrics; - - // Use of Unretained(this) is safe because |this| has the same lifetime as a - // renderer process. - GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( - FROM_HERE, - base::BindOnce( - &RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics, - base::Unretained(this), "30min", process_foregrounded_count_), - base::TimeDelta::FromMinutes(30)); - GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( - FROM_HERE, - base::BindOnce( - &RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics, - base::Unretained(this), "60min", process_foregrounded_count_), - base::TimeDelta::FromMinutes(60)); - GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( - FROM_HERE, - base::BindOnce( - &RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics, - base::Unretained(this), "90min", process_foregrounded_count_), - base::TimeDelta::FromMinutes(90)); -} - void RenderThreadImpl::SetIsLockedToSite() { DCHECK(blink_platform_impl_); blink_platform_impl_->SetIsLockedToSite(); @@ -1813,14 +1771,14 @@ ? current.allocator - previous.allocator \ : 0) -static void RecordPurgeAndSuspendMemoryGrowthKB(const char* basename, - const char* suffix, - int memory_usage) { +static void RecordBackgroundedRenderPurgeMemoryGrowthKB(const char* basename, + const char* suffix, + int memory_usage) { std::string histogram_name = base::StringPrintf("%s.%s", basename, suffix); base::UmaHistogramMemoryKB(histogram_name, memory_usage); } -void RenderThreadImpl::RecordPurgeAndSuspendMemoryGrowthMetrics( +void RenderThreadImpl::OnRecordMetricsForBackgroundedRendererPurgeTimerExpired( const char* suffix, int foregrounded_count_when_purged) { // If this renderer is resumed, we should not update UMA. @@ -1833,35 +1791,66 @@ if (!GetRendererMemoryMetrics(&memory_metrics)) return; - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.PartitionAllocKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, partition_alloc_kb)); - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.BlinkGCKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, blink_gc_kb)); - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.MallocKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, malloc_mb) * 1024); - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.DiscardableKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, discardable_kb)); - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.V8MainThreadIsolateKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, v8_main_thread_isolate_mb) * 1024); - RecordPurgeAndSuspendMemoryGrowthKB( + RecordBackgroundedRenderPurgeMemoryGrowthKB( "PurgeAndSuspend.Experimental.MemoryGrowth.TotalAllocatedKB", suffix, GET_MEMORY_GROWTH(memory_metrics, purge_and_suspend_memory_metrics_, total_allocated_mb) * 1024); } +void RenderThreadImpl::RecordMetricsForBackgroundedRendererPurge() { + needs_to_record_first_active_paint_ = true; + + RendererMemoryMetrics memory_metrics; + if (!GetRendererMemoryMetrics(&memory_metrics)) + return; + + purge_and_suspend_memory_metrics_ = memory_metrics; + GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RenderThreadImpl:: + OnRecordMetricsForBackgroundedRendererPurgeTimerExpired, + base::Unretained(this), "30min", process_foregrounded_count_), + base::TimeDelta::FromMinutes(30)); + GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RenderThreadImpl:: + OnRecordMetricsForBackgroundedRendererPurgeTimerExpired, + base::Unretained(this), "60min", process_foregrounded_count_), + base::TimeDelta::FromMinutes(60)); + GetWebMainThreadScheduler()->DefaultTaskRunner()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + &RenderThreadImpl:: + OnRecordMetricsForBackgroundedRendererPurgeTimerExpired, + base::Unretained(this), "90min", process_foregrounded_count_), + base::TimeDelta::FromMinutes(90)); +} + void RenderThreadImpl::CompositingModeFallbackToSoftware() { gpu_->LoseChannel(); is_gpu_compositing_disabled_ = true;
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index afa96183..1114b6f 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -480,6 +480,8 @@ bool NeedsToRecordFirstActivePaint(int metric_type) const; + void RecordMetricsForBackgroundedRendererPurge(); + // Sets the current pipeline rendering color space. void SetRenderingColorSpace(const gfx::ColorSpace& color_space); @@ -550,7 +552,6 @@ void PurgePluginListCache(bool reload_pages) override; void SetProcessState(mojom::RenderProcessState process_state) override; void SetSchedulerKeepActive(bool keep_active) override; - void ProcessPurgeAndSuspend() override; void SetIsLockedToSite() override; void EnableV8LowMemoryMode() override; @@ -567,7 +568,7 @@ void RecordMemoryUsageAfterBackgrounded(const char* suffix, int foregrounded_count); - void RecordPurgeAndSuspendMemoryGrowthMetrics( + void OnRecordMetricsForBackgroundedRendererPurgeTimerExpired( const char* suffix, int foregrounded_count_when_purged);
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index c4b8ecb..8455450 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1091,6 +1091,16 @@ //------------------------------------------------------------------------------ +void RendererBlinkPlatformImpl::RecordMetricsForBackgroundedRendererPurge() { + auto* render_thread = RenderThreadImpl::current(); + // RenderThreadImpl is null in some tests. + if (!render_thread) + return; + render_thread->RecordMetricsForBackgroundedRendererPurge(); +} + +//------------------------------------------------------------------------------ + void RendererBlinkPlatformImpl::InitializeWebDatabaseHostIfNeeded() { if (!web_database_host_) { web_database_host_ = blink::mojom::ThreadSafeWebDatabaseHostPtr::Create(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index f3309d2..a1f782b 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -212,6 +212,8 @@ void WillStopWorkerThread() override; void WorkerContextCreated(const v8::Local<v8::Context>& worker) override; + void RecordMetricsForBackgroundedRendererPurge() override; + // Disables the WebSandboxSupport implementation for testing. // Tests that do not set up a full sandbox environment should call // SetSandboxEnabledForTesting(false) _before_ creating any instances
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc index e87511f..8ccc2e9 100644 --- a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc +++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
@@ -106,8 +106,6 @@ // a service worker that is in the process of becoming the controller (i.e., // via claim()) on the browser-side could handle the request and break the // assumptions of the renderer. - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); if (IsControlledByServiceWorker() == blink::mojom::ControllerServiceWorkerMode::kNoController) { request.SetSkipServiceWorker(true);
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc index cb407fb8..b3b3e566 100644 --- a/content/shell/browser/shell_views.cc +++ b/content/shell/browser/shell_views.cc
@@ -266,7 +266,7 @@ return gfx::Size(); } void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override { + const views::ViewHierarchyChangedDetails& details) override { if (details.is_add && details.child == this) { InitShellWindow(); }
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index a4cfdd8d..b133f3ff 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -843,6 +843,8 @@ notification_name.size()) .ToLocalChecked(), }; + // TODO(aboxhall): Can we force this to run in a new task, to avoid + // dirtying layout during post-layout hooks? frame->CallFunctionEvenIfScriptDisabled( v8::Local<v8::Function>::New(isolate, notification_callback_), context->Global(), base::size(argv), argv); @@ -1866,8 +1868,6 @@ return "attribute"; case ax::mojom::DescriptionFrom::kContents: return "contents"; - case ax::mojom::DescriptionFrom::kPlaceholder: - return "placeholder"; case ax::mojom::DescriptionFrom::kRelatedElement: return "relatedElement"; } @@ -1963,7 +1963,6 @@ bool WebAXObjectProxy::HasNonIdentityTransform() { accessibility_object_.UpdateLayoutAndCheckValidity(); - accessibility_object_.UpdateLayoutAndCheckValidity(); blink::WebAXObject container; blink::WebFloatRect bounds; SkMatrix44 matrix;
diff --git a/content/shell/test_runner/web_frame_test_client.cc b/content/shell/test_runner/web_frame_test_client.cc index f10f8d5..1c4ab83 100644 --- a/content/shell/test_runner/web_frame_test_client.cc +++ b/content/shell/test_runner/web_frame_test_client.cc
@@ -438,7 +438,7 @@ if (test_runner()->httpHeadersToClear()) { for (const std::string& header : *test_runner()->httpHeadersToClear()) - request.ClearHTTPHeaderField(blink::WebString::FromUTF8(header)); + request.ClearHttpHeaderField(blink::WebString::FromUTF8(header)); } std::string host = url.host(); @@ -576,7 +576,7 @@ if (test_runner()->httpHeadersToClear()) { for (const std::string& header : *test_runner()->httpHeadersToClear()) { - info->url_request.ClearHTTPHeaderField( + info->url_request.ClearHttpHeaderField( blink::WebString::FromUTF8(header)); } }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 3fc87d0..2e60501c 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1743,7 +1743,6 @@ "../common/input/touch_event_stream_validator_unittest.cc", "../common/inter_process_time_ticks_converter_unittest.cc", "../common/mac/attributed_string_coder_unittest.mm", - "../common/manifest_util_unittest.cc", "../common/mime_sniffing_throttle_unittest.cc", "../common/origin_util_unittest.cc", "../common/page_state_serialization_unittest.cc",
diff --git a/content/test/accessibility_browser_test_utils.cc b/content/test/accessibility_browser_test_utils.cc index d6b8330e..ac6c20d 100644 --- a/content/test/accessibility_browser_test_utils.cc +++ b/content/test/accessibility_browser_test_utils.cc
@@ -97,6 +97,14 @@ loop_runner_ = std::make_unique<base::RunLoop>(); } +void AccessibilityNotificationWaiter::WaitForNotificationWithTimeout( + base::TimeDelta timeout) { + base::OneShotTimer quit_timer; + quit_timer.Start(FROM_HERE, timeout, loop_runner_->QuitWhenIdleClosure()); + + WaitForNotification(); +} + const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const { static base::NoDestructor<ui::AXTree> empty_tree; const ui::AXTree* tree = frame_host_->GetAXTreeForTesting(); @@ -117,6 +125,8 @@ if (IsAboutBlank()) return; + LOG(INFO) << "OnAccessibilityEvent " << event_type; + if (event_to_wait_for_ == ax::mojom::Event::kNone || event_to_wait_for_ == event_type) { event_target_id_ = event_target_id;
diff --git a/content/test/accessibility_browser_test_utils.h b/content/test/accessibility_browser_test_utils.h index aba9fcd..f959c41 100644 --- a/content/test/accessibility_browser_test_utils.h +++ b/content/test/accessibility_browser_test_utils.h
@@ -52,6 +52,9 @@ // "about:blank". void WaitForNotification(); + // Blocks until the notification is received, or the given timeout passes. + void WaitForNotificationWithTimeout(base::TimeDelta timeout); + // After WaitForNotification has returned, this will retrieve // the tree of accessibility nodes received from the renderer process. const ui::AXTree& GetAXTree() const;
diff --git a/content/test/data/accessibility/aria/aria-hidden-iframe-body.html b/content/test/data/accessibility/aria/aria-hidden-iframe-body.html index 583b0e4..c8537b87 100644 --- a/content/test/data/accessibility/aria/aria-hidden-iframe-body.html +++ b/content/test/data/accessibility/aria/aria-hidden-iframe-body.html
@@ -5,7 +5,6 @@ @BLINK-ALLOW:richlyEditable @WAIT-FOR:2 --> -<iframe srcdoc="<body contenteditable aria-hidden='true'>1</body>"> -</iframe> -<iframe srcdoc="<body aria-hidden='true'>2</body>"> +<iframe src="frames/aria-hidden-1.html"></iframe> +<iframe src="frames/aria-hidden-2.html"></iframe> </iframe>
diff --git a/content/test/data/accessibility/aria/frames/aria-hidden-1.html b/content/test/data/accessibility/aria/frames/aria-hidden-1.html new file mode 100644 index 0000000..5fcad04 --- /dev/null +++ b/content/test/data/accessibility/aria/frames/aria-hidden-1.html
@@ -0,0 +1 @@ +<body contenteditable aria-hidden='true'>1</body>
diff --git a/content/test/data/accessibility/aria/frames/aria-hidden-2.html b/content/test/data/accessibility/aria/frames/aria-hidden-2.html new file mode 100644 index 0000000..8feb050 --- /dev/null +++ b/content/test/data/accessibility/aria/frames/aria-hidden-2.html
@@ -0,0 +1 @@ +<body aria-hidden='true'>2</body>
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt b/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt index 7c485e7..73cb5b6a 100644 --- a/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt +++ b/content/test/data/accessibility/event/remove-hidden-attribute-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_LIST SetSize=3 EVENT_OBJECT_SHOW on <div#item3> role=ROLE_SYSTEM_LISTITEM name="Item 3" PosInSet=3 SetSize=3 -IA2_EVENT_TEXT_INSERTED on <div> role=ROLE_SYSTEM_LIST SetSize=2 new_text={'<obj>' start=2 end=3} +IA2_EVENT_TEXT_INSERTED on <div> role=ROLE_SYSTEM_LIST SetSize=3 new_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt index 1200268a..3dadf9f 100644 --- a/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt +++ b/content/test/data/accessibility/event/remove-hidden-attribute-subtree-expected-win.txt
@@ -1,3 +1,3 @@ EVENT_OBJECT_REORDER on <ul> role=ROLE_SYSTEM_LIST SetSize=3 EVENT_OBJECT_SHOW on <li#item3> role=ROLE_SYSTEM_LISTITEM PosInSet=3 SetSize=3 -IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=2 new_text={'<obj>' start=2 end=3} +IA2_EVENT_TEXT_INSERTED on <ul> role=ROLE_SYSTEM_LIST SetSize=3 new_text={'<obj>' start=2 end=3}
diff --git a/content/test/data/accessibility/html/frame/box2.html b/content/test/data/accessibility/html/frame/box2.html new file mode 100644 index 0000000..9fa83bf --- /dev/null +++ b/content/test/data/accessibility/html/frame/box2.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> +<body style="margin: 10px; padding: 0px; border: 0px;"> +<div role="img" style="width: 100px; height: 50px; background-color: #fef;"></div> +</body> +</html>
diff --git a/content/test/data/accessibility/html/iframe-transform.html b/content/test/data/accessibility/html/iframe-transform.html index d29a9c59..d96a3c0 100644 --- a/content/test/data/accessibility/html/iframe-transform.html +++ b/content/test/data/accessibility/html/iframe-transform.html
@@ -20,6 +20,6 @@ <html> <body style="padding: 0; margin: 0;"> <iframe width=220 height=220 src="frame/box.html" style="border: 0; position: absolute; top: 0px; left: 0px;"></iframe> - <iframe width=220 height=220 src="frame/box.html" style="border: 0; position: absolute; top: 250px; left: 0px; transform: scale(1.5); transform-origin: left top;"></iframe> + <iframe width=220 height=220 src="frame/box2.html" style="border: 0; position: absolute; top: 250px; left: 0px; transform: scale(1.5); transform-origin: left top;"></iframe> </body> </html>
diff --git a/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt b/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt new file mode 100644 index 0000000..526d9f7 --- /dev/null +++ b/content/test/data/accessibility/html/input-text-name-calc-expected-uia-win.txt
@@ -0,0 +1,12 @@ +region +++document IsKeyboardFocusable=true +++++textbox Name='Title0' IsKeyboardFocusable=true HelpText='Title0' IsDataValidForForm=true +++++textbox Name='Label1' IsKeyboardFocusable=true HelpText='Title1' IsDataValidForForm=true +++++textbox Name='AriaLabel2' IsKeyboardFocusable=true HelpText='Title2' IsDataValidForForm=true +++++textbox Name='LabelledBy3' IsKeyboardFocusable=true HelpText='Title3' IsDataValidForForm=true +++++textbox Name='Placeholder4' IsKeyboardFocusable=true HelpText='Placeholder4' IsDataValidForForm=true +++++textbox Name='ARIA Placeholder4a' IsKeyboardFocusable=true HelpText='ARIA Placeholder4a' IsDataValidForForm=true +++++textbox Name='Placeholder4b' IsKeyboardFocusable=true HelpText='Placeholder4b' IsDataValidForForm=true +++++textbox Name='Placeholder5' IsKeyboardFocusable=true HelpText='Placeholder5' IsDataValidForForm=true +++++textbox Name='LabelledBy6' IsKeyboardFocusable=true HelpText='Title6' IsDataValidForForm=true +++++textbox Name='AriaLabel7' IsKeyboardFocusable=true HelpText='Placeholder7' IsDataValidForForm=true
diff --git a/content/test/data/accessibility/html/input-text-name-calc.html b/content/test/data/accessibility/html/input-text-name-calc.html index 8a561bc..8aa6d37 100644 --- a/content/test/data/accessibility/html/input-text-name-calc.html +++ b/content/test/data/accessibility/html/input-text-name-calc.html
@@ -1,4 +1,5 @@ <!-- +@UIA-WIN-ALLOW:HelpText* @WIN-ALLOW:description* @WIN-ALLOW:explicit-name* @AURALINUX-ALLOW:description*
diff --git a/content/test/data/accessibility/html/svg-expected-uia-win.txt b/content/test/data/accessibility/html/svg-expected-uia-win.txt new file mode 100644 index 0000000..bbc9737 --- /dev/null +++ b/content/test/data/accessibility/html/svg-expected-uia-win.txt
@@ -0,0 +1,6 @@ +region +++document IsKeyboardFocusable=true +++++group +++++++img Name='svg' HelpText='SVG Title Tag' +++++++++group +++++++++++description Name='Test'
diff --git a/content/test/data/accessibility/html/svg.html b/content/test/data/accessibility/html/svg.html index 88c10031..9b5328d 100644 --- a/content/test/data/accessibility/html/svg.html +++ b/content/test/data/accessibility/html/svg.html
@@ -1,4 +1,5 @@ <!-- +@UIA-WIN-ALLOW:HelpText* @MAC-ALLOW:AXDescription='svg' --> <!DOCTYPE html> @@ -6,12 +7,13 @@ <body> <svg aria-label="svg"> + <title>SVG Title Tag</title> <circle r="200" cx="200" cy="200" stroke="red" stroke-width="1" fill="yellow" /> <ellipse cx="120" cy="180" rx="18" ry="33" fill="black"/> <ellipse cx="280" cy="120" rx="18" ry="33" fill="black"/> <ellipse cx="200" cy="220" rx="8" ry="15" fill="black"/> <path stroke-width="10" stroke="black" fill="none" stroke-linecap="round" d="M120,280 Q200,330 290,280"/> - <text x="150" y="130" fill="red">Test</text> + <text x="150" y="130" fill="red">Test</text> </svg> </body>
diff --git a/content/test/data/media/getusermedia-depth-capture.html b/content/test/data/media/getusermedia-depth-capture.html index 38590ff..f6c0a53b 100644 --- a/content/test/data/media/getusermedia-depth-capture.html +++ b/content/test/data/media/getusermedia-depth-capture.html
@@ -32,23 +32,6 @@ }, failedCallback); } - function getDepthStreamAndCameraCalibration() { - console.log('Calling getDepthStreamAndCameraCalibration'); - getFake16bitStream().then(function(stream) { - var depth_track = stream.getVideoTracks()[0]; - if (!depth_track) - return failTest("No depth_track"); - var settings = depth_track.getSettings(); - if (settings && settings.depthNear == 0 && settings.depthFar == 65.535 && - settings.focalLengthX == 135.0 && settings.focalLengthY == 135.6) { - reportTestSuccess(); - } else { - failTest("Unexpected depth_track settings:" + JSON.stringify(settings)); - } - }, - failedCallback); - } - function getBothStreamsAndCheckForFeaturesPresence() { console.log('Calling getBothStreamsAndCheckForFeaturesPresence'); getConstraintsForDevice("fake_device_0") @@ -92,19 +75,6 @@ } } - var depth_fields = ["depthNear", "depthFar", "focalLengthX", - "focalLengthY"]; - for (var field in depth_fields) { - var depth_field = depth_fields[field]; - if (video_track.getSettings()[depth_field] !== undefined) { - return failTest(depth_field + - " present in video track getSettings()."); - } - if (depth_track.getSettings()[depth_field] === undefined) { - return failTest(depth_field + - " missing from depth track getSettings()."); - } - } reportTestSuccess(); }, failedCallback);
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc index 2dd96b84..f588d1f8 100644 --- a/device/fido/fido_device_authenticator.cc +++ b/device/fido/fido_device_authenticator.cc
@@ -18,6 +18,7 @@ #include "device/fido/get_assertion_task.h" #include "device/fido/make_credential_task.h" #include "device/fido/pin.h" +#include "device/fido/u2f_command_constructor.h" namespace device { @@ -72,59 +73,42 @@ } void FidoDeviceAuthenticator::GetTouch(base::OnceCallback<void()> callback) { - // We want to flash and wait for a touch. With a U2F device, that can be - // achieved by requesting a signature for a dummy credential ID, but CTAP2 - // devices will return an error immediately. Newer versions of the CTAP2 spec + // We want to flash and wait for a touch. Newer versions of the CTAP2 spec // include a provision for blocking for a touch when an empty pinAuth is - // specified, but devices may exist that predate this part of the spec and - // also the spec says that devices need only do that if they implement PIN - // support. Therefore, in order to portably wait for a touch a dummy - // credential is created. This does assume that the device supports ECDSA - // P-256, however. - if (device_->supported_protocol() == ProtocolVersion::kU2f) { - CtapGetAssertionRequest req(".dummy", ""); - req.SetAllowList( - {PublicKeyCredentialDescriptor(CredentialType::kPublicKey, {0})}); - GetAssertion( - std::move(req), - base::BindOnce( - [](base::OnceCallback<void()> callback, CtapDeviceResponseCode, - base::Optional<AuthenticatorGetAssertionResponse>) { - std::move(callback).Run(); - }, - std::move(callback))); - } else { - PublicKeyCredentialUserEntity user({1} /* user ID */); - // The user name is incorrectly marked as optional in the CTAP2 spec. - user.SetUserName("dummy"); - CtapMakeCredentialRequest req( - "" /* client_data_json */, PublicKeyCredentialRpEntity(".dummy"), - std::move(user), - PublicKeyCredentialParams( - {{CredentialType::kPublicKey, - base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256)}})); - req.SetExcludeList({}); - // Set an empty pinAuth in case the device is a newer CTAP2 and understands - // this to mean to block for touch. - req.SetPinAuth({}); + // specified, but devices exist that predate this part of the spec and also + // the spec says that devices need only do that if they implement PIN support. + // Therefore, in order to portably wait for a touch, a dummy credential is + // created. This does assume that the device supports ECDSA P-256, however. + PublicKeyCredentialUserEntity user({1} /* user ID */); + // The user name is incorrectly marked as optional in the CTAP2 spec. + user.SetUserName("dummy"); + CtapMakeCredentialRequest req( + "" /* client_data_json */, PublicKeyCredentialRpEntity(".dummy"), + std::move(user), + PublicKeyCredentialParams( + {{CredentialType::kPublicKey, + base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256)}})); + req.SetExcludeList({}); + // Set an empty pinAuth in case the device is a newer CTAP2 and understands + // this to mean to block for touch. + req.SetPinAuth({}); + DCHECK(IsConvertibleToU2fRegisterCommand(req)); - MakeCredential( - std::move(req), - base::BindOnce( - [](base::OnceCallback<void()> callback, - CtapDeviceResponseCode status, - base::Optional<AuthenticatorMakeCredentialResponse>) { - // If the device didn't understand/process the request it may - // fail immediately. Rather than count that as a touch, ignore - // those cases completely. - if (status == CtapDeviceResponseCode::kSuccess || - status == CtapDeviceResponseCode::kCtap2ErrPinNotSet || - status == CtapDeviceResponseCode::kCtap2ErrPinInvalid) { - std::move(callback).Run(); - } - }, - std::move(callback))); - } + MakeCredential( + std::move(req), + base::BindOnce( + [](base::OnceCallback<void()> callback, CtapDeviceResponseCode status, + base::Optional<AuthenticatorMakeCredentialResponse>) { + // If the device didn't understand/process the request it may + // fail immediately. Rather than count that as a touch, ignore + // those cases completely. + if (status == CtapDeviceResponseCode::kSuccess || + status == CtapDeviceResponseCode::kCtap2ErrPinNotSet || + status == CtapDeviceResponseCode::kCtap2ErrPinInvalid) { + std::move(callback).Run(); + } + }, + std::move(callback))); } void FidoDeviceAuthenticator::GetRetries(GetRetriesCallback callback) {
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 99575ba..4533515e 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -207,34 +207,33 @@ return; } - CtapGetAssertionRequest request(request_); - if (base::FeatureList::IsEnabled(device::kWebAuthPINSupport) && authenticator->WillNeedPINToGetAssertion(request_)) { - request.SetUserVerification(UserVerificationRequirement::kRequired); - // Set empty pinAuth to trigger just a touch. - request.SetPinAuth({}); - authenticator->GetAssertion( - std::move(request), - base::BindOnce(&GetAssertionRequestHandler::HandleResponse, + // A PIN will be needed. Just request a touch to let the user select this + // authenticator if they wish. + authenticator->GetTouch( + base::BindOnce(&GetAssertionRequestHandler::HandleTouch, weak_factory_.GetWeakPtr(), authenticator)); - } else { - if (authenticator->Options()) { - if (authenticator->Options()->user_verification_availability == - AuthenticatorSupportedOptions::UserVerificationAvailability:: - kSupportedAndConfigured && - request_.user_verification() != - UserVerificationRequirement::kDiscouraged) { - request.SetUserVerification(UserVerificationRequirement::kRequired); - } else { - request.SetUserVerification(UserVerificationRequirement::kDiscouraged); - } - } - authenticator->GetAssertion( - std::move(request), - base::BindOnce(&GetAssertionRequestHandler::HandleResponse, - weak_factory_.GetWeakPtr(), authenticator)); + return; } + + CtapGetAssertionRequest request(request_); + if (authenticator->Options()) { + if (authenticator->Options()->user_verification_availability == + AuthenticatorSupportedOptions::UserVerificationAvailability:: + kSupportedAndConfigured && + request_.user_verification() != + UserVerificationRequirement::kDiscouraged) { + request.SetUserVerification(UserVerificationRequirement::kRequired); + } else { + request.SetUserVerification(UserVerificationRequirement::kDiscouraged); + } + } + + authenticator->GetAssertion( + std::move(request), + base::BindOnce(&GetAssertionRequestHandler::HandleResponse, + weak_factory_.GetWeakPtr(), authenticator)); } void GetAssertionRequestHandler::AuthenticatorRemoved( @@ -267,24 +266,10 @@ return; } - if (state_ == State::kWaitingForTouch && - base::FeatureList::IsEnabled(device::kWebAuthPINSupport) && - authenticator->WillNeedPINToGetAssertion(request_)) { - if (response_code != CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid && - response_code != CtapDeviceResponseCode::kCtap2ErrPinInvalid) { - VLOG(1) << "Expected invalid pinAuth error but got " - << static_cast<int>(response_code); - return; - } - DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); - state_ = State::kGettingRetries; - authenticator_ = authenticator; - authenticator_->GetRetries( - base::BindOnce(&GetAssertionRequestHandler::OnRetriesResponse, - weak_factory_.GetWeakPtr())); - return; - } + // Requests that require a PIN should follow the |GetTouch| path initially. + DCHECK(state_ == State::kWaitingForSecondTouch || + !base::FeatureList::IsEnabled(device::kWebAuthPINSupport) || + !authenticator->WillNeedPINToGetAssertion(request_)); state_ = State::kFinished; if (response_code != CtapDeviceResponseCode::kSuccess) { @@ -307,6 +292,23 @@ OnAuthenticatorResponse(authenticator, response_code, std::move(responses)); } +void GetAssertionRequestHandler::HandleTouch(FidoAuthenticator* authenticator) { + if (state_ != State::kWaitingForTouch) { + return; + } + + DCHECK(base::FeatureList::IsEnabled(device::kWebAuthPINSupport) && + authenticator->WillNeedPINToGetAssertion(request_)); + + DCHECK(observer()); + CancelActiveAuthenticators(authenticator->GetId()); + state_ = State::kGettingRetries; + authenticator_ = authenticator; + authenticator_->GetRetries( + base::BindOnce(&GetAssertionRequestHandler::OnRetriesResponse, + weak_factory_.GetWeakPtr())); +} + void GetAssertionRequestHandler::OnRetriesResponse( CtapDeviceResponseCode status, base::Optional<pin::RetriesResponse> response) {
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h index 6616f70..49d49b15 100644 --- a/device/fido/get_assertion_request_handler.h +++ b/device/fido/get_assertion_request_handler.h
@@ -58,6 +58,7 @@ FidoAuthenticator* authenticator, CtapDeviceResponseCode response_code, base::Optional<AuthenticatorGetAssertionResponse> response); + void HandleTouch(FidoAuthenticator* authenticator); void OnRetriesResponse(CtapDeviceResponseCode status, base::Optional<pin::RetriesResponse> response); void OnHavePIN(std::string pin);
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc index 9070e09..fdf1726d 100644 --- a/device/fido/make_credential_request_handler.cc +++ b/device/fido/make_credential_request_handler.cc
@@ -142,34 +142,31 @@ return; } - CtapMakeCredentialRequest request(request_parameter_); - if (base::FeatureList::IsEnabled(device::kWebAuthPINSupport) && authenticator->WillNeedPINToMakeCredential(request_parameter_) != ClientPinAvailability::kNotSupported) { - request.SetUserVerification(UserVerificationRequirement::kRequired); - // Set an empty pinAuth parameter to wait for a touch and then report an - // error. - request.SetPinAuth({}); - authenticator->MakeCredential( - std::move(request), - base::BindOnce(&MakeCredentialRequestHandler::HandleResponse, + // A PIN will be needed. Just request a touch to let the user select this + // authenticator if they wish. + authenticator->GetTouch( + base::BindOnce(&MakeCredentialRequestHandler::HandleTouch, weak_factory_.GetWeakPtr(), authenticator)); - } else { - if (authenticator->Options()) { - if (authenticator->Options()->user_verification_availability == - AuthenticatorSupportedOptions::UserVerificationAvailability:: - kSupportedAndConfigured) { - request.SetUserVerification(UserVerificationRequirement::kRequired); - } else { - request.SetUserVerification(UserVerificationRequirement::kDiscouraged); - } - } - authenticator->MakeCredential( - std::move(request), - base::BindOnce(&MakeCredentialRequestHandler::HandleResponse, - weak_factory_.GetWeakPtr(), authenticator)); + return; } + + CtapMakeCredentialRequest request(request_parameter_); + if (authenticator->Options()) { + if (authenticator->Options()->user_verification_availability == + AuthenticatorSupportedOptions::UserVerificationAvailability:: + kSupportedAndConfigured) { + request.SetUserVerification(UserVerificationRequirement::kRequired); + } else { + request.SetUserVerification(UserVerificationRequirement::kDiscouraged); + } + } + authenticator->MakeCredential( + std::move(request), + base::BindOnce(&MakeCredentialRequestHandler::HandleResponse, + weak_factory_.GetWeakPtr(), authenticator)); } void MakeCredentialRequestHandler::AuthenticatorRemoved( @@ -202,48 +199,11 @@ return; } - if (base::FeatureList::IsEnabled(device::kWebAuthPINSupport) && - state_ == State::kWaitingForTouch) { - switch (authenticator->WillNeedPINToMakeCredential(request_parameter_)) { - case ClientPinAvailability::kSupportedAndPinSet: - // Will need to get PIN to handle this request. - if (response_code != CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid && - response_code != CtapDeviceResponseCode::kCtap2ErrPinInvalid) { - VLOG(1) << "Expected invalid pinAuth error but got " - << static_cast<int>(response_code); - return; - } - DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); - state_ = State::kGettingRetries; - authenticator_ = authenticator; - authenticator_->GetRetries( - base::BindOnce(&MakeCredentialRequestHandler::OnRetriesResponse, - weak_factory_.GetWeakPtr())); - return; - - case ClientPinAvailability::kSupportedButPinNotSet: - // Will need to set a PIN to handle this request. - if (response_code != CtapDeviceResponseCode::kCtap2ErrPinNotSet) { - VLOG(1) << "Expected PIN-not-set error but got " - << static_cast<int>(response_code); - return; - } - DCHECK(observer()); - CancelActiveAuthenticators(authenticator->GetId()); - state_ = State::kWaitingForNewPIN; - authenticator_ = authenticator; - observer()->CollectPIN( - base::nullopt, - base::BindOnce(&MakeCredentialRequestHandler::OnHavePIN, - weak_factory_.GetWeakPtr())); - return; - - case ClientPinAvailability::kNotSupported: - // No PIN needed for this request. - break; - } - } + // Requests that require a PIN should follow the |GetTouch| path initially. + DCHECK(state_ == State::kWaitingForSecondTouch || + !base::FeatureList::IsEnabled(device::kWebAuthPINSupport) || + authenticator->WillNeedPINToMakeCredential(request_parameter_) == + ClientPinAvailability::kNotSupported); state_ = State::kFinished; if (response_code != CtapDeviceResponseCode::kSuccess) { @@ -263,6 +223,45 @@ OnAuthenticatorResponse(authenticator, response_code, std::move(response)); } +void MakeCredentialRequestHandler::HandleTouch( + FidoAuthenticator* authenticator) { + if (state_ != State::kWaitingForTouch) { + return; + } + + DCHECK(base::FeatureList::IsEnabled(device::kWebAuthPINSupport)); + + switch (authenticator->WillNeedPINToMakeCredential(request_parameter_)) { + case ClientPinAvailability::kSupportedAndPinSet: + // Will need to get PIN to handle this request. + DCHECK(observer()); + CancelActiveAuthenticators(authenticator->GetId()); + state_ = State::kGettingRetries; + authenticator_ = authenticator; + authenticator_->GetRetries( + base::BindOnce(&MakeCredentialRequestHandler::OnRetriesResponse, + weak_factory_.GetWeakPtr())); + return; + + case ClientPinAvailability::kSupportedButPinNotSet: + // Will need to set a PIN to handle this request. + DCHECK(observer()); + CancelActiveAuthenticators(authenticator->GetId()); + state_ = State::kWaitingForNewPIN; + authenticator_ = authenticator; + observer()->CollectPIN( + base::nullopt, + base::BindOnce(&MakeCredentialRequestHandler::OnHavePIN, + weak_factory_.GetWeakPtr())); + return; + + case ClientPinAvailability::kNotSupported: + // No PIN needed for this request. + NOTREACHED(); + break; + } +} + void MakeCredentialRequestHandler::OnHavePIN(std::string pin) { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); DCHECK(state_ == State::kWaitingForPIN || state_ == State::kWaitingForNewPIN);
diff --git a/device/fido/make_credential_request_handler.h b/device/fido/make_credential_request_handler.h index 241a755e..eb52846 100644 --- a/device/fido/make_credential_request_handler.h +++ b/device/fido/make_credential_request_handler.h
@@ -68,6 +68,7 @@ FidoAuthenticator* authenticator, CtapDeviceResponseCode response_code, base::Optional<AuthenticatorMakeCredentialResponse> response); + void HandleTouch(FidoAuthenticator* authenticator); void OnHavePIN(std::string pin); void OnRetriesResponse(CtapDeviceResponseCode status, base::Optional<pin::RetriesResponse> response);
diff --git a/device/fido/u2f_command_constructor.cc b/device/fido/u2f_command_constructor.cc index 90cd1cc..d8ef619 100644 --- a/device/fido/u2f_command_constructor.cc +++ b/device/fido/u2f_command_constructor.cc
@@ -41,6 +41,12 @@ if (!IsConvertibleToU2fRegisterCommand(request)) return base::nullopt; + if (request.pin_auth() && request.pin_auth()->size() == 0) { + // An empty pin_auth in CTAP2 indicates that the device should just wait + // for a touch. + return ConstructBogusU2fRegistrationCommand(); + } + const bool is_invidual_attestation = request.attestation_preference() == AttestationConveyancePreference::ENTERPRISE;
diff --git a/device/gamepad/gamepad_id_list.cc b/device/gamepad/gamepad_id_list.cc index 3aaa8e1..6b8c48c 100644 --- a/device/gamepad/gamepad_id_list.cc +++ b/device/gamepad/gamepad_id_list.cc
@@ -446,6 +446,7 @@ {0x1781, 0x057e, kXInputTypeNone}, // Google Inc. {0x18d1, 0x2c40, kXInputTypeNone}, + {0x18d1, 0x502e, kXInputTypeNone}, // Lab126, Inc. {0x1949, 0x0402, kXInputTypeNone}, // Gampaq Co.Ltd
diff --git a/device/gamepad/gamepad_id_list.h b/device/gamepad/gamepad_id_list.h index 2ea093a9..2cd2b14 100644 --- a/device/gamepad/gamepad_id_list.h +++ b/device/gamepad/gamepad_id_list.h
@@ -36,6 +36,7 @@ kDragonRiseProduct0006 = 0x00790006, kDragonRiseProduct0011 = 0x00790011, kGoogleProduct2c40 = 0x18d12c40, + kGoogleProduct502e = 0x18d1502e, kGreenAsiaProduct0003 = 0x0e8f0003, kLakeviewResearchProduct0005 = 0x09250005, kLakeviewResearchProduct8866 = 0x09258866,
diff --git a/device/gamepad/gamepad_standard_mappings_linux.cc b/device/gamepad/gamepad_standard_mappings_linux.cc index b36354f..9f3be38 100644 --- a/device/gamepad/gamepad_standard_mappings_linux.cc +++ b/device/gamepad/gamepad_standard_mappings_linux.cc
@@ -677,6 +677,15 @@ mapped->axes_length = AXIS_INDEX_COUNT; } +void MapperStadiaController(const Gamepad& input, Gamepad* mapped) { + const size_t kStadiaControllerExtraButtons = 2; + *mapped = input; + mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]); + mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); + mapped->buttons_length = BUTTON_INDEX_COUNT + kStadiaControllerExtraButtons; + mapped->axes_length = AXIS_INDEX_COUNT; +} + constexpr struct MappingData { GamepadId gamepad_id; GamepadStandardMappingFunction function; @@ -761,6 +770,8 @@ {GamepadId::kRazer1532Product0900, MapperRazerServal}, // ADT-1 Controller {GamepadId::kGoogleProduct2c40, MapperADT1}, + // Stadia Controller + {GamepadId::kGoogleProduct502e, MapperStadiaController}, // Moga Pro Controller (HID mode) {GamepadId::kVendor20d6Product6271, MapperMoga}, // Moga 2 HID
diff --git a/device/gamepad/gamepad_standard_mappings_mac.mm b/device/gamepad/gamepad_standard_mappings_mac.mm index 9db0050..8adac28 100644 --- a/device/gamepad/gamepad_standard_mappings_mac.mm +++ b/device/gamepad/gamepad_standard_mappings_mac.mm
@@ -519,6 +519,15 @@ mapped->axes_length = AXIS_INDEX_COUNT; } +void MapperStadiaController(const Gamepad& input, Gamepad* mapped) { + const size_t kStadiaControllerExtraButtons = 2; + *mapped = input; + mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]); + mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); + mapped->buttons_length = BUTTON_INDEX_COUNT + kStadiaControllerExtraButtons; + mapped->axes_length = AXIS_INDEX_COUNT; +} + constexpr struct MappingData { GamepadId gamepad_id; GamepadStandardMappingFunction function; @@ -581,6 +590,8 @@ {GamepadId::kRazer1532Product0900, MapperRazerServal}, // ADT-1 Controller {GamepadId::kGoogleProduct2c40, MapperADT1}, + // Stadia Controller + {GamepadId::kGoogleProduct502e, MapperStadiaController}, // Moga Pro Controller (HID mode) {GamepadId::kVendor20d6Product6271, MapperMogaPro}, // Macally iShockX, analog mode
diff --git a/device/gamepad/gamepad_standard_mappings_win.cc b/device/gamepad/gamepad_standard_mappings_win.cc index 0363514..af5a22c6 100644 --- a/device/gamepad/gamepad_standard_mappings_win.cc +++ b/device/gamepad/gamepad_standard_mappings_win.cc
@@ -387,6 +387,15 @@ mapped->axes_length = AXIS_INDEX_COUNT; } +void MapperStadiaController(const Gamepad& input, Gamepad* mapped) { + const size_t kStadiaControllerExtraButtons = 2; + *mapped = input; + mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]); + mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]); + mapped->buttons_length = BUTTON_INDEX_COUNT + kStadiaControllerExtraButtons; + mapped->axes_length = AXIS_INDEX_COUNT; +} + constexpr struct MappingData { GamepadId gamepad_id; GamepadStandardMappingFunction function; @@ -427,6 +436,8 @@ {GamepadId::kRazer1532Product0900, MapperRazerServal}, // ADT-1 Controller {GamepadId::kGoogleProduct2c40, MapperADT1}, + // Stadia Controller + {GamepadId::kGoogleProduct502e, MapperStadiaController}, // Moga Pro Controller (HID mode) {GamepadId::kVendor20d6Product6271, MapperMogaPro}, // OnLive Controller (Bluetooth)
diff --git a/device/gamepad/hid_haptic_gamepad_base.cc b/device/gamepad/hid_haptic_gamepad_base.cc index 8cea437..07c9d2a 100644 --- a/device/gamepad/hid_haptic_gamepad_base.cc +++ b/device/gamepad/hid_haptic_gamepad_base.cc
@@ -42,6 +42,8 @@ {0x0b43, 0x0005, 0x00, 4, 3, 3, 1 * kBitsPerByte, 0, 1}, // Analog game controller {0x6666, 0x9401, 0x05, 5, 1, 3, 2 * kBitsPerByte, 0, 0xffff}, + // Stadia controller + {0x18d1, 0x502e, 0x05, 5, 1, 3, 2 * kBitsPerByte, 0, 0xffff}, }; size_t kHapticReportDataLength = base::size(kHapticReportData);
diff --git a/docs/clang_static_analyzer.md b/docs/clang_static_analyzer.md index 8935ffa..093012ad 100644 --- a/docs/clang_static_analyzer.md +++ b/docs/clang_static_analyzer.md
@@ -20,7 +20,7 @@ ## Save some time, look at the buildbot logs! -We run static analysis builds continously, all day long on FYI buildbots. +We run static analysis builds continuously, all day long on FYI buildbots. You can save yourself some time by first inspecting their build logs for errors before running your own analysis builds. You will probably need to Ctrl-F the logs to find any issues for the specific files you're interested in.
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md index d3a6a7b..9af0c5ea 100644 --- a/docs/infra/cq_builders.md +++ b/docs/infra/cq_builders.md
@@ -267,7 +267,7 @@ * [win7-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/win7-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win7-rel)) - * Experimental percentage: 10 + * Experimental percentage: 100 * [win7_chromium_rel_loc_exp](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7_chromium_rel_loc_exp) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/win7_chromium_rel_loc_exp)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+win7_chromium_rel_loc_exp))
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.cc b/extensions/browser/api/feedback_private/feedback_private_api.cc index 4e2f8b8..b0115f6 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api.cc
@@ -11,6 +11,8 @@ #include "base/bind.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/metrics/histogram_base.h" +#include "base/metrics/statistics_recorder.h" #include "base/metrics/user_metrics.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -331,13 +333,15 @@ delegate->FetchAndMergeIwlwifiDumpLogsIfPresent( std::move(sys_logs), browser_context(), - base::Bind(&FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched, this, - feedback_data, - feedback_info.send_bluetooth_logs && - *feedback_info.send_bluetooth_logs)); + base::BindOnce( + &FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched, this, + feedback_data, + feedback_info.send_histograms && *feedback_info.send_histograms, + feedback_info.send_bluetooth_logs && + *feedback_info.send_bluetooth_logs)); #else - OnAllLogsFetched(feedback_data, false /* send_bluetooth_logs */, - std::move(sys_logs)); + OnAllLogsFetched(feedback_data, false /* send_histograms */, + false /* send_bluetooth_logs */, std::move(sys_logs)); #endif // defined(OS_CHROMEOS) return RespondLater(); @@ -345,12 +349,21 @@ void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched( scoped_refptr<FeedbackData> feedback_data, + bool send_histograms, bool send_bluetooth_logs, std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) { VLOG(1) << "All logs have been fetched. Proceeding with sending the report."; feedback_data->SetAndCompressSystemInfo(std::move(sys_logs)); + if (send_histograms) { + auto histograms = std::make_unique<std::string>(); + *histograms = + base::StatisticsRecorder::ToJSON(base::JSON_VERBOSITY_LEVEL_FULL); + if (!histograms->empty()) + feedback_data->SetAndCompressHistograms(std::move(histograms)); + } + if (send_bluetooth_logs) { std::unique_ptr<std::string> bluetooth_logs = std::make_unique<std::string>();
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.h b/extensions/browser/api/feedback_private/feedback_private_api.h index 5e5b4a8..9ce9605 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api.h +++ b/extensions/browser/api/feedback_private/feedback_private_api.h
@@ -142,6 +142,7 @@ private: void OnAllLogsFetched( scoped_refptr<feedback::FeedbackData> feedback_data, + bool send_histograms, bool send_bluetooth_logs, std::unique_ptr<FeedbackCommon::SystemLogsMap> sys_logs); void OnCompleted(api::feedback_private::LandingPageType type, bool success);
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc index 04ec5ca4..0652fc8 100644 --- a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc +++ b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
@@ -95,11 +95,11 @@ // media_perception::mojom::MediaPerceptionControllerClient: void ConnectToVideoCaptureService( - video_capture::mojom::DeviceFactoryRequest request) override { + video_capture::mojom::VideoSourceProviderRequest request) override { DCHECK(delegate_) << "Delegate not set."; delegate_->BindDeviceFactoryProviderToVideoCaptureService( &device_factory_provider_); - device_factory_provider_->ConnectToDeviceFactory(std::move(request)); + device_factory_provider_->ConnectToVideoSourceProvider(std::move(request)); } private:
diff --git a/extensions/browser/api/networking_private/OWNERS b/extensions/browser/api/networking_private/OWNERS index aa215c7..3bec69af 100644 --- a/extensions/browser/api/networking_private/OWNERS +++ b/extensions/browser/api/networking_private/OWNERS
@@ -1 +1,2 @@ stevenjb@chromium.org +tbarzic@chromium.org \ No newline at end of file
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc index e0cfb48..596f096 100644 --- a/extensions/browser/url_loader_factory_manager.cc +++ b/extensions/browser/url_loader_factory_manager.cc
@@ -71,6 +71,7 @@ "0EAEA2FDEE025D95B3ABB37014EFF5A98AC4BEAE", "0FCD1282065485458E630683F098F591B24C406D", "109A37B889E7C8AEA7B0103559C3EB6AF73B7832", + "11AF49711EE340C366CC820C98E3CA2AD7D7DE07", "16A81AEA09A67B03F7AEA5B957D24A4095E764BE", "177508B365CBF1610CC2B53707749D79272F2F0B", "1AB9CC404876117F49135E67BAD813F935AAE9BA", @@ -110,12 +111,15 @@ "6357533CAFFB94A9EA5268ED110079E15561E469", "65C20C06ED10E6F39EED527AC736D87B0390DE70", "67528F9B47BE454EC46809C33D24F2C199BE408D", + "6A113D4E2F96997D9BA4B391B90ED51058B37EFF", "6AE81EF3B13B15080A2DDB23A205A24C65CCC10B", "6BA5F75FFF75B69507BC4B09B7094926EF93DBD2", + "6D3A671DABC1F87910A1AA67EE85C02095D35624", "6E49449D56D031B87835CC767734AF5A064E1A13", "71351EAA5C16350EC5A86C23D7A288317309E53D", "71CB78C3334D5122E7F23C8525AD24100CDE7D4A", "71EE66C0F71CD89BEE340F8568A44101D4C3A9A7", + "7499EF1AEC6F4D70E5E7DA2568A02E8ABC1A6447", "7527942941BFF13D66B46E7A2A56FDBA873FB9E6", "77D83E0A4157A0E77B51AD60BAB69A346CD4FEA3", "7879DB88205D880B64D55E51B9726E1D12F7261F", @@ -150,6 +154,7 @@ "B3CF6C01796E8D03378FAA77AF507E27BB847E9D", "B4782AE831D849EFCC2AF4BE2012816EDDF8D908", "BF5224FB246A6B67EA986EFF77A43F6C1BCA9672", + "C0A30989F3717CE5B1B2FE462797951EA6D3922A", "C5539F4EBECABA792CC40D03A56144AAD3BF9D19", "C5BCB9E2E47C3F6FD3F7F83ED982872F77852BA7", "C86D546CA47034163C12DC2C912910C3A12C3B07", @@ -175,6 +180,7 @@ "F273C23C616F5C56E8EDBAE24B21F5D408936A0D", "F566B33D62CE21415AF5B3F3FD8762B7454B8874", "F59AB261280AB3AE9826D9359507838B90B07431", + "F608282162AD48CE45D5BC2F6F467B56E88EBFA4", "F73F9EF0207603992CA3C00A7A0CB223D5571B3F", "F9287A33E15038F2591F23E6E9C486717C7202DD", "FEE3DC8C722657A4A5B0F72CA48CF950DC956148",
diff --git a/extensions/common/api/feedback_private.idl b/extensions/common/api/feedback_private.idl index 7cdf2b7..a5069b2 100644 --- a/extensions/common/api/feedback_private.idl +++ b/extensions/common/api/feedback_private.idl
@@ -73,7 +73,6 @@ SystemInformation[]? systemInformation; // True if we have permission to add histograms to this feedback report. - // Deprecated and will be ignored. boolean? sendHistograms; // Optional feedback UI flow. Default is the regular user flow.
diff --git a/extensions/components/native_app_window/native_app_window_views.cc b/extensions/components/native_app_window/native_app_window_views.cc index 596f2c56..35aa2fb8 100644 --- a/extensions/components/native_app_window/native_app_window_views.cc +++ b/extensions/components/native_app_window/native_app_window_views.cc
@@ -320,7 +320,7 @@ } void NativeAppWindowViews::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { if (details.is_add && details.child == this) { web_view_ = new views::WebView(NULL); AddChildView(web_view_);
diff --git a/extensions/components/native_app_window/native_app_window_views.h b/extensions/components/native_app_window/native_app_window_views.h index 6bcc3e5..a537c42 100644 --- a/extensions/components/native_app_window/native_app_window_views.h +++ b/extensions/components/native_app_window/native_app_window_views.h
@@ -118,7 +118,7 @@ // views::View implementation. void Layout() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; gfx::Size GetMinimumSize() const override; gfx::Size GetMaximumSize() const override; void OnFocus() override;
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc index 9a53837b..1993abc 100644 --- a/fuchsia/engine/browser/frame_impl.cc +++ b/fuchsia/engine/browser/frame_impl.cc
@@ -458,8 +458,8 @@ content::NavigationController::LoadURLParams params_converted(validated_url); if (params.has_headers()) { std::vector<base::StringPiece> extra_headers; - extra_headers.reserve(params.headers()->size()); - for (const auto& header : *params.headers()) { + extra_headers.reserve(params.headers().size()); + for (const auto& header : params.headers()) { extra_headers.push_back(base::StringPiece( reinterpret_cast<const char*>(header.data()), header.size())); }
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc index 5ed5be83..856142c 100644 --- a/fuchsia/runners/cast/cast_runner.cc +++ b/fuchsia/runners/cast/cast_runner.cc
@@ -102,7 +102,7 @@ // Create a component based on the returned configuration, and pass it the // fields stashed in PendingComponent. - GURL cast_app_url(*app_config.web_url()); + GURL cast_app_url(app_config.web_url()); auto component = std::make_unique<CastComponent>( this, std::move(pending_component->startup_context), std::move(pending_component->controller_request),
diff --git a/gpu/command_buffer/client/context_support.h b/gpu/command_buffer/client/context_support.h index a3438f75..48e2b80 100644 --- a/gpu/command_buffer/client/context_support.h +++ b/gpu/command_buffer/client/context_support.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/callback.h" +#include "base/containers/span.h" #include "ui/gfx/overlay_transform.h" #include "ui/gfx/presentation_feedback.h" @@ -134,6 +135,12 @@ virtual unsigned int GetTransferBufferFreeSize() const = 0; + // Determines if an encoded image can be decoded using hardware decode + // acceleration. If this method returns true, then the client can be confident + // that a call to RasterInterface::ScheduleImageDecode() will succeed. + virtual bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const = 0; + // Returns true if the context provider automatically manages calls to // GrContext::resetContext under the hood to prevent GL state synchronization // problems between the GLES2 interface and skia.
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 985e6324..4c7e257 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -6656,6 +6656,12 @@ return 0; } +bool GLES2Implementation::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const { + NOTREACHED(); + return false; +} + void GLES2Implementation::GenSyncTokenCHROMIUM(GLbyte* sync_token) { if (!sync_token) { SetGLError(GL_INVALID_VALUE, "glGenSyncTokenCHROMIUM", "empty sync_token");
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 4a5d198..3e4d8c5f 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -143,6 +143,8 @@ const std::vector<std::pair<uint32_t, uint32_t>>& entries) override; void DeleteTransferCacheEntry(uint32_t type, uint32_t id) override; unsigned int GetTransferBufferFreeSize() const override; + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const override; void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8_t>* result); GLint GetAttribLocationHelper(GLuint program, const char* name);
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index 832dad31..beb0128 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -515,6 +515,11 @@ return transfer_buffer_->GetFreeSize(); } +bool RasterImplementation::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const { + return image_decode_accelerator_->IsImageSupported(encoded_data); +} + const std::string& RasterImplementation::GetLogPrefix() const { const std::string& prefix(debug_marker_manager_.GetMarker()); return prefix.empty() ? this_in_hex_ : prefix; @@ -1136,11 +1141,6 @@ FlushPaintCachePurgedEntries(); } -bool RasterImplementation::CanDecodeWithHardwareAcceleration( - base::span<const uint8_t> encoded_data) { - return image_decode_accelerator_->IsImageSupported(encoded_data); -} - SyncToken RasterImplementation::ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h index 7a0b50a..86dc3c3 100644 --- a/gpu/command_buffer/client/raster_implementation.h +++ b/gpu/command_buffer/client/raster_implementation.h
@@ -134,8 +134,6 @@ const gfx::Vector2dF& post_translate, GLfloat post_scale, bool requires_clear) override; - bool CanDecodeWithHardwareAcceleration( - base::span<const uint8_t> encoded_data) override; SyncToken ScheduleImageDecode(base::span<const uint8_t> encoded_data, const gfx::Size& output_size, uint32_t transfer_cache_entry_id, @@ -184,6 +182,8 @@ const std::vector<std::pair<uint32_t, uint32_t>>& entries) override; void DeleteTransferCacheEntry(uint32_t type, uint32_t id) override; unsigned int GetTransferBufferFreeSize() const override; + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const override; bool GetQueryObjectValueHelper(const char* function_name, GLuint id,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 8c6b378..298cf5f0 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -152,12 +152,6 @@ NOTREACHED(); } -bool RasterImplementationGLES::CanDecodeWithHardwareAcceleration( - base::span<const uint8_t> encoded_data) { - NOTREACHED(); - return false; -} - SyncToken RasterImplementationGLES::ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index cdc9578..b377da0 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -78,8 +78,6 @@ void EndRasterCHROMIUM() override; // Image decode acceleration. - bool CanDecodeWithHardwareAcceleration( - base::span<const uint8_t> encoded_data) override; SyncToken ScheduleImageDecode(base::span<const uint8_t> encoded_data, const gfx::Size& output_size, uint32_t transfer_cache_entry_id,
diff --git a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc index 6e0ac73..7bb47393 100644 --- a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc +++ b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
@@ -220,6 +220,10 @@ const std::vector<std::pair<uint32_t, uint32_t>>& entries) override {} void DeleteTransferCacheEntry(uint32_t type, uint32_t id) override {} unsigned int GetTransferBufferFreeSize() const override { return 0; } + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const override { + return false; + } bool HasGrContextSupport() const override { return false; } void SetGrContext(GrContext* gr) override {} void WillCallGLFromSkia() override {}
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h index 77d8ae4d..ef08d50 100644 --- a/gpu/command_buffer/client/raster_interface.h +++ b/gpu/command_buffer/client/raster_interface.h
@@ -64,15 +64,10 @@ GLfloat post_scale, bool requires_clear) = 0; - // Determines if an encoded image can be decoded using hardware decode - // acceleration. If this method returns true, then the client can be confident - // that a call to ScheduleImageDecode() will succeed. - virtual bool CanDecodeWithHardwareAcceleration( - base::span<const uint8_t> encoded_data) = 0; - // Schedules a hardware-accelerated image decode and a sync token that's // released when the image decode is complete. If the decode could not be - // scheduled, an empty sync token is returned. + // scheduled, an empty sync token is returned. This method should only be + // called if ContextSupport::CanDecodeWithHardwareAcceleration() returns true. virtual SyncToken ScheduleImageDecode( base::span<const uint8_t> encoded_data, const gfx::Size& output_size,
diff --git a/gpu/command_buffer/client/webgpu_implementation.cc b/gpu/command_buffer/client/webgpu_implementation.cc index 66f4f4b..8f038c4 100644 --- a/gpu/command_buffer/client/webgpu_implementation.cc +++ b/gpu/command_buffer/client/webgpu_implementation.cc
@@ -139,6 +139,11 @@ NOTREACHED(); return 0; } +bool WebGPUImplementation::CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const { + NOTREACHED(); + return false; +} // ImplementationBase implementation. void WebGPUImplementation::IssueShallowFlush() {
diff --git a/gpu/command_buffer/client/webgpu_implementation.h b/gpu/command_buffer/client/webgpu_implementation.h index e76ded88..f261c64 100644 --- a/gpu/command_buffer/client/webgpu_implementation.h +++ b/gpu/command_buffer/client/webgpu_implementation.h
@@ -81,6 +81,8 @@ const std::vector<std::pair<uint32_t, uint32_t>>& entries) override; void DeleteTransferCacheEntry(uint32_t type, uint32_t id) override; unsigned int GetTransferBufferFreeSize() const override; + bool CanDecodeWithHardwareAcceleration( + base::span<const uint8_t> encoded_data) const override; // ImplementationBase implementation. void IssueShallowFlush() override;
diff --git a/gpu/command_buffer/service/scheduler.cc b/gpu/command_buffer/service/scheduler.cc index 6246f03..c0ff111 100644 --- a/gpu/command_buffer/service/scheduler.cc +++ b/gpu/command_buffer/service/scheduler.cc
@@ -335,7 +335,6 @@ } void Scheduler::EnableSequence(SequenceId sequence_id) { - DCHECK(thread_checker_.CalledOnValidThread()); base::AutoLock auto_lock(lock_); Sequence* sequence = GetSequence(sequence_id); DCHECK(sequence); @@ -343,7 +342,6 @@ } void Scheduler::DisableSequence(SequenceId sequence_id) { - DCHECK(thread_checker_.CalledOnValidThread()); base::AutoLock auto_lock(lock_); Sequence* sequence = GetSequence(sequence_id); DCHECK(sequence);
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index f7a4e2a0..4881834 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -20,6 +20,7 @@ #include "gpu/config/gpu_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" +#include "ui/gl/gl_version_info.h" #include "ui/gl/init/gl_factory.h" #if defined(OS_LINUX) @@ -399,14 +400,17 @@ gl_.Initialize(options); gl_.MakeCurrent(); - bool result = - gl::init::GetGLWindowSystemBindingInfo(&window_system_binding_info_); + gl_extensions_ = + gfx::MakeExtensionSet(gl::GetGLExtensionsFromCurrentContext()); + gl::GLVersionInfo gl_version_info( + reinterpret_cast<const char*>(glGetString(GL_VERSION)), + reinterpret_cast<const char*>(glGetString(GL_RENDERER)), gl_extensions_); + bool result = gl::init::GetGLWindowSystemBindingInfo( + gl_version_info, &window_system_binding_info_); DCHECK(result); egl_extensions_ = gfx::MakeExtensionSet(window_system_binding_info_.extensions); - gl_extensions_ = - gfx::MakeExtensionSet(gl::GetGLExtensionsFromCurrentContext()); return true; }
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index 4e28d955..3a7166c 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -300,7 +300,8 @@ return false; } } - if (!direct_rendering && gpu_info.direct_rendering) { + if (direct_rendering_version.IsSpecified() && + !direct_rendering_version.Contains(gpu_info.direct_rendering_version)) { return false; } if (in_process_gpu && !gpu_info.in_process_gpu) {
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h index e84b962..4563cac 100644 --- a/gpu/config/gpu_control_list.h +++ b/gpu/config/gpu_control_list.h
@@ -153,7 +153,7 @@ Version pixel_shader_version; bool in_process_gpu; uint32_t gl_reset_notification_strategy; - bool direct_rendering; + Version direct_rendering_version; Version gpu_count; SupportedOrNot hardware_overlay;
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc index 6214f40..e35e9c5e 100644 --- a/gpu/config/gpu_control_list_entry_unittest.cc +++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -661,9 +661,17 @@ TEST_F(GpuControlListEntryTest, DirectRendering) { const Entry& entry = GetEntry(kGpuControlListEntryTest_DirectRendering); GPUInfo gpu_info; - gpu_info.direct_rendering = true; + // No info does not match. + gpu_info.direct_rendering_version = ""; EXPECT_FALSE(entry.Contains(kOsLinux, "7.0", gpu_info)); - gpu_info.direct_rendering = false; + + // Indirect rendering does not match. + gpu_info.direct_rendering_version = "1"; + EXPECT_FALSE(entry.Contains(kOsLinux, "7.0", gpu_info)); + + gpu_info.direct_rendering_version = "2"; + EXPECT_TRUE(entry.Contains(kOsLinux, "7.0", gpu_info)); + gpu_info.direct_rendering_version = "2.3"; EXPECT_TRUE(entry.Contains(kOsLinux, "7.0", gpu_info)); }
diff --git a/gpu/config/gpu_control_list_testing.json b/gpu/config/gpu_control_list_testing.json index 3c4cd77..ca5a29e 100644 --- a/gpu/config/gpu_control_list_testing.json +++ b/gpu/config/gpu_control_list_testing.json
@@ -698,7 +698,10 @@ "os": { "type": "linux" }, - "direct_rendering": false, + "direct_rendering_version": { + "op" : ">=", + "value": "2" + }, "features": [ "test_feature_1" ]
diff --git a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h index f543d980..34dfde9b 100644 --- a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h +++ b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h
@@ -40,22 +40,134 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry1_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry2[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry2_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry3[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry3_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry4[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry4_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const GpuControlList::More kMoreForEntry4_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry5[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry5_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const GpuControlList::More kMoreForEntry5_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry6[1] = { TEST_FEATURE_0, }; @@ -68,6 +180,22 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry6_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry7[1] = { TEST_FEATURE_0, }; @@ -77,15 +205,47 @@ 0x0640, }; +const GpuControlList::More kMoreForEntry7_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry8[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry8_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry9[1] = { TEST_FEATURE_0, }; -const GpuControlList::More kMoreForEntry9 = { +const GpuControlList::More kMoreForEntry9_1440601243 = { GpuControlList::kGLTypeGLES, // gl_type {GpuControlList::kEQ, GpuControlList::kVersionStyleNumerical, "3.0", nullptr}, // gl_version @@ -93,7 +253,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -104,7 +265,7 @@ TEST_FEATURE_0, }; -const GpuControlList::More kMoreForEntry10 = { +const GpuControlList::More kMoreForEntry10_1440601243 = { GpuControlList::kGLTypeANGLE, // gl_type {GpuControlList::kGT, GpuControlList::kVersionStyleNumerical, "2.0", nullptr}, // gl_version @@ -112,7 +273,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -123,7 +285,7 @@ TEST_FEATURE_0, }; -const GpuControlList::More kMoreForEntry11 = { +const GpuControlList::More kMoreForEntry11_1440601243 = { GpuControlList::kGLTypeGL, // gl_type {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, "4.0", nullptr}, // gl_version @@ -131,7 +293,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -149,6 +312,22 @@ nullptr, }; +const GpuControlList::More kMoreForEntry12_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry13[1] = { TEST_FEATURE_0, }; @@ -160,6 +339,22 @@ nullptr, }; +const GpuControlList::More kMoreForEntry13_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry14[1] = { TEST_FEATURE_0, }; @@ -171,6 +366,22 @@ nullptr, }; +const GpuControlList::More kMoreForEntry14_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry15[1] = { TEST_FEATURE_0, }; @@ -182,6 +393,22 @@ nullptr, }; +const GpuControlList::More kMoreForEntry15_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry16[1] = { TEST_FEATURE_0, }; @@ -193,14 +420,62 @@ nullptr, }; +const GpuControlList::More kMoreForEntry16_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry17[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry17_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry18[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry18_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry19[1] = { TEST_FEATURE_0, }; @@ -213,6 +488,22 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry19_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry20[1] = { TEST_FEATURE_0, }; @@ -225,6 +516,22 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry20_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry21[1] = { TEST_FEATURE_1, }; @@ -237,10 +544,42 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry21_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry22[1] = { TEST_FEATURE_1, }; +const GpuControlList::More kMoreForEntry22_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const GpuControlList::GLStrings kGLStringsForGpuControlTestingEntry22Exception0 = { nullptr, @@ -249,11 +588,27 @@ nullptr, }; +const GpuControlList::More kMoreForEntry22_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry23[1] = { TEST_FEATURE_1, }; -const GpuControlList::More kMoreForEntry23 = { +const GpuControlList::More kMoreForEntry23_1440601243 = { GpuControlList::kGLTypeGL, // gl_type {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, "3.5", nullptr}, // gl_version @@ -261,7 +616,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -274,11 +630,43 @@ TEST_FEATURE_2, }; +const GpuControlList::More kMoreForEntry24_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry25[2] = { TEST_FEATURE_1, TEST_FEATURE_2, }; +const GpuControlList::More kMoreForEntry25_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry26[1] = { TEST_FEATURE_0, }; @@ -287,6 +675,22 @@ 0x0640, }; +const GpuControlList::More kMoreForEntry26_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry27[1] = { TEST_FEATURE_0, }; @@ -305,10 +709,42 @@ nullptr}, // machine model version }; +const GpuControlList::More kMoreForEntry27_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry28[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry28_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const char* const kMachineModelNameForEntry28Exception0[1] = { "Nexus.*", }; @@ -321,6 +757,22 @@ nullptr}, // machine model version }; +const GpuControlList::More kMoreForEntry28_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry29[1] = { TEST_FEATURE_0, }; @@ -336,6 +788,22 @@ nullptr}, // machine model version }; +const GpuControlList::More kMoreForEntry29_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry30[1] = { TEST_FEATURE_0, }; @@ -351,6 +819,22 @@ nullptr}, // machine model version }; +const GpuControlList::More kMoreForEntry30_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const GpuControlList::MachineModelInfo kMachineModelInfoForEntry30Exception0 = { 0, // machine model name size nullptr, // machine model names @@ -358,6 +842,22 @@ nullptr}, // machine model version }; +const GpuControlList::More kMoreForEntry30_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry31[1] = { TEST_FEATURE_0, }; @@ -366,6 +866,22 @@ 0x0166, }; +const GpuControlList::More kMoreForEntry31_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry32[1] = { TEST_FEATURE_0, }; @@ -374,6 +890,22 @@ 0x0640, }; +const GpuControlList::More kMoreForEntry32_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry33[1] = { TEST_FEATURE_0, }; @@ -382,6 +914,22 @@ 0x0166, }; +const GpuControlList::More kMoreForEntry33_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry34[1] = { TEST_FEATURE_0, }; @@ -390,6 +938,22 @@ 0x0166, }; +const GpuControlList::More kMoreForEntry34_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry35[1] = { TEST_FEATURE_0, }; @@ -398,6 +962,22 @@ 0x0166, }; +const GpuControlList::More kMoreForEntry35_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry36[1] = { TEST_FEATURE_0, }; @@ -407,10 +987,42 @@ 0x0168, }; +const GpuControlList::More kMoreForEntry36_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry37[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry37_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry38[1] = { TEST_FEATURE_0, }; @@ -419,15 +1031,47 @@ 0x0640, }; +const GpuControlList::More kMoreForEntry38_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry39[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry39_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry40[1] = { TEST_FEATURE_0, }; -const GpuControlList::More kMoreForEntry40 = { +const GpuControlList::More kMoreForEntry40_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -435,7 +1079,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -446,22 +1091,102 @@ TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry41_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry42[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry42_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry43[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry43_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry44[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry44_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry45[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry45_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const uint32_t kDeviceIDsForGpuControlTestingEntry45Exception0[1] = { 0x2a06, }; @@ -475,6 +1200,22 @@ nullptr, nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry45_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const uint32_t kDeviceIDsForGpuControlTestingEntry45Exception1[1] = { 0x2a02, }; @@ -488,19 +1229,67 @@ nullptr, nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry45_1440601243Exception1 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry46[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry46_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry47[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry47_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry48[1] = { TEST_FEATURE_0, }; -const GpuControlList::More kMoreForEntry48 = { +const GpuControlList::More kMoreForEntry48_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -508,7 +1297,8 @@ nullptr}, // pixel_shader_version true, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -519,6 +1309,22 @@ TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry49_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry50[1] = { TEST_FEATURE_0, }; @@ -531,6 +1337,22 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry50_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry51[1] = { TEST_FEATURE_0, }; @@ -543,10 +1365,42 @@ nullptr}, // driver_date }; +const GpuControlList::More kMoreForEntry51_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry52[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry52_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const GpuControlList::GLStrings kGLStringsForGpuControlTestingEntry52Exception0 = { nullptr, @@ -555,10 +1409,42 @@ nullptr, }; +const GpuControlList::More kMoreForEntry52_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry53[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry53_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry54[1] = { TEST_FEATURE_0, }; @@ -571,21 +1457,7 @@ nullptr}, // driver_date }; -const char* const kDisabledExtensionsForEntry55[2] = { - "test_extension2", - "test_extension1", -}; - -const char* const kDisabledExtensionsForEntry56[2] = { - "test_extension3", - "test_extension2", -}; - -const int kFeatureListForGpuControlTestingEntry57[1] = { - TEST_FEATURE_1, -}; - -const GpuControlList::More kMoreForEntry57 = { +const GpuControlList::More kMoreForEntry54_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -593,7 +1465,70 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - false, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const char* const kDisabledExtensionsForEntry55[2] = { + "test_extension2", + "test_extension1", +}; + +const GpuControlList::More kMoreForEntry55_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const char* const kDisabledExtensionsForEntry56[2] = { + "test_extension3", + "test_extension2", +}; + +const GpuControlList::More kMoreForEntry56_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const int kFeatureListForGpuControlTestingEntry57[1] = { + TEST_FEATURE_1, +}; + +const GpuControlList::More kMoreForEntry57_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kGE, GpuControlList::kVersionStyleNumerical, "2", + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -604,11 +1539,7 @@ TEST_FEATURE_0, }; -const int kFeatureListForGpuControlTestingEntry59[1] = { - TEST_FEATURE_0, -}; - -const GpuControlList::More kMoreForEntry59 = { +const GpuControlList::More kMoreForEntry58_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -616,7 +1547,28 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const int kFeatureListForGpuControlTestingEntry59[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::More kMoreForEntry59_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -627,7 +1579,7 @@ TEST_FEATURE_1, }; -const GpuControlList::More kMoreForEntry60 = { +const GpuControlList::More kMoreForEntry60_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -635,7 +1587,8 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kDontCare, // hardware_overlay @@ -651,6 +1604,22 @@ GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry61_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry62[1] = { TEST_FEATURE_0, }; @@ -659,6 +1628,22 @@ GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry62_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry63[1] = { TEST_FEATURE_0, }; @@ -667,6 +1652,22 @@ GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry63_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry64[1] = { TEST_FEATURE_0, }; @@ -675,6 +1676,22 @@ GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry64_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry65[1] = { TEST_FEATURE_0, }; @@ -683,14 +1700,62 @@ GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry65_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry66[1] = { TEST_FEATURE_0, }; +const GpuControlList::More kMoreForEntry66_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const GpuSeriesType kGpuSeriesForEntry66Exception0[1] = { GpuSeriesType::kIntelKabyLake, }; +const GpuControlList::More kMoreForEntry66_1440601243Exception0 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + const int kFeatureListForGpuControlTestingEntry67[1] = { TEST_FEATURE_0, }; @@ -703,11 +1768,7 @@ nullptr}, // driver_date }; -const int kFeatureListForGpuControlTestingEntry68[1] = { - TEST_FEATURE_0, -}; - -const GpuControlList::More kMoreForEntry68 = { +const GpuControlList::More kMoreForEntry67_1440601243 = { GpuControlList::kGLTypeNone, // gl_type {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gl_version @@ -715,7 +1776,28 @@ nullptr}, // pixel_shader_version false, // in_process_gpu 0, // gl_reset_notification_strategy - true, // direct_rendering + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group +}; + +const int kFeatureListForGpuControlTestingEntry68[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::More kMoreForEntry68_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, nullptr}, // gpu_count GpuControlList::kUnsupported, // hardware_overlay
diff --git a/gpu/config/gpu_control_list_testing_autogen.cc b/gpu/config/gpu_control_list_testing_autogen.cc index 7601e14f..b71fbeb0 100644 --- a/gpu/config/gpu_control_list_testing_autogen.cc +++ b/gpu/config/gpu_control_list_testing_autogen.cc
@@ -41,7 +41,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry1_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -71,7 +71,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry2_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -101,7 +101,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry3_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -131,7 +131,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry4_1440601243, // more data }, base::size(kExceptionsForEntry4), // exceptions count kExceptionsForEntry4, // exceptions @@ -161,7 +161,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry5_1440601243, // more data }, base::size(kExceptionsForEntry5), // exceptions count kExceptionsForEntry5, // exceptions @@ -191,7 +191,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry6_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -221,7 +221,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry7_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -251,7 +251,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry8_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -281,7 +281,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry9, // more data + &kMoreForEntry9_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -311,7 +311,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry10, // more data + &kMoreForEntry10_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -341,7 +341,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry11, // more data + &kMoreForEntry11_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -371,7 +371,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry12_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -401,7 +401,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry13_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -431,7 +431,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry14_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -461,7 +461,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry15_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -491,7 +491,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry16_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -521,7 +521,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry17_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -551,7 +551,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry18_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -581,7 +581,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry19_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -611,7 +611,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry20_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -641,7 +641,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry21_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -671,7 +671,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry22_1440601243, // more data }, base::size(kExceptionsForEntry22), // exceptions count kExceptionsForEntry22, // exceptions @@ -701,7 +701,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry23, // more data + &kMoreForEntry23_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -731,7 +731,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry24_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -761,7 +761,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry25_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -792,7 +792,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry26_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -822,7 +822,7 @@ &kMachineModelInfoForEntry27, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry27_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -852,7 +852,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry28_1440601243, // more data }, base::size(kExceptionsForEntry28), // exceptions count kExceptionsForEntry28, // exceptions @@ -882,7 +882,7 @@ &kMachineModelInfoForEntry29, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry29_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -912,7 +912,7 @@ &kMachineModelInfoForEntry30, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry30_1440601243, // more data }, base::size(kExceptionsForEntry30), // exceptions count kExceptionsForEntry30, // exceptions @@ -943,7 +943,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry31_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -974,7 +974,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry32_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1005,7 +1005,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry33_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1036,7 +1036,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry34_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1067,7 +1067,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry35_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1098,7 +1098,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry36_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1128,7 +1128,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry37_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1159,7 +1159,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry38_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1189,7 +1189,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry39_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1219,7 +1219,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry40, // more data + &kMoreForEntry40_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1249,7 +1249,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry41_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1279,7 +1279,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry42_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1309,7 +1309,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry43_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1339,7 +1339,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry44_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1369,7 +1369,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry45_1440601243, // more data }, base::size(kExceptionsForEntry45), // exceptions count kExceptionsForEntry45, // exceptions @@ -1400,7 +1400,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry46_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1431,7 +1431,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry47_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1461,7 +1461,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry48, // more data + &kMoreForEntry48_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1491,7 +1491,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry49_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1521,7 +1521,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry50_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1551,7 +1551,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry51_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1581,7 +1581,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry52_1440601243, // more data }, base::size(kExceptionsForEntry52), // exceptions count kExceptionsForEntry52, // exceptions @@ -1611,7 +1611,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry53_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1641,7 +1641,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry54_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1671,7 +1671,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry55_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1701,7 +1701,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry56_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1731,7 +1731,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry57, // more data + &kMoreForEntry57_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1761,7 +1761,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry58_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1791,7 +1791,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry59, // more data + &kMoreForEntry59_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1821,7 +1821,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry60, // more data + &kMoreForEntry60_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1851,7 +1851,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry61), // gpu_series size kGpuSeriesForEntry61, // gpu_series - nullptr, // more conditions + &kMoreForEntry61_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1881,7 +1881,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry62), // gpu_series size kGpuSeriesForEntry62, // gpu_series - nullptr, // more conditions + &kMoreForEntry62_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1911,7 +1911,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry63), // gpu_series size kGpuSeriesForEntry63, // gpu_series - nullptr, // more conditions + &kMoreForEntry63_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1941,7 +1941,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry64), // gpu_series size kGpuSeriesForEntry64, // gpu_series - nullptr, // more conditions + &kMoreForEntry64_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -1971,7 +1971,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry65), // gpu_series size kGpuSeriesForEntry65, // gpu_series - nullptr, // more conditions + &kMoreForEntry65_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -2001,7 +2001,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry66_1440601243, // more data }, base::size(kExceptionsForEntry66), // exceptions count kExceptionsForEntry66, // exceptions @@ -2031,7 +2031,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry67_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions @@ -2061,7 +2061,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - &kMoreForEntry68, // more data + &kMoreForEntry68_1440601243, // more data }, 0, // exceptions count nullptr, // exceptions
diff --git a/gpu/config/gpu_control_list_testing_exceptions_autogen.h b/gpu/config/gpu_control_list_testing_exceptions_autogen.h index 1adc7d7..49b04a3 100644 --- a/gpu/config/gpu_control_list_testing_exceptions_autogen.h +++ b/gpu/config/gpu_control_list_testing_exceptions_autogen.h
@@ -27,7 +27,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry4_1440601243Exception0, // more data }, }; @@ -46,7 +46,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry5_1440601243Exception0, // more data }, }; @@ -65,7 +65,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry22_1440601243Exception0, // more data }, }; @@ -84,7 +84,7 @@ &kMachineModelInfoForEntry28Exception0, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry28_1440601243Exception0, // more data }, }; @@ -103,7 +103,7 @@ &kMachineModelInfoForEntry30Exception0, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry30_1440601243Exception0, // more data }, }; @@ -120,10 +120,10 @@ GpuControlList::kMultiGpuStyleNone, // multi_gpu_style &kDriverInfoForGpuControlTestingEntry45Exception0, // driver info nullptr, // GL strings - nullptr, // machine model info - 0, // gpu_series size - nullptr, // gpu_series - nullptr, // more conditions + nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series + &kMoreForEntry45_1440601243Exception0, // more data }, { GpuControlList::kOsAny, // os_type @@ -137,10 +137,10 @@ GpuControlList::kMultiGpuStyleNone, // multi_gpu_style &kDriverInfoForGpuControlTestingEntry45Exception1, // driver info nullptr, // GL strings - nullptr, // machine model info - 0, // gpu_series size - nullptr, // gpu_series - nullptr, // more conditions + nullptr, // machine model info + 0, // gpu_series size + nullptr, // gpu_series + &kMoreForEntry45_1440601243Exception1, // more data }, }; @@ -159,7 +159,7 @@ nullptr, // machine model info 0, // gpu_series size nullptr, // gpu_series - nullptr, // more conditions + &kMoreForEntry52_1440601243Exception0, // more data }, }; @@ -178,7 +178,7 @@ nullptr, // machine model info base::size(kGpuSeriesForEntry66Exception0), // gpu_series size kGpuSeriesForEntry66Exception0, // gpu_series - nullptr, // more conditions + &kMoreForEntry66_1440601243Exception0, // more data }, };
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 25bff8ed..5ec819c6 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -449,6 +449,10 @@ }, "gl_type": "gl", "gl_renderer": ".*Mesa.*", + "direct_rendering_version": { + "op" : "<", + "value": "2.3" + }, "features": [ "disable_post_sub_buffers_for_onscreen_surfaces" ] @@ -1865,6 +1869,10 @@ }, "gl_type": "gl", "gl_version_string": ".*Mesa.*", + "direct_rendering_version": { + "op" : "<", + "value": "2.3" + }, "features": [ "disable_post_sub_buffers_for_onscreen_surfaces" ] @@ -2580,19 +2588,6 @@ ] }, { - "id": 248, - "description": "Direct composition causes slow presents on Intel Sandybridge", - "cr_bugs": [775898, 785648], - "os": { - "type": "win" - }, - "vendor_id": "0x8086", - "device_id": ["0x0116"], - "features": [ - "disable_direct_composition" - ] - }, - { "id": 249, "description": "Direct composition causes slow presents on old Nvidia GPUs", "cr_bugs": [775898], @@ -3254,6 +3249,21 @@ "features": [ "exit_on_context_lost" ] + }, + { + "id": 300, + "cr_bugs": [775898, 785648, 9245627], + "description": "Direct composition causes rendering issues on Intel SandyBridge and IvyBridge GPUs", + "os": { + "type" : "win" + }, + "gpu_series": [ + "intel_sandybridge", + "intel_ivybridge" + ], + "features": [ + "disable_direct_composition" + ] } ] }
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc index 38abaf01..7036b3a5 100644 --- a/gpu/config/gpu_info.cc +++ b/gpu/config/gpu_info.cc
@@ -186,7 +186,6 @@ amd_switchable(false), gl_reset_notification_strategy(0), software_rendering(false), - direct_rendering(true), sandboxed(false), in_process_gpu(true), passthrough_cmd_decoder(false), @@ -243,7 +242,7 @@ std::string gl_ws_extensions; uint32_t gl_reset_notification_strategy; bool software_rendering; - bool direct_rendering; + std::string direct_rendering_version; bool sandboxed; bool in_process_gpu; bool passthrough_cmd_decoder; @@ -306,7 +305,7 @@ static_cast<int>(gl_reset_notification_strategy)); // TODO(kbr): add performance_stats. enumerator->AddBool("softwareRendering", software_rendering); - enumerator->AddBool("directRendering", direct_rendering); + enumerator->AddString("directRenderingVersion", direct_rendering_version); enumerator->AddBool("sandboxed", sandboxed); enumerator->AddBool("inProcessGpu", in_process_gpu); enumerator->AddBool("passthroughCmdDecoder", passthrough_cmd_decoder);
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h index 88420f3..37e29d2 100644 --- a/gpu/config/gpu_info.h +++ b/gpu/config/gpu_info.h
@@ -295,9 +295,12 @@ bool software_rendering; - // Whether the driver uses direct rendering. True on most platforms, false on - // X11 when using remote X. - bool direct_rendering; + // Empty means unknown. Defined on X11 as + // - "1" means indirect (versions can't be all zero) + // - "2" means some type of direct rendering, but version cannot not be + // reliably determined + // - "2.1", "2.2", "2.3" for DRI, DRI2, DRI3 respectively + std::string direct_rendering_version; // Whether the gpu process is running in a sandbox. bool sandboxed;
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc index d5737b6..79d1a7f 100644 --- a/gpu/config/gpu_info_collector.cc +++ b/gpu/config/gpu_info_collector.cc
@@ -226,11 +226,13 @@ gfx::HasExtension(extension_set, "GL_OES_EGL_image"); #else gl::GLWindowSystemBindingInfo window_system_binding_info; - if (gl::init::GetGLWindowSystemBindingInfo(&window_system_binding_info)) { + if (gl::init::GetGLWindowSystemBindingInfo(gl_info, + &window_system_binding_info)) { gpu_info->gl_ws_vendor = window_system_binding_info.vendor; gpu_info->gl_ws_version = window_system_binding_info.version; gpu_info->gl_ws_extensions = window_system_binding_info.extensions; - gpu_info->direct_rendering = window_system_binding_info.direct_rendering; + gpu_info->direct_rendering_version = + window_system_binding_info.direct_rendering_version; } #endif // OS_ANDROID
diff --git a/gpu/config/process_json.py b/gpu/config/process_json.py index c4faaf2..df68c6a 100755 --- a/gpu/config/process_json.py +++ b/gpu/config/process_json.py
@@ -9,6 +9,7 @@ import os import platform import sys +import zlib from optparse import OptionParser from subprocess import call @@ -378,7 +379,7 @@ pixel_shader_version = None in_process_gpu = False gl_reset_notification_strategy = None - direct_rendering = True + direct_rendering_version = '' gpu_count = None hardware_overlay = None test_group = 0 @@ -451,9 +452,8 @@ in_process_gpu = True elif key == 'gl_reset_notification_strategy': gl_reset_notification_strategy = entry[key] - elif key == 'direct_rendering': - assert not entry[key] - direct_rendering = False + elif key == 'direct_rendering_version': + direct_rendering_version = entry[key] elif key == 'gpu_count': gpu_count = entry[key] elif key == 'hardware_overlay': @@ -502,13 +502,13 @@ data_file, data_helper_file) # group a bunch of less used conditions if (gl_version != None or pixel_shader_version != None or in_process_gpu or - gl_reset_notification_strategy != None or (not direct_rendering) or - gpu_count != None or hardware_overlay != None or test_group != 0): + gl_reset_notification_strategy != None or direct_rendering_version != None + or gpu_count != None or hardware_overlay != None or test_group != 0): write_entry_more_data(entry_id, is_exception, exception_id, gl_type, gl_version, pixel_shader_version, in_process_gpu, - gl_reset_notification_strategy, direct_rendering, - gpu_count, hardware_overlay, test_group, data_file, - data_helper_file) + gl_reset_notification_strategy, + direct_rendering_version, gpu_count, hardware_overlay, + test_group, data_file, data_helper_file) else: data_file.write('nullptr, // more conditions\n') @@ -549,11 +549,18 @@ def write_entry_more_data(entry_id, is_exception, exception_id, gl_type, gl_version, pixel_shader_version, in_process_gpu, - gl_reset_notification_strategy, direct_rendering, - gpu_count, hardware_overlay, test_group, data_file, - data_helper_file): + gl_reset_notification_strategy, + direct_rendering_version, gpu_count, hardware_overlay, + test_group, data_file, data_helper_file): # write more data - var_name = 'kMoreForEntry' + str(entry_id) + + # Generate a unique name for jumbo build which concatenates multiple + # translation units into one to speed compilation. + basename = os.path.basename(data_helper_file.name) + # & 0xffffffff converts to unsigned to keep consistent across Python versions + # and platforms as per https://docs.python.org/3/library/zlib.html + suffix = '_%s' % (zlib.crc32(basename) & 0xffffffff) + var_name = 'kMoreForEntry' + str(entry_id) + suffix if is_exception: var_name += 'Exception' + str(exception_id) data_helper_file.write('const GpuControlList::More %s = {\n' % var_name) @@ -565,7 +572,8 @@ gl_reset_notification_strategy = '0' data_helper_file.write('%s, // gl_reset_notification_strategy\n' % gl_reset_notification_strategy) - write_boolean_value(direct_rendering, 'direct_rendering', data_helper_file) + write_version(direct_rendering_version, 'direct_rendering_version', + data_helper_file) write_version(gpu_count, 'gpu_count', data_helper_file) write_supported_or_not(hardware_overlay, 'hardware_overlay', data_helper_file) write_integer_value(test_group, 'test_group', data_helper_file)
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index 5deceb6..d4c3b43 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -735,7 +735,10 @@ "os": { "type": "linux" }, - "direct_rendering": false, + "direct_rendering_version": { + "op": "<", + "value": "2" + }, "features": [ "all" ]
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom index fb42f07..9731c4d3 100644 --- a/gpu/ipc/common/gpu_info.mojom +++ b/gpu/ipc/common/gpu_info.mojom
@@ -141,7 +141,7 @@ string gl_ws_extensions; uint32 gl_reset_notification_strategy; bool software_rendering; - bool direct_rendering; + string direct_rendering_version; bool sandboxed; bool in_process_gpu; bool passthrough_cmd_decoder;
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc index 26148ba..f17db0f 100644 --- a/gpu/ipc/common/gpu_info_struct_traits.cc +++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -351,7 +351,6 @@ out->amd_switchable = data.amd_switchable(); out->gl_reset_notification_strategy = data.gl_reset_notification_strategy(); out->software_rendering = data.software_rendering(); - out->direct_rendering = data.direct_rendering(); out->sandboxed = data.sandboxed(); out->in_process_gpu = data.in_process_gpu(); out->passthrough_cmd_decoder = data.passthrough_cmd_decoder(); @@ -386,6 +385,7 @@ data.ReadGlWsVendor(&out->gl_ws_vendor) && data.ReadGlWsVersion(&out->gl_ws_version) && data.ReadGlWsExtensions(&out->gl_ws_extensions) && + data.ReadDirectRenderingVersion(&out->direct_rendering_version) && #if defined(OS_WIN) data.ReadOverlayCapabilities(&out->overlay_capabilities) && data.ReadDxDiagnostics(&out->dx_diagnostics) &&
diff --git a/gpu/ipc/common/gpu_info_struct_traits.h b/gpu/ipc/common/gpu_info_struct_traits.h index 926f8ea..dca1fcf 100644 --- a/gpu/ipc/common/gpu_info_struct_traits.h +++ b/gpu/ipc/common/gpu_info_struct_traits.h
@@ -313,8 +313,9 @@ return input.software_rendering; } - static bool direct_rendering(const gpu::GPUInfo& input) { - return input.direct_rendering; + static const std::string& direct_rendering_version( + const gpu::GPUInfo& input) { + return input.direct_rendering_version; } static bool sandboxed(const gpu::GPUInfo& input) { return input.sandboxed; }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc index d739de42..8c67295 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc
@@ -13,6 +13,7 @@ #include "base/memory/ptr_util.h" #include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "ui/gfx/geometry/size.h" +#include "ui/gl/android/android_surface_control_compat.h" namespace gpu { @@ -47,6 +48,8 @@ case gfx::BufferUsage::SCANOUT: desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; + if (usage == gfx::BufferUsage::SCANOUT) + desc.usage |= gl::SurfaceControl::RequiredUsage(); break; default: NOTREACHED();
diff --git a/gpu/ipc/common/struct_traits_unittest.cc b/gpu/ipc/common/struct_traits_unittest.cc index 2c51f08d..83a4aa2 100644 --- a/gpu/ipc/common/struct_traits_unittest.cc +++ b/gpu/ipc/common/struct_traits_unittest.cc
@@ -149,7 +149,7 @@ const std::string gl_ws_extensions = "gl_ws_extensions"; const uint32_t gl_reset_notification_strategy = 0xbeef; const bool software_rendering = true; - const bool direct_rendering = true; + const std::string direct_rendering_version = "DRI1"; const bool sandboxed = true; const bool in_process_gpu = true; const bool passthrough_cmd_decoder = true; @@ -193,7 +193,7 @@ input.gl_ws_extensions = gl_ws_extensions; input.gl_reset_notification_strategy = gl_reset_notification_strategy; input.software_rendering = software_rendering; - input.direct_rendering = direct_rendering; + input.direct_rendering_version = direct_rendering_version; input.sandboxed = sandboxed; input.in_process_gpu = in_process_gpu; input.passthrough_cmd_decoder = passthrough_cmd_decoder; @@ -252,7 +252,7 @@ EXPECT_EQ(gl_reset_notification_strategy, output.gl_reset_notification_strategy); EXPECT_EQ(software_rendering, output.software_rendering); - EXPECT_EQ(direct_rendering, output.direct_rendering); + EXPECT_EQ(direct_rendering_version, output.direct_rendering_version); EXPECT_EQ(sandboxed, output.sandboxed); EXPECT_EQ(in_process_gpu, output.in_process_gpu); EXPECT_EQ(passthrough_cmd_decoder, output.passthrough_cmd_decoder);
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index 0c86b101..8ed01fb 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -598,6 +598,8 @@ Microsoft::WRL::ComPtr<IDXGIDecodeSwapChain> decode_swap_chain_; Microsoft::WRL::ComPtr<IUnknown> decode_surface_; + Microsoft::WRL::ComPtr<ID3D11Query> video_processor_blt_query_; + DISALLOW_COPY_AND_ASSIGN(SwapChainPresenter); }; @@ -761,9 +763,14 @@ } static crash_reporter::CrashKeyString<32> texture_size_key( - "video-texture-size"); + "dynamic-texture-size"); texture_size_key.Set(texture_size.ToString()); + static crash_reporter::CrashKeyString<2> first_use_key( + "dynamic-texture-first-use"); + bool first_use = !staging_texture_ || (staging_texture_size_ != texture_size); + first_use_key.Set(first_use ? "1" : "0"); + if (!staging_texture_ || (staging_texture_size_ != texture_size)) { staging_texture_.Reset(); D3D11_TEXTURE2D_DESC desc = {}; @@ -792,10 +799,20 @@ DCHECK(staging_texture_); staging_texture_size_ = texture_size; } + Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; d3d11_device_->GetImmediateContext(context.GetAddressOf()); // TODO(crbug.com/890227): Temporary CHECK for debugging. CHECK(context); + + static crash_reporter::CrashKeyString<2> in_use_key("dynamic-texture-in-use"); + if (video_processor_blt_query_) { + BOOL result = FALSE; + HRESULT hr = context->GetData(video_processor_blt_query_.Get(), &result, + sizeof(BOOL), D3D11_ASYNC_GETDATA_DONOTFLUSH); + in_use_key.Set(SUCCEEDED(hr) && result ? "0" : "1"); + } + D3D11_MAPPED_SUBRESOURCE mapped_resource; HRESULT hr = context->Map(staging_texture_.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource); @@ -1455,6 +1472,20 @@ DLOG(ERROR) << "VideoProcessorBlt failed with error 0x" << std::hex << hr; return false; } + + // TODO(crbug.com/890227): Temporary query for debugging. + D3D11_QUERY_DESC query_desc = {}; + query_desc.Query = D3D11_QUERY_EVENT; + query_desc.MiscFlags = 0; + hr = d3d11_device_->CreateQuery(&query_desc, &video_processor_blt_query_); + if (SUCCEEDED(hr)) { + Microsoft::WRL::ComPtr<ID3D11DeviceContext> context; + d3d11_device_->GetImmediateContext(&context); + DCHECK(context); + context->End(video_processor_blt_query_.Get()); + } else { + DLOG(ERROR) << "CreateQuery failed with error 0x" << std::hex << hr; + } } return true;
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index b9a99c0..b831ae9 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -105,8 +105,12 @@ } GpuChannelManager::~GpuChannelManager() { - // Destroy channels before anything else because of dependencies. + // Clear |gpu_channels_| first to prevent reentrancy problems from GpuChannel + // destructor. + auto gpu_channels = std::move(gpu_channels_); gpu_channels_.clear(); + gpu_channels.clear(); + if (default_offscreen_surface_.get()) { default_offscreen_surface_->Destroy(); default_offscreen_surface_ = nullptr;
diff --git a/infra/config/commit-queue.cfg b/infra/config/commit-queue.cfg index 26ba17ac..096ff7e 100644 --- a/infra/config/commit-queue.cfg +++ b/infra/config/commit-queue.cfg
@@ -315,7 +315,7 @@ builders { name: "chromium/try/win7-rel" # https://crbug.com/943372 - experiment_percentage: 10 + experiment_percentage: 100 } builders { name: "chromium/try/win7_chromium_rel_loc_exp"
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index 10fa78da..6864224 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -1689,6 +1689,7 @@ name: "ToTAndroidASan" mixins: "clang-ci" mixins: "linux" + dimensions: "os:" #needed to target dedicated HW } builders { name: "ToTAndroidCFI"
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg index 591e860..8dc2eb1 100644 --- a/infra/config/luci-scheduler.cfg +++ b/infra/config/luci-scheduler.cfg
@@ -295,7 +295,6 @@ triggers: "android-cronet-arm64-dbg" triggers: "android-cronet-arm64-rel" triggers: "android-cronet-asan-arm-rel" - triggers: "android-cronet-x86-dbg" triggers: "android-cronet-x86-rel" triggers: "android-dbg" triggers: "android-incremental-dbg" @@ -397,6 +396,18 @@ triggers: "WebRTC Chromium FYI Win Builder (dbg)" } +# These bots are triggered on new tags only. +trigger { + id: "refs-tags-trigger" + acl_sets: "default" + + gitiles: { + repo: "https://chromium.googlesource.com/chromium/src.git" + refs: "regexp:refs/tags/.+" + } + + triggers: "android-cronet-x86-dbg" +} ################################################################################ # Android Builders. Sorted alphabetically.
diff --git a/infra/config/tricium-prod.cfg b/infra/config/tricium-prod.cfg index 6d63366..6a82b50 100644 --- a/infra/config/tricium-prod.cfg +++ b/infra/config/tricium-prod.cfg
@@ -11,7 +11,7 @@ platform: UBUNTU configs { name: "filter" - value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/header_guard,+build/include_what_you_use,+build/include_order" + value: "-,+readability/todo,+readability/check,+readability/fn_size,+build/header_guard,+build/include_order" } configs { name: "verbose"
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h index 25a2b77..54f6c283 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h
@@ -26,7 +26,7 @@ // Getter for the message displayed in addition to the title. If no message // was set, this returns an empty string. - base::string16 GetDetailsMessageText() const; + NSString* GetDetailsMessageText() const; // The Username being saved or updated by the Infobar. NSString* GetUserNameText() const;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm index 1071c24..940d695 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
@@ -30,10 +30,9 @@ infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION), is_sync_user_(is_sync_user) {} -base::string16 IOSChromePasswordManagerInfoBarDelegate::GetDetailsMessageText() +NSString* IOSChromePasswordManagerInfoBarDelegate::GetDetailsMessageText() const { - return is_sync_user_ ? l10n_util::GetStringUTF16(IDS_SAVE_PASSWORD_FOOTER) - : base::string16(); + return is_sync_user_ ? l10n_util::GetNSString(IDS_SAVE_PASSWORD_FOOTER) : @""; } NSString* IOSChromePasswordManagerInfoBarDelegate::GetUserNameText() const {
diff --git a/ios/chrome/browser/passwords/ios_password_infobar_controller.mm b/ios/chrome/browser/passwords/ios_password_infobar_controller.mm index 7ba3ad3..11be516 100644 --- a/ios/chrome/browser/passwords/ios_password_infobar_controller.mm +++ b/ios/chrome/browser/passwords/ios_password_infobar_controller.mm
@@ -4,7 +4,6 @@ #import "ios/chrome/browser/passwords/ios_password_infobar_controller.h" -#include "base/strings/sys_string_conversions.h" #import "ios/chrome/browser/infobars/confirm_infobar_controller+protected.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h" #import "ios/chrome/browser/ui/infobars/confirm_infobar_view.h" @@ -20,12 +19,11 @@ auto* delegate = static_cast<IOSChromePasswordManagerInfoBarDelegate*>( self.infoBarDelegate); - base::string16 message = delegate->GetDetailsMessageText(); - if (message.empty()) + NSString* message = delegate->GetDetailsMessageText(); + if (message.length) return; - [view addFooterLabel:base::SysUTF16ToNSString( - delegate->GetDetailsMessageText())]; + [view addFooterLabel:message]; } @end
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm index aa20772..9734196 100644 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -32,13 +32,11 @@ #import "ios/chrome/browser/ui/translate/translate_infobar_view.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/app/chrome_test_util.h" -#include "ios/chrome/test/app/navigation_test_util.h" #import "ios/chrome/test/app/tab_test_util.h" #import "ios/chrome/test/app/web_view_interaction_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" -#import "ios/web/public/test/earl_grey/js_test_util.h" #import "ios/web/public/test/earl_grey/web_view_matchers.h" #include "ios/web/public/test/http_server/data_response_provider.h" #import "ios/web/public/test/http_server/http_server.h" @@ -679,7 +677,9 @@ std::string html = "<html lang='fr'><body>"; NSUInteger targetSize = 1024 * 1024; // More than 1 MB of page content. while (html.length() < targetSize) { + html.append("<p>"); html.append(kFrenchText); + html.append("</p>"); } html.append("</body></html>"); @@ -689,22 +689,7 @@ web::test::HttpServer::MakeUrl("http://languageDetectionLargePage"); responses[URL] = html; web::test::SetUpSimpleHttpServer(responses); - - if (@available(iOS 12, *)) { - // TODO(crbug.com/874452) iOS12 has a bug where long pages take forever to - // load. Use a 20 second timeout here. - chrome_test_util::LoadUrl(URL); - web::WebState* webState = chrome_test_util::GetCurrentWebState(); - GREYAssert(WaitUntilConditionOrTimeout(20, - ^{ - return !webState->IsLoading(); - }), - @"Failed to load large page on iOS 12."); - if (webState->ContentIsHTML()) - web::WaitUntilWindowIdInjected(webState); - } else { - [ChromeEarlGrey loadURL:URL]; - } + [ChromeEarlGrey loadURL:URL]; // Check that language has been detected. translate::LanguageDetectionDetails expectedLanguageDetails;
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index a4d7e8a..6836ee9d 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -6,8 +6,6 @@ source_set("ui") { sources = [ - "UIView+SizeClassSupport.h", - "UIView+SizeClassSupport.mm", "chrome_load_params.h", "chrome_load_params.mm", "file_locations.h", @@ -237,8 +235,6 @@ "browser_view_controller_dependency_factory.mm", "browser_view_controller_helper.h", "browser_view_controller_helper.mm", - "fade_truncated_label.h", - "fade_truncated_label.mm", "key_commands_provider.h", "key_commands_provider.mm", "open_in_controller.h",
diff --git a/ios/chrome/browser/ui/UIView+SizeClassSupport.h b/ios/chrome/browser/ui/UIView+SizeClassSupport.h deleted file mode 100644 index af53dd0e..0000000 --- a/ios/chrome/browser/ui/UIView+SizeClassSupport.h +++ /dev/null
@@ -1,29 +0,0 @@ -// 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_UIVIEW_SIZECLASSSUPPORT_H_ -#define IOS_CHROME_BROWSER_UI_UIVIEW_SIZECLASSSUPPORT_H_ - -#import <UIKit/UIKit.h> - -// An enum type to describe size classes. -typedef NS_ENUM(NSInteger, SizeClassIdiom) { - COMPACT = 0, - REGULAR, - UNSPECIFIED, - SIZE_CLASS_COUNT = UNSPECIFIED, -}; - -// UIView category that exposes SizeClassIdiom getters. -@interface UIView (SizeClassSupport) - -// Convenience getters for the view's width and height SizeClassIdioms. If the -// view's size class is unspecified, these functions return the size class idiom -// of the application's key window. -@property(nonatomic, readonly) SizeClassIdiom cr_widthSizeClass; -@property(nonatomic, readonly) SizeClassIdiom cr_heightSizeClass; - -@end - -#endif // IOS_CHROME_BROWSER_UI_UIVIEW_SIZECLASSSUPPORT_H_
diff --git a/ios/chrome/browser/ui/UIView+SizeClassSupport.mm b/ios/chrome/browser/ui/UIView+SizeClassSupport.mm deleted file mode 100644 index 137d6e8..0000000 --- a/ios/chrome/browser/ui/UIView+SizeClassSupport.mm +++ /dev/null
@@ -1,53 +0,0 @@ -// 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. - -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" - -#include "base/logging.h" -#import "ios/chrome/browser/ui/util/ui_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// Returns the SizeClassIdiom corresponding with |size_class|. -SizeClassIdiom GetSizeClassIdiom(UIUserInterfaceSizeClass size_class) { - switch (size_class) { - case UIUserInterfaceSizeClassCompact: - return COMPACT; - case UIUserInterfaceSizeClassRegular: - return REGULAR; - case UIUserInterfaceSizeClassUnspecified: - return UNSPECIFIED; - } -} - -// Returns YES if |size_class| is not UIUserInterfaceSizeClassUnspecified. -bool IsSizeClassSpecified(UIUserInterfaceSizeClass size_class) { - return size_class != UIUserInterfaceSizeClassUnspecified; -} - -} // namespace - -@implementation UIView (SizeClassSupport) - -- (SizeClassIdiom)cr_widthSizeClass { - UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow; - UIUserInterfaceSizeClass sizeClass = self.traitCollection.horizontalSizeClass; - if (!IsSizeClassSpecified(sizeClass)) - sizeClass = keyWindow.traitCollection.horizontalSizeClass; - return GetSizeClassIdiom(sizeClass); -} - -- (SizeClassIdiom)cr_heightSizeClass { - UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow; - UIUserInterfaceSizeClass sizeClass = self.traitCollection.verticalSizeClass; - if (!IsSizeClassSpecified(sizeClass)) - sizeClass = keyWindow.traitCollection.verticalSizeClass; - return GetSizeClassIdiom(sizeClass); -} - -@end
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/chip_button.mm b/ios/chrome/browser/ui/autofill/manual_fill/chip_button.mm index 8d98634..a9802af 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/chip_button.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/chip_button.mm
@@ -58,12 +58,24 @@ - (void)setHighlighted:(BOOL)highlighted { [super setHighlighted:highlighted]; - CGFloat alpha = highlighted ? 0.2 : 1.0; - self.backgroundView.alpha = alpha; + self.backgroundView.backgroundColor = + highlighted ? UIColor.cr_manualFillHighlightedChipColor + : UIColor.cr_manualFillChipColor; +} + +- (void)setEnabled:(BOOL)enabled { + [super setEnabled:enabled]; + self.backgroundView.hidden = !enabled; + self.contentEdgeInsets = enabled ? [self chipEdgeInsets] : UIEdgeInsetsZero; } #pragma mark - Private +- (UIEdgeInsets)chipEdgeInsets { + return UIEdgeInsetsMake(kChipVerticalPadding, kChipHorizontalPadding, + kChipVerticalPadding, kChipHorizontalPadding); +} + - (void)initializeStyling { _backgroundView = [[UIView alloc] init]; _backgroundView.userInteractionEnabled = NO; @@ -94,9 +106,7 @@ DCHECK(boldFontDescriptor); self.titleLabel.font = [UIFont fontWithDescriptor:boldFontDescriptor size:0]; - self.contentEdgeInsets = - UIEdgeInsetsMake(kChipVerticalPadding, kChipHorizontalPadding, - kChipVerticalPadding, kChipHorizontalPadding); + self.contentEdgeInsets = [self chipEdgeInsets]; } @end
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h b/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h index b30f7eb..69cfaf5 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h
@@ -18,6 +18,10 @@ // Color for the manual fill chips. @property(class, nonatomic, readonly) UIColor* cr_manualFillChipColor; +// Color for the highlighted manual fill chips. +@property(class, nonatomic, readonly) + UIColor* cr_manualFillHighlightedChipColor; + // Color for the line separators in manual fill (0.66, 0.66, 0.66 RGB). @property(class, nonatomic, readonly) UIColor* cr_manualFillSeparatorColor;
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.mm b/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.mm index edfa1ac..5699871c 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.mm
@@ -24,6 +24,14 @@ return color; } ++ (UIColor*)cr_manualFillHighlightedChipColor { + static UIColor* color = [UIColor colorWithRed:196.0 / 255.0 + green:203.0 / 255.0 + blue:207.0 / 255.0 + alpha:1.0]; + return color; +} + + (UIColor*)cr_manualFillChipDarkTextColor { static UIColor* color = [UIColor colorWithRed:55.0 / 255.0 green:55.0 / 255.0
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm index 7e5034c..93f37e76 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -8,7 +8,6 @@ #include "base/logging.h" #include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" #import "ios/chrome/browser/ui/omnibox/omnibox_constants.h"
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index be8e2b8..dce4c246 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -10,7 +10,6 @@ #include "base/metrics/user_metrics.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h" -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_synchronizing.h"
diff --git a/ios/chrome/browser/ui/fade_truncated_label.h b/ios/chrome/browser/ui/fade_truncated_label.h deleted file mode 100644 index 088099c..0000000 --- a/ios/chrome/browser/ui/fade_truncated_label.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_FADE_TRUNCATED_LABEL_H_ -#define IOS_CHROME_BROWSER_UI_FADE_TRUNCATED_LABEL_H_ - -#import <UIKit/UIKit.h> - -// A label class that applies a gradient fade to the end of a label whose bounds -// are too small to draw the entire string. This class uses a CAGradientLayer -// as a mask instead of clipping the drawing context of the label. -@interface FadeTruncatedLabel : UILabel - -// Returns a CAGadientLayer to use as a label's masking layer that will apply -// a fade truncation if |text| takes up more space than |bounds| when drawn -// with |attributes|. -+ (CAGradientLayer*)maskLayerForText:(NSString*)text - withAttributes:(NSDictionary*)attributes - inBounds:(CGRect)bounds; - -// Adds animations from |beginFrame| to |endFrame| using the provided |duration| -// and |timingFunction|. -- (void)animateFromBeginFrame:(CGRect)beginFrame - toEndFrame:(CGRect)endFrame - duration:(CFTimeInterval)duration - timingFunction:(CAMediaTimingFunction*)timingFunction; - -// Reverses animations added by -// |-animateFromBeginFrame:toEndFrame:duration:timingFunction:|. -- (void)reverseAnimations; - -// Removes animations added by -// |-animateFromBeginFrame:toEndFrame:duration:timingFunction:|. -- (void)cleanUpAnimations; - -@end - -#endif // IOS_CHROME_BROWSER_UI_FADE_TRUNCATED_LABEL_H_
diff --git a/ios/chrome/browser/ui/fade_truncated_label.mm b/ios/chrome/browser/ui/fade_truncated_label.mm deleted file mode 100644 index c5fbad5..0000000 --- a/ios/chrome/browser/ui/fade_truncated_label.mm +++ /dev/null
@@ -1,189 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/fade_truncated_label.h" - -#include <algorithm> - -#import "ios/chrome/browser/ui/util/animation_util.h" -#import "ios/chrome/browser/ui/util/reversed_animation.h" -#import "ui/gfx/ios/uikit_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -// Animation key used for frame animations. -NSString* const kFadeTruncatedLabelAnimationKey = - @"FadeTruncatedLabelAnimationKey"; -} - -@interface FadeTruncatedLabel () - -// Layer used to apply fade truncation to label. -@property(nonatomic, strong) CAGradientLayer* maskLayer; - -// Temporary label used during animations. -@property(nonatomic, strong) UILabel* animationLabel; - -// Returns the percentage of the label's width at which to begin the fade -// gradient. -+ (CGFloat)gradientPercentageForText:(NSString*)text - withAttributes:(NSDictionary*)attributes - inBounds:(CGRect)bounds; - -@end - -@implementation FadeTruncatedLabel - -@synthesize maskLayer = _maskLayer; -@synthesize animationLabel = _animationLabel; - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - // Set background color and line break mode. - self.backgroundColor = [UIColor clearColor]; - self.lineBreakMode = NSLineBreakByClipping; - - // Instantiate |maskLayer| and add as mask. - self.maskLayer = [[self class] maskLayerForText:self.text - withAttributes:@{ - NSFontAttributeName : self.font - } - inBounds:{CGPointZero, frame.size}]; - self.layer.mask = self.maskLayer; - } - return self; -} - -#pragma mark - UILabel overrides - -- (void)drawTextInRect:(CGRect)rect { - // Draw if not animating. - if (!self.animationLabel) - [super drawTextInRect:rect]; - - // Update the mask gradient. - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - self.maskLayer.frame = rect; - NSDictionary* fontAttributes = @{NSFontAttributeName : self.font}; - CGFloat gradientBeginPercentage = - [[self class] gradientPercentageForText:self.text - withAttributes:fontAttributes - inBounds:self.maskLayer.bounds]; - self.maskLayer.locations = @[ @(gradientBeginPercentage), @(1.0) ]; - [CATransaction commit]; -} - -#pragma mark - Animations - -- (void)animateFromBeginFrame:(CGRect)beginFrame - toEndFrame:(CGRect)endFrame - duration:(CFTimeInterval)duration - timingFunction:(CAMediaTimingFunction*)timingFunction { - CAAnimation* frameAnimation = nil; - - // Animate the label. - frameAnimation = FrameAnimationMake(self.layer, beginFrame, endFrame); - frameAnimation.duration = duration; - frameAnimation.timingFunction = timingFunction; - [self.layer addAnimation:frameAnimation - forKey:kFadeTruncatedLabelAnimationKey]; - - // When animating, add a temporary label using the larger frame size so that - // truncation can occur via the gradient rather than by the edge of the text - // layer's backing store. - CGSize animationTextSize = - CGSizeMake(std::max(beginFrame.size.width, endFrame.size.width), - std::max(beginFrame.size.height, endFrame.size.height)); - self.animationLabel = - [[UILabel alloc] initWithFrame:{CGPointZero, animationTextSize}]; - self.animationLabel.text = self.text; - self.animationLabel.textColor = self.textColor; - self.animationLabel.font = self.font; - [self addSubview:self.animationLabel]; - - // Animate the mask layer. - CGRect beginBounds = {CGPointZero, beginFrame.size}; - CGRect endBounds = {CGPointZero, endFrame.size}; - frameAnimation = FrameAnimationMake(self.maskLayer, beginBounds, endBounds); - frameAnimation.duration = duration; - frameAnimation.timingFunction = timingFunction; - NSDictionary* attributes = @{NSFontAttributeName : self.font}; - CGFloat beginGradientPercentage = - [[self class] gradientPercentageForText:self.text - withAttributes:attributes - inBounds:beginBounds]; - CGFloat endGradientPercentage = - [[self class] gradientPercentageForText:self.text - withAttributes:attributes - inBounds:endBounds]; - CABasicAnimation* gradientAnimation = - [CABasicAnimation animationWithKeyPath:@"locations"]; - gradientAnimation.fromValue = @[ @(beginGradientPercentage), @(1.0) ]; - gradientAnimation.toValue = @[ @(endGradientPercentage), @(1.0) ]; - gradientAnimation.duration = duration; - gradientAnimation.timingFunction = timingFunction; - CAAnimation* animation = - AnimationGroupMake(@[ frameAnimation, gradientAnimation ]); - [self.maskLayer addAnimation:animation - forKey:kFadeTruncatedLabelAnimationKey]; -} - -- (void)reverseAnimations { - // Reverse the animations, but leave the animation label in place. - ReverseAnimationsForKeyForLayers(kFadeTruncatedLabelAnimationKey, - @[ self.layer, self.maskLayer ]); -} - -- (void)cleanUpAnimations { - // Remove animation label and redraw. - [self.animationLabel removeFromSuperview]; - self.animationLabel = nil; - [self setNeedsDisplay]; - // Remove animations from layers. - RemoveAnimationForKeyFromLayers(kFadeTruncatedLabelAnimationKey, - @[ self.layer, self.maskLayer ]); -} - -#pragma mark - Class methods - -+ (CGFloat)gradientPercentageForText:(NSString*)text - withAttributes:(NSDictionary*)attributes - inBounds:(CGRect)bounds { - CGSize textSize = - ui::AlignSizeToUpperPixel([text sizeWithAttributes:attributes]); - CGFloat gradientBeginPercentage = 1.0; - if (textSize.width > bounds.size.width) { - // Fade width is chosen to match GTMFadeTruncatingLabel. - CGFloat fadeWidth = - std::min<CGFloat>(bounds.size.height * 2, floor(bounds.size.width / 4)); - gradientBeginPercentage = - (bounds.size.width - fadeWidth) / bounds.size.width; - } - return gradientBeginPercentage; -} - -+ (CAGradientLayer*)maskLayerForText:(NSString*)text - withAttributes:(NSDictionary*)attributes - inBounds:(CGRect)bounds { - CAGradientLayer* maskLayer = [CAGradientLayer layer]; - maskLayer.bounds = bounds; - maskLayer.colors = @[ - reinterpret_cast<id>([UIColor blackColor].CGColor), - reinterpret_cast<id>([UIColor clearColor].CGColor) - ]; - maskLayer.startPoint = CGPointMake(0.0, 0.5); - maskLayer.endPoint = CGPointMake(1.0, 0.5); - CGFloat gradientBeginPercentage = [self gradientPercentageForText:text - withAttributes:attributes - inBounds:bounds]; - maskLayer.locations = @[ @(gradientBeginPercentage), @(1.0) ]; - return maskLayer; -} - -@end
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm index 4dc366b..92f19f9 100644 --- a/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm +++ b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
@@ -12,7 +12,6 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/find_in_page/find_in_page_controller.h" #import "ios/chrome/browser/find_in_page/find_in_page_model.h" -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/find_bar/find_bar_view.h" #import "ios/chrome/browser/ui/image_util/image_util.h"
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm index 94612bc95..0bb0a94 100644 --- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm +++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm
@@ -7,7 +7,6 @@ #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/strings/sys_string_conversions.h" -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" #include "ios/chrome/browser/ui/fancy_ui/primary_action_button.h" #include "ios/chrome/browser/ui/first_run/first_run_util.h" #import "ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h" @@ -28,6 +27,26 @@ namespace { +// An enum type to describe size classes. +typedef NS_ENUM(NSInteger, SizeClassIdiom) { + COMPACT = 0, + REGULAR, + UNSPECIFIED, + SIZE_CLASS_COUNT = UNSPECIFIED, +}; + +// Returns the SizeClassIdiom corresponding with |size_class|. +SizeClassIdiom GetSizeClassIdiom(UIUserInterfaceSizeClass size_class) { + switch (size_class) { + case UIUserInterfaceSizeClassCompact: + return COMPACT; + case UIUserInterfaceSizeClassRegular: + return REGULAR; + case UIUserInterfaceSizeClassUnspecified: + return UNSPECIFIED; + } +} + // Accessibility identifier for the checkbox button. NSString* const kUMAMetricsButtonAccessibilityIdentifier = @"UMAMetricsButtonAccessibilityIdentifier"; @@ -356,7 +375,7 @@ // The image is centered and laid out below |titleLabel| as specified by // kImageTopPadding. CGSize imageViewSize = self.imageView.bounds.size; - CGFloat imageViewTopPadding = kImageTopPadding[self.cr_heightSizeClass]; + CGFloat imageViewTopPadding = kImageTopPadding[[self heightSizeClassIdiom]]; self.imageView.frame = AlignRectOriginAndSizeToPixels(CGRectMake( (CGRectGetWidth(self.containerView.bounds) - imageViewSize.width) / 2.0, CGRectGetMaxY(self.titleLabel.frame) + imageViewTopPadding, @@ -424,7 +443,7 @@ [_TOSLabelLinkController setLinkColor:UIColorFromRGB(kLinkColorRGB)]; CGSize TOSLabelSize = [self.TOSLabel sizeThatFits:containerSize]; - CGFloat TOSLabelTopPadding = kTOSLabelTopPadding[self.cr_heightSizeClass]; + CGFloat TOSLabelTopPadding = kTOSLabelTopPadding[[self heightSizeClassIdiom]]; self.TOSLabel.frame = AlignRectOriginAndSizeToPixels( CGRectMake((containerSize.width - TOSLabelSize.width) / 2.0, CGRectGetMaxY(self.imageView.frame) + TOSLabelTopPadding, @@ -436,13 +455,14 @@ // button and below |TOSLabel| as specified by kOptInLabelPadding. CGSize checkBoxSize = [self.checkBoxButton imageForState:self.checkBoxButton.state].size; - CGFloat checkBoxPadding = kCheckBoxPadding[self.cr_widthSizeClass]; + CGFloat checkBoxPadding = kCheckBoxPadding[[self widthSizeClassIdiom]]; CGFloat optInLabelSidePadding = checkBoxSize.width + 2.0 * checkBoxPadding; CGSize optInLabelSize = [self.optInLabel sizeThatFits:CGSizeMake(CGRectGetWidth(self.containerView.bounds) - optInLabelSidePadding, CGFLOAT_MAX)]; - CGFloat optInLabelTopPadding = kOptInLabelPadding[self.cr_heightSizeClass]; + CGFloat optInLabelTopPadding = + kOptInLabelPadding[[self heightSizeClassIdiom]]; CGFloat optInLabelOriginX = base::i18n::IsRTL() ? 0.0f : optInLabelSidePadding; self.optInLabel.frame = AlignRectOriginAndSizeToPixels( @@ -459,7 +479,7 @@ // |optInLabel|. CGSize checkBoxSize = [self.checkBoxButton imageForState:self.checkBoxButton.state].size; - CGFloat checkBoxPadding = kCheckBoxPadding[self.cr_widthSizeClass]; + CGFloat checkBoxPadding = kCheckBoxPadding[[self widthSizeClassIdiom]]; CGSize checkBoxButtonSize = CGSizeMake(CGRectGetWidth(self.optInLabel.frame) + checkBoxSize.width + 2.0 * checkBoxPadding, @@ -487,7 +507,7 @@ CGSize containerViewSize = self.containerView.bounds.size; containerViewSize.height = CGRectGetMaxY(self.checkBoxButton.frame); - CGFloat padding = kOptInLabelPadding[self.cr_heightSizeClass]; + CGFloat padding = kOptInLabelPadding[[self heightSizeClassIdiom]]; CGFloat originY = fmin( (CGRectGetHeight(self.bounds) - containerViewSize.height) / 2.0, CGRectGetMinY(self.OKButton.frame) - padding - containerViewSize.height); @@ -501,7 +521,7 @@ // The OK button is laid out at the bottom of the view as specified by // kOKButtonBottomPadding. CGFloat OKButtonBottomPadding = - kOKButtonBottomPadding[self.cr_widthSizeClass]; + kOKButtonBottomPadding[[self widthSizeClassIdiom]]; CGSize OKButtonSize = self.OKButton.bounds.size; CGFloat bottomSafeArea = self.safeAreaInsets.bottom; self.OKButton.frame = AlignRectOriginAndSizeToPixels( @@ -529,14 +549,14 @@ - (void)configureTitleLabel { self.titleLabel.font = [[MDCTypography fontLoader] - regularFontOfSize:kTitleLabelFontSize[self.cr_widthSizeClass]]; + regularFontOfSize:kTitleLabelFontSize[[self widthSizeClassIdiom]]]; } - (void)configureImageView { CGFloat sideLength = self.imageView.image.size.width; - if (self.cr_widthSizeClass == COMPACT) { + if ([self widthSizeClassIdiom] == COMPACT) { sideLength = self.bounds.size.width * kAppLogoProportionMultiplier; - } else if (self.cr_heightSizeClass == COMPACT) { + } else if ([self heightSizeClassIdiom] == COMPACT) { sideLength = self.bounds.size.height * kAppLogoProportionMultiplier; } self.imageView.bounds = AlignRectOriginAndSizeToPixels( @@ -546,19 +566,20 @@ - (void)configureTOSLabel { self.TOSLabel.font = [[MDCTypography fontLoader] - regularFontOfSize:kTOSLabelFontSize[self.cr_widthSizeClass]]; - self.TOSLabel.cr_lineHeight = kTOSLabelLineHeight[self.cr_widthSizeClass]; + regularFontOfSize:kTOSLabelFontSize[[self widthSizeClassIdiom]]]; + self.TOSLabel.cr_lineHeight = kTOSLabelLineHeight[[self widthSizeClassIdiom]]; } - (void)configureOptInLabel { self.optInLabel.font = [[MDCTypography fontLoader] - regularFontOfSize:kOptInLabelFontSize[self.cr_widthSizeClass]]; - self.optInLabel.cr_lineHeight = kOptInLabelLineHeight[self.cr_widthSizeClass]; + regularFontOfSize:kOptInLabelFontSize[[self widthSizeClassIdiom]]]; + self.optInLabel.cr_lineHeight = + kOptInLabelLineHeight[[self widthSizeClassIdiom]]; } - (void)configureContainerView { CGFloat containerViewWidth = - self.cr_widthSizeClass == COMPACT + [self widthSizeClassIdiom] == COMPACT ? kContainerViewCompactWidthPercentage * CGRectGetWidth(self.bounds) : kContainerViewRegularWidth; self.containerView.frame = @@ -567,13 +588,30 @@ - (void)configureOKButton { UIFont* font = [[MDCTypography fontLoader] - mediumFontOfSize:kOKButtonTitleLabelFontSize[self.cr_widthSizeClass]]; + mediumFontOfSize:kOKButtonTitleLabelFontSize[[self widthSizeClassIdiom]]]; [self.OKButton setTitleFont:font forState:UIControlStateNormal]; CGSize size = [self.OKButton sizeThatFits:CGSizeMake(CGFLOAT_MAX, - kOKButtonHeight[self.cr_widthSizeClass])]; - [self.OKButton setBounds:CGRectMake(0, 0, size.width, - kOKButtonHeight[self.cr_widthSizeClass])]; + kOKButtonHeight[[self widthSizeClassIdiom]])]; + [self.OKButton + setBounds:CGRectMake(0, 0, size.width, + kOKButtonHeight[[self widthSizeClassIdiom]])]; +} + +- (SizeClassIdiom)widthSizeClassIdiom { + UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow; + UIUserInterfaceSizeClass sizeClass = self.traitCollection.horizontalSizeClass; + if (sizeClass == UIUserInterfaceSizeClassUnspecified) + sizeClass = keyWindow.traitCollection.horizontalSizeClass; + return GetSizeClassIdiom(sizeClass); +} + +- (SizeClassIdiom)heightSizeClassIdiom { + UIWindow* keyWindow = [UIApplication sharedApplication].keyWindow; + UIUserInterfaceSizeClass sizeClass = self.traitCollection.verticalSizeClass; + if (sizeClass == UIUserInterfaceSizeClassUnspecified) + sizeClass = keyWindow.traitCollection.verticalSizeClass; + return GetSizeClassIdiom(sizeClass); } #pragma mark -
diff --git a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn index 2d0231a4..ee0049a 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
@@ -17,6 +17,7 @@ "//ios/chrome/browser/infobars:public", "//ios/chrome/browser/passwords:public", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/infobars:infobars_ui", "//ios/chrome/browser/ui/infobars/banners", "//ios/chrome/browser/ui/infobars/modals",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm index de0df403..f07813a38 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
@@ -7,6 +7,8 @@ #include "base/strings/sys_string_conversions.h" #include "components/infobars/core/confirm_infobar_delegate.h" #include "ios/chrome/browser/infobars/infobar_controller_delegate.h" +#import "ios/chrome/browser/ui/fullscreen/animated_scoped_fullscreen_disabler.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" #import "ios/chrome/browser/ui/infobars/infobar_badge_ui_delegate.h" @@ -20,7 +22,11 @@ #endif @interface InfobarConfirmCoordinator () <InfobarBannerDelegate, - InfobarModalDelegate> + InfobarModalDelegate> { + // The AnimatedFullscreenDisable disables fullscreen by displaying the + // Toolbar/s when an Infobar banner is presented. + std::unique_ptr<AnimatedScopedFullscreenDisabler> animatedFullscreenDisabler_; +} // Delegate that holds the Infobar information and actions. @property(nonatomic, readonly) ConfirmInfoBarDelegate* confirmInfobarDelegate; @@ -38,6 +44,8 @@ @synthesize badgeDelegate = _badgeDelegate; // Property defined in InfobarCoordinating. @synthesize bannerTransitionDriver = _bannerTransitionDriver; +// Property defined in InfobarCoordinating. +@synthesize browserState = _browserState; // Property defined in InfobarUIDelegate. @synthesize delegate = _delegate; // Property defined in InfobarCoordinating. @@ -91,6 +99,14 @@ #pragma mark - InfobarCoordinating - (void)presentInfobarModalFrom:(UIViewController*)baseViewController { + // Make sure to display the Toolbar/Omnibox before presenting the Banner. + DCHECK(self.browserState); + animatedFullscreenDisabler_ = + std::make_unique<AnimatedScopedFullscreenDisabler>( + FullscreenControllerFactory::GetInstance()->GetForBrowserState( + self.browserState)); + animatedFullscreenDisabler_->StartAnimation(); + self.modalTransitionDriver = [[InfobarModalTransitionDriver alloc] initWithTransitionMode:InfobarModalTransitionBase]; [self presentInfobarModalFrom:baseViewController @@ -113,6 +129,10 @@ } } +- (void)setBrowserState:(ios::ChromeBrowserState*)browserState { + _browserState = browserState; +} + #pragma mark - InfobarBannerDelegate - (void)bannerInfobarButtonWasPressed:(id)sender { @@ -127,6 +147,7 @@ completion:^{ [self.badgeDelegate infobarBannerWasDismissed]; self.bannerTransitionDriver = nil; + animatedFullscreenDisabler_ = nullptr; }]; }
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h index ebb6360..13b7382 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_coordinating.h
@@ -8,6 +8,9 @@ @class InfobarBannerTransitionDriver; @class InfobarModalTransitionDriver; @protocol InfobarBadgeUIDelegate; +namespace ios { +class ChromeBrowserState; +} // InfobarCoordinating defines common methods for all Infobar Coordinators. @protocol InfobarCoordinating @@ -28,6 +31,9 @@ // Handles any followup actions to Infobar UI events. @property(nonatomic, weak) id<InfobarBadgeUIDelegate> badgeDelegate; +// The ChromeBrowserState owned by the Coordinator. +@property(nonatomic, assign) ios::ChromeBrowserState* browserState; + // The Coordinator's BannerViewController, can be nil. - (UIViewController*)bannerViewController;
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm index 9e52747e..2e106646 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -7,6 +7,8 @@ #include "base/strings/sys_string_conversions.h" #include "ios/chrome/browser/infobars/infobar_controller_delegate.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h" +#import "ios/chrome/browser/ui/fullscreen/animated_scoped_fullscreen_disabler.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" #import "ios/chrome/browser/ui/infobars/infobar_badge_ui_delegate.h" @@ -22,7 +24,11 @@ #endif @interface InfobarPasswordCoordinator () <InfobarBannerDelegate, - InfobarModalDelegate> + InfobarModalDelegate> { + // The AnimatedFullscreenDisable disables fullscreen by displaying the + // Toolbar/s when an Infobar banner is presented. + std::unique_ptr<AnimatedScopedFullscreenDisabler> animatedFullscreenDisabler_; +} // Delegate that holds the Infobar information and actions. @property(nonatomic, readonly) @@ -42,6 +48,8 @@ @synthesize badgeDelegate = _badgeDelegate; // Property defined in InfobarCoordinating. @synthesize bannerTransitionDriver = _bannerTransitionDriver; +// Property defined in InfobarCoordinating. +@synthesize browserState = _browserState; // Property defined in InfobarUIDelegate. @synthesize delegate = _delegate; // Property defined in InfobarCoordinating. @@ -107,6 +115,14 @@ } - (void)presentInfobarBannerFrom:(UIViewController*)baseViewController { + // Make sure to display the Toolbar/Omnibox before presenting the Banner. + DCHECK(self.browserState); + animatedFullscreenDisabler_ = + std::make_unique<AnimatedScopedFullscreenDisabler>( + FullscreenControllerFactory::GetInstance()->GetForBrowserState( + self.browserState)); + animatedFullscreenDisabler_->StartAnimation(); + [self.bannerViewController setModalPresentationStyle:UIModalPresentationCustom]; self.bannerTransitionDriver = [[InfobarBannerTransitionDriver alloc] init]; @@ -122,6 +138,10 @@ } } +- (void)setBrowserState:(ios::ChromeBrowserState*)browserState { + _browserState = browserState; +} + #pragma mark - InfobarBannerDelegate - (void)bannerInfobarButtonWasPressed:(UIButton*)sender { @@ -136,6 +156,7 @@ completion:^{ [self.badgeDelegate infobarBannerWasDismissed]; self.bannerTransitionDriver = nil; + animatedFullscreenDisabler_ = nullptr; }]; }
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm index 3a8e050..6ac641e 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -154,6 +154,7 @@ // Present the InfobarBanner, and set the Coordinator and View hierarchies. [infobarCoordinator start]; infobarCoordinator.badgeDelegate = self.mediator; + infobarCoordinator.browserState = self.browserState; [infobarCoordinator presentInfobarBannerFrom:self.baseViewController]; self.infobarViewController = [infobarCoordinator bannerViewController]; [self.childCoordinators addObject:infobarCoordinator];
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index 6df82a64..788e280 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -4,6 +4,7 @@ source_set("popup") { sources = [ + "omnibox_popup_base_view_controller+internal.h", "omnibox_popup_base_view_controller.h", "omnibox_popup_base_view_controller.mm", "omnibox_popup_coordinator.h",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller+internal.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller+internal.h new file mode 100644 index 0000000..2b726e75 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller+internal.h
@@ -0,0 +1,35 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_BASE_VIEW_CONTROLLER_INTERNAL_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_BASE_VIEW_CONTROLLER_INTERNAL_H_ + +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" + +// Interface defining protected methods on OmniboxPopupBaseViewController. +// +// TODO (crbug.com/943521): This is only for subclassing during migration of +// OmniboxPopupViewController and should be removed when that is done. +@interface OmniboxPopupBaseViewController (Internal) + +// Alignment of omnibox text. Popup text should match this alignment. +@property(nonatomic, assign) NSTextAlignment alignment; + +// Table view that displays the results. +@property(nonatomic, strong) UITableView* tableView; + +// Adjust the inset on the table view to prevent keyboard from overlapping the +// text. +- (void)updateContentInsetForKeyboard; + +// Hook for subclasses to update the table view after the matches have been +// processed. +- (void)updateTableViewWithAnimation:(BOOL)animation; + +// Action handler for when the button is tapped. +- (void)trailingButtonTapped:(id)sender; + +@end + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_BASE_VIEW_CONTROLLER_INTERNAL_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h index c9b496d..50e2621 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h
@@ -7,7 +7,51 @@ #import <UIKit/UIKit.h> -@interface OmniboxPopupBaseViewController : UIViewController +#import "ios/chrome/browser/ui/commands/omnibox_suggestion_commands.h" +#import "ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h" +#import "ios/chrome/browser/ui/omnibox/image_retriever.h" +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" +#include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h" + +@protocol ImageRetriever; + +// View controller used to display a list of omnibox autocomplete matches in the +// omnibox popup. +// It implements up/down arrow handling to highlight autocomplete results. +// Ideally, that should be implemented as key commands in this view controller, +// but UITextField has standard handlers for up/down arrows, so when the omnibox +// is the first responder, this view controller cannot receive these events. +// Hence the delegation. +@interface OmniboxPopupBaseViewController + : UIViewController <AutocompleteResultConsumer, + OmniboxSuggestionCommands, + UIScrollViewDelegate> + +// When enabled, this view controller will display shortcuts when no suggestions +// are available. When enabling this, |shortcutsViewController| must be set. +// This can be toggled at runtime, for example to only show shortcuts on regular +// pages and not show them on NTP. +@property(nonatomic, assign) BOOL shortcutsEnabled; +// The view controller to display when no suggestions is available. See also: +// |shortcutsEnabled|. +@property(nonatomic, weak) UIViewController* shortcutsViewController; + +@property(nonatomic, assign) BOOL incognito; +@property(nonatomic, weak) id<AutocompleteResultConsumerDelegate> delegate; +@property(nonatomic, weak) id<ImageRetriever> imageRetriever; + +// The cell with shortcuts to display when no results are available (only if +// this is enabled with |shortcutsEnabled|). Lazily instantiated. +@property(nonatomic, strong) UITableViewCell* shortcutsCell; + +@property(nonatomic, strong) NSArray<id<AutocompleteSuggestion>>* currentResult; + +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithNibName:(NSString*)nibNameOrNil + bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; + @end #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_BASE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.mm index 6197424c..bc692f8c 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.mm
@@ -3,10 +3,411 @@ // found in the LICENSE file. #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller+internal.h" + +#include "base/metrics/histogram_macros.h" +#include "base/time/time.h" +#include "ios/chrome/browser/ui/omnibox/omnibox_constants.h" +#include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row.h" +#include "ios/chrome/browser/ui/omnibox/popup/self_sizing_table_view.h" +#include "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h" +#include "ios/chrome/browser/ui/util/ui_util.h" +#include "ios/chrome/browser/ui/util/uikit_ui_util.h" +#include "ios/chrome/common/ui_util/constraints_ui_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +namespace { +const CGFloat kTopAndBottomPadding = 8.0; +UIColor* BackgroundColorTablet() { + return [UIColor whiteColor]; +} +UIColor* BackgroundColorPhone() { + return [UIColor colorWithRed:(245 / 255.0) + green:(245 / 255.0) + blue:(246 / 255.0) + alpha:1.0]; +} +UIColor* BackgroundColorIncognito() { + return [UIColor colorWithRed:(50 / 255.0) + green:(50 / 255.0) + blue:(50 / 255.0) + alpha:1.0]; +} +} // namespace + +@interface OmniboxPopupBaseViewController () <UITableViewDelegate, + UITableViewDataSource> + +#pragma mark Redeclaration of Internal properties + +@property(nonatomic, assign) NSTextAlignment alignment; +@property(nonatomic, strong) UITableView* tableView; + +#pragma mark Private properties + +// Index path of currently highlighted row. The rows can be highlighted by +// tapping and holding on them or by using arrow keys on a hardware keyboard. +@property(nonatomic, strong) NSIndexPath* highlightedIndexPath; + +// Flag that enables forwarding scroll events to the delegate. Disabled while +// updating the cells to avoid defocusing the omnibox when the omnibox popup +// changes size and table view issues a scroll event. +@property(nonatomic, assign) BOOL forwardsScrollEvents; + +// The height of the keyboard. Used to determine the content inset for the +// scroll view. +@property(nonatomic, assign) CGFloat keyboardHeight; + +// Time the view appeared on screen. Used to record a metric of how long this +// view controller was on screen. +@property(nonatomic, assign) base::TimeTicks viewAppearanceTime; + +@end + @implementation OmniboxPopupBaseViewController + +- (instancetype)init { + if (self = [super initWithNibName:nil bundle:nil]) { + _forwardsScrollEvents = YES; + if (IsIPadIdiom()) { + // The iPad keyboard can cover some of the rows of the scroll view. The + // scroll view's content inset may need to be updated when the keyboard is + // displayed. + NSNotificationCenter* defaultCenter = + [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver:self + selector:@selector(keyboardDidShow:) + name:UIKeyboardDidShowNotification + object:nil]; + } + } + return self; +} + +- (void)loadView { + self.tableView = + [[SelfSizingTableView alloc] initWithFrame:CGRectZero + style:UITableViewStylePlain]; + self.tableView.delegate = self; + self.tableView.dataSource = self; + self.view = self.tableView; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.tableView.insetsContentViewsToSafeArea = YES; + + // Initialize the same size as the parent view, autoresize will correct this. + [self.view setFrame:CGRectZero]; + if (self.incognito) { + self.view.backgroundColor = BackgroundColorIncognito(); + } else { + self.view.backgroundColor = + IsIPadIdiom() ? BackgroundColorTablet() : BackgroundColorPhone(); + } + + [self.view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight)]; + + // Table configuration. + self.tableView.allowsMultipleSelectionDuringEditing = NO; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + self.tableView.separatorInset = UIEdgeInsetsZero; + if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) { + [self.tableView setLayoutMargins:UIEdgeInsetsZero]; + } + self.tableView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; + [self.tableView setContentInset:UIEdgeInsetsMake(kTopAndBottomPadding, 0, + kTopAndBottomPadding, 0)]; + self.tableView.estimatedRowHeight = 0; +} + +- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + + ToolbarConfiguration* configuration = [[ToolbarConfiguration alloc] + initWithStyle:self.incognito ? INCOGNITO : NORMAL]; + + if (IsRegularXRegularSizeClass(self)) { + self.view.backgroundColor = configuration.backgroundColor; + } else { + self.view.backgroundColor = [UIColor clearColor]; + } +} + +#pragma mark - View lifecycle + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.viewAppearanceTime = base::TimeTicks::Now(); +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + UMA_HISTOGRAM_MEDIUM_TIMES("MobileOmnibox.PopupOpenDuration", + base::TimeTicks::Now() - self.viewAppearanceTime); +} + +#pragma mark - Properties accessors + +- (void)setShortcutsEnabled:(BOOL)shortcutsEnabled { + if (shortcutsEnabled == _shortcutsEnabled) { + return; + } + + DCHECK(!shortcutsEnabled || self.shortcutsViewController); + + _shortcutsEnabled = shortcutsEnabled; + [self.tableView reloadData]; +} + +- (UITableViewCell*)shortcutsCell { + if (_shortcutsCell) { + return _shortcutsCell; + } + + DCHECK(self.shortcutsEnabled); + DCHECK(self.shortcutsViewController); + + UITableViewCell* cell = [[UITableViewCell alloc] init]; + _shortcutsCell = cell; + cell.backgroundColor = [UIColor clearColor]; + [self.shortcutsViewController willMoveToParentViewController:self]; + [self addChildViewController:self.shortcutsViewController]; + [cell.contentView addSubview:self.shortcutsViewController.view]; + self.shortcutsViewController.view.translatesAutoresizingMaskIntoConstraints = + NO; + AddSameConstraints(self.shortcutsViewController.view, cell.contentView); + [self.shortcutsViewController didMoveToParentViewController:self]; + cell.accessibilityIdentifier = kShortcutsAccessibilityIdentifier; + return cell; +} + +#pragma mark - AutocompleteResultConsumer + +- (void)updateMatches:(NSArray<id<AutocompleteSuggestion>>*)result + withAnimation:(BOOL)animation { + self.forwardsScrollEvents = NO; + // Reset highlight state. + if (self.highlightedIndexPath) { + [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; + self.highlightedIndexPath = nil; + } + + self.currentResult = result; + + [self updateTableViewWithAnimation:animation]; + self.forwardsScrollEvents = YES; +} + +- (void)keyboardDidShow:(NSNotification*)notification { + NSDictionary* keyboardInfo = [notification userInfo]; + NSValue* keyboardFrameValue = + [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey]; + self.keyboardHeight = CurrentKeyboardHeight(keyboardFrameValue); + if (self.tableView.contentSize.height > 0) + [self updateContentInsetForKeyboard]; +} + +- (void)highlightRowAtIndexPath:(NSIndexPath*)indexPath { + UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; + [cell setHighlighted:YES animated:NO]; +} + +- (void)unhighlightRowAtIndexPath:(NSIndexPath*)indexPath { + UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; + [cell setHighlighted:NO animated:NO]; +} + +// Set text alignment for popup cells. +- (void)setTextAlignment:(NSTextAlignment)alignment { + self.alignment = alignment; +} + +#pragma mark - OmniboxSuggestionCommands + +- (void)highlightNextSuggestion { + NSIndexPath* path = self.highlightedIndexPath; + if (path == nil) { + // When nothing is highlighted, pressing Up Arrow doesn't do anything. + return; + } + + if (path.row == 0) { + // Can't move up from first row. Call the delegate again so that the inline + // autocomplete text is set again (in case the user exited the inline + // autocomplete). + [self.delegate autocompleteResultConsumer:self + didHighlightRow:self.highlightedIndexPath.row]; + return; + } + + [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; + self.highlightedIndexPath = + [NSIndexPath indexPathForRow:self.highlightedIndexPath.row - 1 + inSection:0]; + [self highlightRowAtIndexPath:self.highlightedIndexPath]; + + [self.delegate autocompleteResultConsumer:self + didHighlightRow:self.highlightedIndexPath.row]; +} + +- (void)highlightPreviousSuggestion { + if (!self.highlightedIndexPath) { + // Initialize the highlighted row to -1, so that pressing down when nothing + // is highlighted highlights the first row (at index 0). + self.highlightedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0]; + } + + NSIndexPath* path = self.highlightedIndexPath; + + if (path.row == [self.tableView numberOfRowsInSection:0] - 1) { + // Can't go below last row. Call the delegate again so that the inline + // autocomplete text is set again (in case the user exited the inline + // autocomplete). + [self.delegate autocompleteResultConsumer:self + didHighlightRow:self.highlightedIndexPath.row]; + return; + } + + // There is a row below, move highlight there. + [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; + self.highlightedIndexPath = + [NSIndexPath indexPathForRow:self.highlightedIndexPath.row + 1 + inSection:0]; + [self highlightRowAtIndexPath:self.highlightedIndexPath]; + + [self.delegate autocompleteResultConsumer:self + didHighlightRow:self.highlightedIndexPath.row]; +} + +- (void)keyCommandReturn { + [self.tableView selectRowAtIndexPath:self.highlightedIndexPath + animated:YES + scrollPosition:UITableViewScrollPositionNone]; +} + +#pragma mark - Table view delegate + +- (BOOL)tableView:(UITableView*)tableView + shouldHighlightRowAtIndexPath:(NSIndexPath*)indexPath { + if (self.shortcutsEnabled && indexPath.row == 0 && + self.currentResult.count == 0) { + return NO; + } + + return YES; +} + +- (void)tableView:(UITableView*)tableView + didSelectRowAtIndexPath:(NSIndexPath*)indexPath { + DCHECK_EQ(0U, (NSUInteger)indexPath.section); + DCHECK_LT((NSUInteger)indexPath.row, self.currentResult.count); + NSUInteger row = indexPath.row; + + // Crash reports tell us that |row| is sometimes indexed past the end of + // the results array. In those cases, just ignore the request and return + // early. See b/5813291. + if (row >= self.currentResult.count) + return; + [self.delegate autocompleteResultConsumer:self didSelectRow:row]; +} + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView*)scrollView { + // TODO(crbug.com/733650): Default to the dragging check once it's been tested + // on trunk. + if (!scrollView.dragging) + return; + + // TODO(crbug.com/911534): The following call chain ultimately just dismisses + // the keyboard, but involves many layers of plumbing, and should be + // refactored. + if (self.forwardsScrollEvents) + [self.delegate autocompleteResultConsumerDidScroll:self]; +} + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView*)tableView + numberOfRowsInSection:(NSInteger)section { + DCHECK_EQ(0, section); + if (self.shortcutsEnabled && self.currentResult.count == 0) { + return 1; + } + return self.currentResult.count; +} +// Customize the appearance of table view cells. +- (UITableViewCell*)tableView:(UITableView*)tableView + cellForRowAtIndexPath:(NSIndexPath*)indexPath { + return nil; +} + +- (BOOL)tableView:(UITableView*)tableView + canEditRowAtIndexPath:(NSIndexPath*)indexPath { + DCHECK_EQ(0U, (NSUInteger)indexPath.section); + + if (self.shortcutsEnabled && indexPath.row == 0 && + self.currentResult.count == 0) { + return NO; + } + + // iOS doesn't check -numberOfRowsInSection before checking + // -canEditRowAtIndexPath in a reload call. If |indexPath.row| is too large, + // simple return |NO|. + if ((NSUInteger)indexPath.row >= self.currentResult.count) + return NO; + + return [self.currentResult[indexPath.row] supportsDeletion]; +} + +- (void)tableView:(UITableView*)tableView + commitEditingStyle:(UITableViewCellEditingStyle)editingStyle + forRowAtIndexPath:(NSIndexPath*)indexPath { + DCHECK_EQ(0U, (NSUInteger)indexPath.section); + DCHECK_LT((NSUInteger)indexPath.row, self.currentResult.count); + if (editingStyle == UITableViewCellEditingStyleDelete) { + [self.delegate autocompleteResultConsumer:self + didSelectRowForDeletion:indexPath.row]; + } +} + +#pragma mark - Internal API methods + +- (void)updateContentInsetForKeyboard { + CGRect absoluteRect = + [self.tableView convertRect:self.tableView.bounds + toCoordinateSpace:UIScreen.mainScreen.coordinateSpace]; + CGFloat screenHeight = CurrentScreenHeight(); + CGFloat bottomInset = screenHeight - self.tableView.contentSize.height - + _keyboardHeight - absoluteRect.origin.y - + kTopAndBottomPadding * 2; + bottomInset = MAX(kTopAndBottomPadding, -bottomInset); + self.tableView.contentInset = + UIEdgeInsetsMake(kTopAndBottomPadding, 0, bottomInset, 0); + self.tableView.scrollIndicatorInsets = self.tableView.contentInset; +} + +- (void)updateTableViewWithAnimation:(BOOL)animation { + // for subclassing +} + +#pragma mark Action for append UIButton + +- (void)trailingButtonTapped:(id)sender { + NSUInteger row = [sender tag]; + [self.delegate autocompleteResultConsumer:self + didTapTrailingButtonForRow:row]; +} + @end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm index 91f3d15..b91b062 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_coordinator.mm
@@ -29,7 +29,7 @@ } @property(nonatomic, strong) - OmniboxPopupLegacyViewController* popupViewController; + OmniboxPopupBaseViewController* popupViewController; @property(nonatomic, strong) OmniboxPopupMediator* mediator; @property(nonatomic, strong) ShortcutsCoordinator* shortcutsCoordinator;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h index aa14d4c..89e54ea 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h
@@ -10,38 +10,7 @@ #import "ios/chrome/browser/ui/omnibox/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" -@protocol ImageRetriever; - -// View controller used to display a list of omnibox autocomplete matches in the -// omnibox popup. -// It implements up/down arrow handling to highlight autocomplete results. -// Ideally, that should be implemented as key commands in this view controller, -// but UITextField has standard handlers for up/down arrows, so when the omnibox -// is the first responder, this view controller cannot receive these events. -// Hence the delegation. -@interface OmniboxPopupLegacyViewController - : OmniboxPopupBaseViewController <AutocompleteResultConsumer, - OmniboxSuggestionCommands> - -// When enabled, this view controller will display shortcuts when no suggestions -// are available. When enabling this, |shortcutsViewController| must be set. -// This can be toggled at runtime, for example to only show shortcuts on regular -// pages and not show them on NTP. -@property(nonatomic, assign) BOOL shortcutsEnabled; -// The view controller to display when no suggestions is available. See also: -// |shortcutsEnabled|. -@property(nonatomic, weak) UIViewController* shortcutsViewController; - -@property(nonatomic, assign) BOOL incognito; -@property(nonatomic, weak) id<AutocompleteResultConsumerDelegate> delegate; -@property(nonatomic, weak) id<ImageRetriever> imageRetriever; - -- (instancetype)init NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (instancetype)initWithNibName:(NSString*)nibNameOrNil - bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; - +@interface OmniboxPopupLegacyViewController : OmniboxPopupBaseViewController @end #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_LEGACY_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm index df4e9d5..a9c8719 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.mm
@@ -3,6 +3,7 @@ // found in the LICENSE file. #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h" +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller+internal.h" #include <memory> @@ -33,129 +34,26 @@ const CGFloat kRowHeight = 48.0; const CGFloat kShortcutsRowHeight = 220; const CGFloat kAnswerRowHeight = 64.0; -const CGFloat kTopAndBottomPadding = 8.0; -UIColor* BackgroundColorTablet() { - return [UIColor whiteColor]; -} -UIColor* BackgroundColorPhone() { - return [UIColor colorWithRed:(245 / 255.0) - green:(245 / 255.0) - blue:(246 / 255.0) - alpha:1.0]; -} -UIColor* BackgroundColorIncognito() { - return [UIColor colorWithRed:(50 / 255.0) - green:(50 / 255.0) - blue:(50 / 255.0) - alpha:1.0]; -} } // namespace @interface OmniboxPopupLegacyViewController () < - OmniboxPopupRowAccessibilityDelegate, - UITableViewDelegate, - UITableViewDataSource> { - // Alignment of omnibox text. Popup text should match this alignment. - NSTextAlignment _alignment; - - NSArray<id<AutocompleteSuggestion>>* _currentResult; - + OmniboxPopupRowAccessibilityDelegate> { // Array containing the OmniboxPopupRow objects displayed in the view. NSArray* _rows; - - // The height of the keyboard. Used to determine the content inset for the - // scroll view. - CGFloat _keyboardHeight; } -// Index path of currently highlighted row. The rows can be highlighted by -// tapping and holding on them or by using arrow keys on a hardware keyboard. -@property(nonatomic, strong) NSIndexPath* highlightedIndexPath; - -@property(nonatomic, strong) UITableView* tableView; - -// Flag that enables forwarding scroll events to the delegate. Disabled while -// updating the cells to avoid defocusing the omnibox when the omnibox popup -// changes size and table view issues a scroll event. -@property(nonatomic, assign) BOOL forwardsScrollEvents; - -// The cell with shortcuts to display when no results are available (only if -// this is enabled with |shortcutsEnabled|). Lazily instantiated. -@property(nonatomic, strong) UITableViewCell* shortcutsCell; - -// Time the view appeared on screen. Used to record a metric of how long this -// view controller was on screen. -@property(nonatomic, assign) base::TimeTicks viewAppearanceTime; - @end @implementation OmniboxPopupLegacyViewController -@synthesize delegate = _delegate; -@synthesize incognito = _incognito; -@synthesize imageRetriever = _imageRetriever; -@synthesize highlightedIndexPath = _highlightedIndexPath; -@synthesize tableView = _tableView; -@synthesize forwardsScrollEvents = _forwardsScrollEvents; -#pragma mark - -#pragma mark Initialization - -- (instancetype)init { - if (self = [super initWithNibName:nil bundle:nil]) { - _forwardsScrollEvents = YES; - if (IsIPadIdiom()) { - // The iPad keyboard can cover some of the rows of the scroll view. The - // scroll view's content inset may need to be updated when the keyboard is - // displayed. - NSNotificationCenter* defaultCenter = - [NSNotificationCenter defaultCenter]; - [defaultCenter addObserver:self - selector:@selector(keyboardDidShow:) - name:UIKeyboardDidShowNotification - object:nil]; - } - } - return self; -} - -- (void)dealloc { - self.tableView.delegate = nil; -} - -- (void)loadView { - self.tableView = - [[SelfSizingTableView alloc] initWithFrame:CGRectZero - style:UITableViewStylePlain]; - self.tableView.delegate = self; - self.tableView.dataSource = self; - self.view = self.tableView; -} - -- (UIScrollView*)scrollView { - return (UIScrollView*)self.tableView; -} - (void)viewDidLoad { [super viewDidLoad]; - self.tableView.insetsContentViewsToSafeArea = YES; - - // Initialize the same size as the parent view, autoresize will correct this. - [self.view setFrame:CGRectZero]; - if (_incognito) { - self.view.backgroundColor = BackgroundColorIncognito(); - } else { - self.view.backgroundColor = - IsIPadIdiom() ? BackgroundColorTablet() : BackgroundColorPhone(); - } - - [self.view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - // Cache fonts needed for omnibox attributed string. NSMutableArray* rowsBuilder = [[NSMutableArray alloc] init]; for (int i = 0; i < kRowCount; i++) { OmniboxPopupRow* row = - [[OmniboxPopupRow alloc] initWithIncognito:_incognito]; + [[OmniboxPopupRow alloc] initWithIncognito:self.incognito]; row.accessibilityIdentifier = [NSString stringWithFormat:@"omnibox suggestion %i", i]; row.autoresizingMask = UIViewAutoresizingFlexibleWidth; @@ -169,19 +67,6 @@ row.rowHeight = kRowHeight; } _rows = [rowsBuilder copy]; - - // Table configuration. - self.tableView.allowsMultipleSelectionDuringEditing = NO; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - self.tableView.separatorInset = UIEdgeInsetsZero; - if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) { - [self.tableView setLayoutMargins:UIEdgeInsetsZero]; - } - self.tableView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - [self.tableView setContentInset:UIEdgeInsetsMake(kTopAndBottomPadding, 0, - kTopAndBottomPadding, 0)]; - self.tableView.estimatedRowHeight = 0; } - (void)didReceiveMemoryWarning { @@ -194,15 +79,6 @@ - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; [self layoutRows]; - - ToolbarConfiguration* configuration = [[ToolbarConfiguration alloc] - initWithStyle:self.incognito ? INCOGNITO : NORMAL]; - - if (IsRegularXRegularSizeClass(self)) { - self.view.backgroundColor = configuration.backgroundColor; - } else { - self.view.backgroundColor = [UIColor clearColor]; - } } - (void)viewWillTransitionToSize:(CGSize)size @@ -217,80 +93,6 @@ completion:nil]; } -#pragma mark - View lifecycle - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - self.viewAppearanceTime = base::TimeTicks::Now(); -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - UMA_HISTOGRAM_MEDIUM_TIMES("MobileOmnibox.PopupOpenDuration", - base::TimeTicks::Now() - self.viewAppearanceTime); -} - -#pragma mark - Properties accessors - -- (void)setIncognito:(BOOL)incognito { - DCHECK(!self.viewLoaded); - _incognito = incognito; -} - -- (void)setShortcutsEnabled:(BOOL)shortcutsEnabled { - if (shortcutsEnabled == _shortcutsEnabled) { - return; - } - - DCHECK(!shortcutsEnabled || self.shortcutsViewController); - - _shortcutsEnabled = shortcutsEnabled; - [self.tableView reloadData]; -} - -- (UITableViewCell*)shortcutsCell { - if (_shortcutsCell) { - return _shortcutsCell; - } - - DCHECK(self.shortcutsEnabled); - DCHECK(self.shortcutsViewController); - - UITableViewCell* cell = [[UITableViewCell alloc] init]; - _shortcutsCell = cell; - cell.backgroundColor = [UIColor clearColor]; - [self.shortcutsViewController willMoveToParentViewController:self]; - [self addChildViewController:self.shortcutsViewController]; - [cell.contentView addSubview:self.shortcutsViewController.view]; - self.shortcutsViewController.view.translatesAutoresizingMaskIntoConstraints = - NO; - AddSameConstraints(self.shortcutsViewController.view, cell.contentView); - [self.shortcutsViewController didMoveToParentViewController:self]; - cell.accessibilityIdentifier = kShortcutsAccessibilityIdentifier; - return cell; -} - -#pragma mark - AutocompleteResultConsumer - -- (void)updateMatches:(NSArray<id<AutocompleteSuggestion>>*)result - withAnimation:(BOOL)animation { - self.forwardsScrollEvents = NO; - // Reset highlight state. - if (self.highlightedIndexPath) { - [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; - self.highlightedIndexPath = nil; - } - - _currentResult = result; - [self layoutRows]; - - size_t size = _currentResult.count; - if (animation && size > 0) { - [self fadeInRows]; - } - self.forwardsScrollEvents = YES; -} - #pragma mark - #pragma mark Updating data and UI @@ -311,9 +113,10 @@ const CGFloat kAnswerImageLeftPadding = -1; const CGFloat kAnswerImageRightPadding = 4; const CGFloat kAnswerImageTopPadding = 2; - const BOOL alignmentRight = _alignment == NSTextAlignmentRight; + const BOOL alignmentRight = self.alignment == NSTextAlignmentRight; - BOOL LTRTextInRTLLayout = _alignment == NSTextAlignmentLeft && UseRTLLayout(); + BOOL LTRTextInRTLLayout = + self.alignment == NSTextAlignmentLeft && UseRTLLayout(); row.rowHeight = match.hasAnswer ? kAnswerRowHeight : kRowHeight; @@ -356,7 +159,7 @@ // layout logic there. UILabel* detailTextLabel = match.hasAnswer ? row.detailAnswerLabel : row.detailTruncatingLabel; - [detailTextLabel setTextAlignment:_alignment]; + [detailTextLabel setTextAlignment:self.alignment]; // The width must be positive for CGContextRef to be valid. UIEdgeInsets safeAreaInsets = self.view.safeAreaInsets; @@ -385,7 +188,7 @@ [detailTextLabel setNeedsDisplay]; OmniboxPopupTruncatingLabel* textLabel = row.textTruncatingLabel; - [textLabel setTextAlignment:_alignment]; + [textLabel setTextAlignment:self.alignment]; LayoutRect textLabelLayout = LayoutRectMake(kTextCellLeadingPadding, CGRectGetWidth(rowBounds), 0, labelWidth, kTextLabelHeight); @@ -470,8 +273,17 @@ [textLabel setNeedsDisplay]; } +- (void)updateTableViewWithAnimation:(BOOL)animation { + [self layoutRows]; + + size_t size = self.currentResult.count; + if (animation && size > 0) { + [self fadeInRows]; + } +} + - (void)layoutRows { - size_t size = _currentResult.count; + size_t size = self.currentResult.count; [self.tableView reloadData]; [self.tableView beginUpdates]; @@ -479,7 +291,7 @@ OmniboxPopupRow* row = _rows[i]; if (i < size) { - [self updateRow:row withMatch:_currentResult[i]]; + [self updateRow:row withMatch:self.currentResult[i]]; row.hidden = NO; } else { row.hidden = YES; @@ -491,29 +303,6 @@ [self updateContentInsetForKeyboard]; } -- (void)keyboardDidShow:(NSNotification*)notification { - NSDictionary* keyboardInfo = [notification userInfo]; - NSValue* keyboardFrameValue = - [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey]; - _keyboardHeight = CurrentKeyboardHeight(keyboardFrameValue); - if (self.tableView.contentSize.height > 0) - [self updateContentInsetForKeyboard]; -} - -- (void)updateContentInsetForKeyboard { - CGRect absoluteRect = - [self.tableView convertRect:self.tableView.bounds - toCoordinateSpace:UIScreen.mainScreen.coordinateSpace]; - CGFloat screenHeight = CurrentScreenHeight(); - CGFloat bottomInset = screenHeight - self.tableView.contentSize.height - - _keyboardHeight - absoluteRect.origin.y - - kTopAndBottomPadding * 2; - bottomInset = MAX(kTopAndBottomPadding, -bottomInset); - self.tableView.contentInset = - UIEdgeInsetsMake(kTopAndBottomPadding, 0, bottomInset, 0); - self.tableView.scrollIndicatorInsets = self.tableView.contentInset; -} - - (void)fadeInRows { [CATransaction begin]; [CATransaction @@ -545,215 +334,51 @@ [CATransaction commit]; } -- (void)highlightRowAtIndexPath:(NSIndexPath*)indexPath { - UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; - [cell setHighlighted:YES animated:NO]; -} - -- (void)unhighlightRowAtIndexPath:(NSIndexPath*)indexPath { - UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]; - [cell setHighlighted:NO animated:NO]; -} - -#pragma mark - -#pragma mark Action for append UIButton - -- (void)trailingButtonTapped:(id)sender { - NSUInteger row = [sender tag]; - [self.delegate autocompleteResultConsumer:self - didTapTrailingButtonForRow:row]; -} - #pragma mark - #pragma mark UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView*)scrollView { + [super scrollViewDidScroll:scrollView]; + // TODO(crbug.com/733650): Default to the dragging check once it's been tested // on trunk. if (!scrollView.dragging) return; - // TODO(crbug.com/911534): The following call chain ultimately just dismisses - // the keyboard, but involves many layers of plumbing, and should be - // refactored. - if (self.forwardsScrollEvents) - [self.delegate autocompleteResultConsumerDidScroll:self]; - for (OmniboxPopupRow* row in _rows) { row.highlighted = NO; } } -// Set text alignment for popup cells. -- (void)setTextAlignment:(NSTextAlignment)alignment { - _alignment = alignment; -} - -#pragma mark - -#pragma mark OmniboxSuggestionCommands - -- (void)highlightNextSuggestion { - NSIndexPath* path = self.highlightedIndexPath; - if (path == nil) { - // When nothing is highlighted, pressing Up Arrow doesn't do anything. - return; - } - - if (path.row == 0) { - // Can't move up from first row. Call the delegate again so that the inline - // autocomplete text is set again (in case the user exited the inline - // autocomplete). - [self.delegate autocompleteResultConsumer:self - didHighlightRow:self.highlightedIndexPath.row]; - return; - } - - [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; - self.highlightedIndexPath = - [NSIndexPath indexPathForRow:self.highlightedIndexPath.row - 1 - inSection:0]; - [self highlightRowAtIndexPath:self.highlightedIndexPath]; - - [self.delegate autocompleteResultConsumer:self - didHighlightRow:self.highlightedIndexPath.row]; -} - -- (void)highlightPreviousSuggestion { - if (!self.highlightedIndexPath) { - // Initialize the highlighted row to -1, so that pressing down when nothing - // is highlighted highlights the first row (at index 0). - self.highlightedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0]; - } - - NSIndexPath* path = self.highlightedIndexPath; - - if (path.row == [self.tableView numberOfRowsInSection:0] - 1) { - // Can't go below last row. Call the delegate again so that the inline - // autocomplete text is set again (in case the user exited the inline - // autocomplete). - [self.delegate autocompleteResultConsumer:self - didHighlightRow:self.highlightedIndexPath.row]; - return; - } - - // There is a row below, move highlight there. - [self unhighlightRowAtIndexPath:self.highlightedIndexPath]; - self.highlightedIndexPath = - [NSIndexPath indexPathForRow:self.highlightedIndexPath.row + 1 - inSection:0]; - [self highlightRowAtIndexPath:self.highlightedIndexPath]; - - [self.delegate autocompleteResultConsumer:self - didHighlightRow:self.highlightedIndexPath.row]; -} - -- (void)keyCommandReturn { - [self.tableView selectRowAtIndexPath:self.highlightedIndexPath - animated:YES - scrollPosition:UITableViewScrollPositionNone]; -} - -#pragma mark - -#pragma mark Table view delegate - -- (BOOL)tableView:(UITableView*)tableView - shouldHighlightRowAtIndexPath:(NSIndexPath*)indexPath { - if (self.shortcutsEnabled && indexPath.row == 0 && - _currentResult.count == 0) { - return NO; - } - - return YES; -} - -- (void)tableView:(UITableView*)tableView - didSelectRowAtIndexPath:(NSIndexPath*)indexPath { - DCHECK_EQ(0U, (NSUInteger)indexPath.section); - DCHECK_LT((NSUInteger)indexPath.row, _currentResult.count); - NSUInteger row = indexPath.row; - - // Crash reports tell us that |row| is sometimes indexed past the end of - // the results array. In those cases, just ignore the request and return - // early. See b/5813291. - if (row >= _currentResult.count) - return; - [self.delegate autocompleteResultConsumer:self didSelectRow:row]; -} - #pragma mark - #pragma mark Table view data source - (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath { if (self.shortcutsEnabled && indexPath.row == 0 && - _currentResult.count == 0) { + self.currentResult.count == 0) { return kShortcutsRowHeight; } DCHECK_EQ(0U, (NSUInteger)indexPath.section); - DCHECK_LT((NSUInteger)indexPath.row, _currentResult.count); + DCHECK_LT((NSUInteger)indexPath.row, self.currentResult.count); return ((OmniboxPopupRow*)(_rows[indexPath.row])).rowHeight; } -- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView*)tableView - numberOfRowsInSection:(NSInteger)section { - DCHECK_EQ(0, section); - if (self.shortcutsEnabled && _currentResult.count == 0) { - return 1; - } - return _currentResult.count; -} - // Customize the appearance of table view cells. - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { DCHECK_EQ(0U, (NSUInteger)indexPath.section); if (self.shortcutsEnabled && indexPath.row == 0 && - _currentResult.count == 0) { + self.currentResult.count == 0) { return self.shortcutsCell; } - DCHECK_LT((NSUInteger)indexPath.row, _currentResult.count); + DCHECK_LT((NSUInteger)indexPath.row, self.currentResult.count); return _rows[indexPath.row]; } -- (BOOL)tableView:(UITableView*)tableView - canEditRowAtIndexPath:(NSIndexPath*)indexPath { - DCHECK_EQ(0U, (NSUInteger)indexPath.section); - - if (self.shortcutsEnabled && indexPath.row == 0 && - _currentResult.count == 0) { - return NO; - } - - // iOS doesn't check -numberOfRowsInSection before checking - // -canEditRowAtIndexPath in a reload call. If |indexPath.row| is too large, - // simple return |NO|. - if ((NSUInteger)indexPath.row >= _currentResult.count) - return NO; - - return [_currentResult[indexPath.row] supportsDeletion]; -} - -- (void)tableView:(UITableView*)tableView - commitEditingStyle:(UITableViewCellEditingStyle)editingStyle - forRowAtIndexPath:(NSIndexPath*)indexPath { - DCHECK_EQ(0U, (NSUInteger)indexPath.section); - DCHECK_LT((NSUInteger)indexPath.row, _currentResult.count); - if (editingStyle == UITableViewCellEditingStyleDelete) { - // The delete button never disappears if you don't call this after a tap. - // It doesn't seem to be required anywhere else. - [_rows[indexPath.row] prepareForReuse]; - [self.delegate autocompleteResultConsumer:self - didSelectRowForDeletion:indexPath.row]; - } -} - #pragma mark - private - (BOOL)showsLeadingIcons {
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm index 4d17b6f..1c486e6 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm
@@ -5,7 +5,6 @@ #import "ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.h" #include "base/logging.h" -#import "ios/chrome/browser/ui/UIView+SizeClassSupport.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_animator.h" #import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller+subclassing.h"
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h index faef9f1..4f15bc8 100644 --- a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h +++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h
@@ -7,7 +7,7 @@ #include <UIKit/UIKit.h> -@class OmniboxPopupLegacyViewController; +@class OmniboxPopupBaseViewController; // In the main app, the |OmniboxPopupViewController| view is contained inside // another view (see |OmniboxPopupPresenter|). This class mimics that for @@ -15,10 +15,10 @@ @interface SCOmniboxPopupContainerViewController : UIViewController @property(nonatomic, strong) - OmniboxPopupLegacyViewController* popupViewController; + OmniboxPopupBaseViewController* popupViewController; - (instancetype)initWithPopupViewController: - (OmniboxPopupLegacyViewController*)popupViewController + (OmniboxPopupBaseViewController*)popupViewController NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm index 000d2e5..f886839 100644 --- a/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm +++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.mm
@@ -4,7 +4,7 @@ #import "ios/showcase/omnibox_popup/sc_omnibox_popup_container_view_controller.h" -#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_view_controller.h" +#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_base_view_controller.h" #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" @@ -15,7 +15,7 @@ @implementation SCOmniboxPopupContainerViewController - (instancetype)initWithPopupViewController: - (OmniboxPopupLegacyViewController*)popupViewController { + (OmniboxPopupBaseViewController*)popupViewController { self = [super initWithNibName:nil bundle:nil]; if (self) { _popupViewController = popupViewController;
diff --git a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm index a75a428..00ea775 100644 --- a/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm +++ b/ios/showcase/omnibox_popup/sc_omnibox_popup_coordinator.mm
@@ -17,7 +17,7 @@ @interface SCOmniboxPopupCoordinator () <Coordinator> @property(nonatomic, strong) - OmniboxPopupLegacyViewController* popupViewController; + OmniboxPopupBaseViewController* popupViewController; @property(nonatomic, strong) SCOmniboxPopupContainerViewController* containerViewController; @property(nonatomic, strong) SCOmniboxPopupMediator* mediator;
diff --git a/ios/web/common/BUILD.gn b/ios/web/common/BUILD.gn index 0b7c9014..1766611 100644 --- a/ios/web/common/BUILD.gn +++ b/ios/web/common/BUILD.gn
@@ -7,6 +7,13 @@ source_set("common") { sources = [ "crw_content_view.h", + "crw_web_view_content_view.h", + "crw_web_view_content_view.mm", + ] + + deps = [ + "//base", + "//ios/web/public:features", ] libs = [ "UIKit.framework" ]
diff --git a/ios/web/common/crw_web_view_content_view.h b/ios/web/common/crw_web_view_content_view.h new file mode 100644 index 0000000..d8c1ef6 --- /dev/null +++ b/ios/web/common/crw_web_view_content_view.h
@@ -0,0 +1,31 @@ +// 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_WEB_COMMON_CRW_WEB_VIEW_CONTENT_VIEW_H_ +#define IOS_WEB_COMMON_CRW_WEB_VIEW_CONTENT_VIEW_H_ + +#import "ios/web/common/crw_content_view.h" + +// Wraps a web vew in a CRWContentView. +@interface CRWWebViewContentView : CRWContentView + +// The webView passed to |-initWithWebView|. +@property(nonatomic, strong, readonly) UIView* webView; + +// Initializes the CRWWebViewContentView to display |webView|. +- (instancetype)initWithWebView:(UIView*)webView + scrollView:(UIScrollView*)scrollView + NS_DESIGNATED_INITIALIZER; + +// Available only for testing. +- (instancetype)initForTesting NS_DESIGNATED_INITIALIZER; + +// CRWWebViewContentViews should be initialized via |-initWithWebView: +// scrollView:|. +- (instancetype)initWithCoder:(NSCoder*)decoder NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +@end + +#endif // IOS_WEB_COMMON_CRW_WEB_VIEW_CONTENT_VIEW_H_
diff --git a/ios/web/web_state/ui/crw_web_view_content_view.mm b/ios/web/common/crw_web_view_content_view.mm similarity index 98% rename from ios/web/web_state/ui/crw_web_view_content_view.mm rename to ios/web/common/crw_web_view_content_view.mm index 72c35a2..54c043a 100644 --- a/ios/web/web_state/ui/crw_web_view_content_view.mm +++ b/ios/web/common/crw_web_view_content_view.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" #import <WebKit/WebKit.h> #include <cmath>
diff --git a/ios/web/interstitials/web_interstitial_impl.mm b/ios/web/interstitials/web_interstitial_impl.mm index 49d99bf..7f6dfc89 100644 --- a/ios/web/interstitials/web_interstitial_impl.mm +++ b/ios/web/interstitials/web_interstitial_impl.mm
@@ -8,11 +8,11 @@ #include "base/logging.h" #include "base/strings/sys_string_conversions.h" +#import "ios/web/common/crw_web_view_content_view.h" #import "ios/web/navigation/navigation_manager_impl.h" #import "ios/web/public/interstitials/web_interstitial_delegate.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/reload_type.h" -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" #import "ios/web/public/web_view_creation_util.h" #import "ios/web/web_state/web_state_impl.h" #import "net/base/mac/url_conversions.h"
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn index cbdd0d0..23112b7 100644 --- a/ios/web/public/BUILD.gn +++ b/ios/web/public/BUILD.gn
@@ -6,6 +6,7 @@ source_set("public") { public_deps = [ + ":features", ":user_agent", "//net", "//services/network/public/cpp", @@ -33,7 +34,6 @@ "favicon_status.h", "favicon_url.cc", "favicon_url.h", - "features.h", "interstitials/web_interstitial.h", "interstitials/web_interstitial_delegate.h", "java_script_dialog_callback.h", @@ -110,6 +110,18 @@ configs += [ "//build/config/compiler:enable_arc" ] } +source_set("features") { + sources = [ + "features.h", + ] + + deps = [ + "//base", + ] + + configs += [ "//build/config/compiler:enable_arc" ] +} + # This is a separate target as it is used by Cronet. source_set("user_agent") { deps = [
diff --git a/ios/web/public/test/fakes/test_web_view_content_view.h b/ios/web/public/test/fakes/test_web_view_content_view.h index 8b7a257..0a5c507c7 100644 --- a/ios/web/public/test/fakes/test_web_view_content_view.h +++ b/ios/web/public/test/fakes/test_web_view_content_view.h
@@ -5,7 +5,7 @@ #ifndef IOS_WEB_PUBLIC_TEST_FAKES_TEST_WEB_VIEW_CONTENT_VIEW_H_ #define IOS_WEB_PUBLIC_TEST_FAKES_TEST_WEB_VIEW_CONTENT_VIEW_H_ -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" // A test version of CRWWebViewContentView. @interface TestWebViewContentView : CRWWebViewContentView
diff --git a/ios/web/public/test/web_test_with_web_state.mm b/ios/web/public/test/web_test_with_web_state.mm index bf5b24c..cdcaeaa 100644 --- a/ios/web/public/test/web_test_with_web_state.mm +++ b/ios/web/public/test/web_test_with_web_state.mm
@@ -4,6 +4,8 @@ #import "ios/web/public/test/web_test_with_web_state.h" +#import <UIKit/UIKit.h> + #include "base/ios/ios_util.h" #include "base/message_loop/message_loop_current.h" #include "base/run_loop.h" @@ -54,11 +56,20 @@ web::WebState::CreateParams params(GetBrowserState()); web_state_ = web::WebState::Create(params); - // Force generation of child views; necessary for some tests. - web_state_->GetView(); + // The WKWebView must be present in the view hierarchy in order to prevent + // WebKit optimizations which may pause internal parts of the web view + // without notice. Work around this by adding the view directly. + // TODO:(crbug.com/944077) Remove this workaround once fixed in ios/web. + UIViewController* view_controller = + [[[UIApplication sharedApplication] keyWindow] rootViewController]; + [view_controller.view addSubview:web_state_->GetView()]; } void WebTestWithWebState::TearDown() { + if (web_state_) { + [web_state_->GetView() removeFromSuperview]; + } + DestroyWebState(); WebTest::TearDown(); }
diff --git a/ios/web/public/web_state/ui/crw_web_view_content_view.h b/ios/web/public/web_state/ui/crw_web_view_content_view.h index 4038def2..02546926 100644 --- a/ios/web/public/web_state/ui/crw_web_view_content_view.h +++ b/ios/web/public/web_state/ui/crw_web_view_content_view.h
@@ -1,31 +1,13 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. +// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_CONTENT_VIEW_H_ #define IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_CONTENT_VIEW_H_ -#import "ios/web/common/crw_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" -// Wraps a web vew in a CRWContentView. -@interface CRWWebViewContentView : CRWContentView - -// The webView passed to |-initWithWebView|. -@property(nonatomic, strong, readonly) UIView* webView; - -// Initializes the CRWWebViewContentView to display |webView|. -- (instancetype)initWithWebView:(UIView*)webView - scrollView:(UIScrollView*)scrollView - NS_DESIGNATED_INITIALIZER; - -// Available only for testing. -- (instancetype)initForTesting NS_DESIGNATED_INITIALIZER; - -// CRWWebViewContentViews should be initialized via |-initWithWebView: -// scrollView:|. -- (instancetype)initWithCoder:(NSCoder*)decoder NS_UNAVAILABLE; -- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - -@end +// TODO(crbug.com/942244): Remove all imports of this file. Clients should +// import ios/web/common/crw_web_view_content_view.h instead. #endif // IOS_WEB_PUBLIC_WEB_STATE_UI_CRW_WEB_VIEW_CONTENT_VIEW_H_
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn index b313788..ca254c59 100644 --- a/ios/web/web_state/ui/BUILD.gn +++ b/ios/web/web_state/ui/BUILD.gn
@@ -58,7 +58,6 @@ "crw_web_controller.mm", "crw_web_controller_container_view.h", "crw_web_controller_container_view.mm", - "crw_web_view_content_view.mm", "crw_web_view_proxy_impl.h", "crw_web_view_proxy_impl.mm", "crw_web_view_scroll_view_proxy.mm",
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 18e1757..e1f80ef 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -42,6 +42,7 @@ #include "crypto/symmetric_key.h" #import "ios/net/http_response_headers_util.h" #import "ios/web/common/crw_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" #import "ios/web/find_in_page/find_in_page_manager_impl.h" #include "ios/web/history_state_util.h" #import "ios/web/interstitials/web_interstitial_impl.h" @@ -74,7 +75,6 @@ #import "ios/web/public/web_state/ui/crw_context_menu_delegate.h" #import "ios/web/public/web_state/ui/crw_native_content.h" #import "ios/web/public/web_state/ui/crw_native_content_provider.h" -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" #include "ios/web/public/web_state/url_verification_constants.h" #include "ios/web/public/web_state/web_frame.h" @@ -4271,9 +4271,13 @@ requestURL.SchemeIs(url::kAboutScheme) || requestURL.SchemeIs(url::kBlobScheme); if (!webControllerCanShow) { - // Stop load if navigation is believed to be happening on the main frame. - if ([self isMainFrameNavigationAction:action]) - [self stopLoading]; + if (!web::features::StorePendingItemInContext()) { + if ([self isMainFrameNavigationAction:action]) { + [self stopLoading]; + } + } else { + allowLoad = NO; + } // Purge web view if last committed URL is different from the document // URL. This can happen if external URL was added to the navigation stack @@ -4331,6 +4335,14 @@ // inserting the webview. [self discardNonCommittedItemsIfLastCommittedWasNotNativeView]; + web::NavigationContextImpl* context = + [self contextForPendingMainFrameNavigationWithURL:requestURL]; + if (context) { + // Destroy associated pending item, because this will be the last + // WKWebView callback for this navigation context. + context->ReleaseItem(); + } + if (!_isBeingDestroyed && [self shouldClosePageOnNativeApplicationLoad]) { // Loading was started for user initiated navigations and should be // stopped because no other WKWebView callbacks are called.
diff --git a/ios/web/web_state/ui/crw_web_controller_container_view.mm b/ios/web/web_state/ui/crw_web_controller_container_view.mm index dae891b..25028192 100644 --- a/ios/web/web_state/ui/crw_web_controller_container_view.mm +++ b/ios/web/web_state/ui/crw_web_controller_container_view.mm
@@ -6,8 +6,8 @@ #include "base/logging.h" #import "ios/web/common/crw_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" #import "ios/web/public/web_state/ui/crw_native_content.h" -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" #import "ios/web/web_state/ui/crw_web_view_proxy_impl.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index 524dfb8..b4368f5c 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -17,6 +17,7 @@ #include "base/test/scoped_feature_list.h" #import "ios/testing/ocmock_complex_type_helper.h" #import "ios/web/common/crw_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" #import "ios/web/navigation/crw_session_controller.h" #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/navigation_manager_impl.h" @@ -38,7 +39,6 @@ #import "ios/web/public/test/web_view_content_test_util.h" #import "ios/web/public/web_state/ui/crw_native_content.h" #import "ios/web/public/web_state/ui/crw_native_content_provider.h" -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" #include "ios/web/public/web_state/url_verification_constants.h" #include "ios/web/public/web_state/web_state_observer.h" #import "ios/web/test/fakes/crw_fake_back_forward_list.h"
diff --git a/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm b/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm index 7e1d0efc..986917e 100644 --- a/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm +++ b/ios/web/web_state/ui/crw_web_view_content_view_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" +#import "ios/web/common/crw_web_view_content_view.h" #import <UIKit/UIKit.h>
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 6fee326d..72f2662 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -1130,23 +1130,25 @@ } // Tests failed navigation because URL scheme is not supported by WebState. -// TODO(crbug.com/917176): Actual callbacks for this navigation should not be -// different from callbacks observed in WebViewUnsupportedSchemeNavigation. TEST_P(WebStateObserverTest, WebStateUnsupportedSchemeNavigation) { GURL url("ftp://foo.test/"); // Perform a navigation to url with unsupported scheme. EXPECT_CALL(observer_, DidStartLoading(web_state())); EXPECT_CALL(observer_, DidStopLoading(web_state())); - - WebStatePolicyDecider::RequestInfo expected_request_info( - ui::PageTransition::PAGE_TRANSITION_TYPED, - /*target_main_frame=*/true, /*has_user_gesture=*/false); - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(expected_request_info))) - .WillOnce(Return(true)); + if (!web::features::StorePendingItemInContext()) { + WebStatePolicyDecider::RequestInfo expected_request_info( + ui::PageTransition::PAGE_TRANSITION_TYPED, + /*target_main_frame=*/true, /*has_user_gesture=*/false); + EXPECT_CALL(*decider_, + ShouldAllowRequest(_, RequestInfoMatch(expected_request_info))) + .WillOnce(Return(true)); + } test::LoadUrl(web_state(), url); ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state())); + + // Typed URL should be discarded after the navigation is rejected. + EXPECT_FALSE(web_state()->GetNavigationManager()->GetVisibleItem()); } // Tests web page reload navigation. @@ -2163,6 +2165,9 @@ EXPECT_CALL(observer_, DidStopLoading(web_state())); test::LoadUrl(web_state(), test_server_->GetURL("/echo")); ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state())); + + // Typed URL should be discarded after the navigation is rejected. + EXPECT_FALSE(web_state()->GetNavigationManager()->GetVisibleItem()); } // Tests rejecting the navigation from ShouldAllowResponse. PageLoaded callback
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 9939587..b347714 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -386,9 +386,16 @@ const base::Feature kMediaDrmPersistentLicense{ "MediaDrmPersistentLicense", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables MediaDrmOriginIdManager to provide preprovisioned origin IDs for +// MediaDrmBridge. If disabled, MediaDrmBridge will get unprovisioned origin IDs +// which will trigger provisioning process after MediaDrmBridge is created. +const base::Feature kMediaDrmPreprovisioning{"MediaDrmPreprovisioning", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Determines if MediaDrmOriginIdManager should attempt to pre-provision origin // IDs at startup (whenever a profile is loaded). Also used by tests that // disable it so that the tests can setup before pre-provisioning is done. +// Note: Have no effect if kMediaDrmPreprovisioning feature is disabled. const base::Feature kMediaDrmPreprovisioningAtStartup{ "MediaDrmPreprovisioningAtStartup", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 8266279..12b5e5b 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -144,6 +144,7 @@ MEDIA_EXPORT extern const base::Feature kVideoFullscreenOrientationLock; MEDIA_EXPORT extern const base::Feature kVideoRotateToFullscreen; MEDIA_EXPORT extern const base::Feature kMediaDrmPersistentLicense; +MEDIA_EXPORT extern const base::Feature kMediaDrmPreprovisioning; MEDIA_EXPORT extern const base::Feature kMediaDrmPreprovisioningAtStartup; MEDIA_EXPORT extern const base::Feature kAImageReaderVideoOutput; #endif // defined(OS_ANDROID)
diff --git a/media/blink/multibuffer_data_source_unittest.cc b/media/blink/multibuffer_data_source_unittest.cc index 2ab6142..429bf96 100644 --- a/media/blink/multibuffer_data_source_unittest.cc +++ b/media/blink/multibuffer_data_source_unittest.cc
@@ -1448,7 +1448,7 @@ Initialize(kHttpUrl, true); // Server responds without content-length. WebURLResponse response = response_generator_->Generate200(); - response.ClearHTTPHeaderField(WebString::FromUTF8("Content-Length")); + response.ClearHttpHeaderField(WebString::FromUTF8("Content-Length")); response.SetExpectedContentLength(kPositionNotSpecified); Respond(response); EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index d3a7300..d5daff5 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -336,6 +336,7 @@ mojom::MediaMetricsProviderPtr provider; MediaMetricsProvider::Create( false, base::BindRepeating([]() { return ukm::kInvalidSourceId; }), + base::BindRepeating([]() { return learning::FeatureValue(0); }), VideoDecodePerfHistory::SaveCallback(), mojo::MakeRequest(&provider)); // Initialize provider since none of the tests below actually go through the
diff --git a/media/capabilities/learning_helper.cc b/media/capabilities/learning_helper.cc index 144d6785..824c422 100644 --- a/media/capabilities/learning_helper.cc +++ b/media/capabilities/learning_helper.cc
@@ -79,6 +79,8 @@ if (feature_factory) { dropped_frame_task.name = kDroppedFrameRatioEnhancedTreeTaskName; dropped_frame_task.feature_descriptions.push_back( + {"origin", ::media::learning::LearningTask::Ordering::kUnordered}); + dropped_frame_task.feature_descriptions.push_back( FeatureLibrary::NetworkType()); dropped_frame_task.feature_descriptions.push_back( FeatureLibrary::BatteryPower()); @@ -95,6 +97,7 @@ void LearningHelper::AppendStats( const VideoDecodeStatsDB::VideoDescKey& video_key, + learning::FeatureValue origin, const VideoDecodeStatsDB::DecodeStatsEntry& new_stats) { // If no frames were recorded, then do nothing. if (new_stats.frames_decoded == 0) @@ -130,8 +133,10 @@ // Add this example to all tasks. AddExample(base_table_controller_.get(), example); AddExample(base_tree_controller_.get(), example); - if (enhanced_tree_controller_) + if (enhanced_tree_controller_) { + example.features.push_back(origin); AddExample(enhanced_tree_controller_.get(), example); + } } void LearningHelper::AddExample(LearningTaskController* controller,
diff --git a/media/capabilities/learning_helper.h b/media/capabilities/learning_helper.h index c3355ff7..d8b5506 100644 --- a/media/capabilities/learning_helper.h +++ b/media/capabilities/learning_helper.h
@@ -25,7 +25,12 @@ LearningHelper(learning::FeatureProviderFactoryCB feature_factory); ~LearningHelper(); + // |origin| is sent in separately since it's somewhat hacky. This should be + // provided by the FeatureProvider, but the way LearningHelper is used, it + // doesn't have access to the origin. Per-frame LearningTaskControllers will + // be able to do this much more easily. void AppendStats(const VideoDecodeStatsDB::VideoDescKey& video_key, + learning::FeatureValue origin, const VideoDecodeStatsDB::DecodeStatsEntry& new_stats); private:
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index a9b9bdd..0f62a52 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -265,6 +265,8 @@ "video/chromeos/display_rotation_observer.h", "video/chromeos/pixel_format_utils.cc", "video/chromeos/pixel_format_utils.h", + "video/chromeos/renderer_facing_cros_image_capture.cc", + "video/chromeos/renderer_facing_cros_image_capture.h", "video/chromeos/reprocess_manager.cc", "video/chromeos/reprocess_manager.h", "video/chromeos/request_builder.cc",
diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom index 89bbfec..233d135 100644 --- a/media/capture/mojom/video_capture_types.mojom +++ b/media/capture/mojom/video_capture_types.mojom
@@ -281,13 +281,6 @@ PlaneStrides? strides; }; -struct VideoCaptureDeviceDescriptorCameraCalibration { - double focal_length_x; - double focal_length_y; - double depth_near; - double depth_far; -}; - struct VideoCaptureDeviceDescriptor { string display_name; string device_id; @@ -295,7 +288,6 @@ VideoFacingMode facing_mode; VideoCaptureApi capture_api; VideoCaptureTransportType transport_type; - VideoCaptureDeviceDescriptorCameraCalibration? camera_calibration; }; struct VideoCaptureDeviceInfo {
diff --git a/media/capture/mojom/video_capture_types.typemap b/media/capture/mojom/video_capture_types.typemap index 146a77b..d3363e5 100644 --- a/media/capture/mojom/video_capture_types.typemap +++ b/media/capture/mojom/video_capture_types.typemap
@@ -33,7 +33,7 @@ "media.mojom.VideoCaptureFrameDropReason=media::VideoCaptureFrameDropReason", "media.mojom.VideoCaptureFormat=media::VideoCaptureFormat", "media.mojom.VideoCaptureParams=media::VideoCaptureParams", - "media.mojom.VideoCaptureDeviceDescriptorCameraCalibration=media::VideoCaptureDeviceDescriptor::CameraCalibration", "media.mojom.VideoCaptureDeviceDescriptor=media::VideoCaptureDeviceDescriptor", "media.mojom.VideoCaptureDeviceInfo=media::VideoCaptureDeviceInfo", + "media.mojom.VideoFacingMode=media::VideoFacingMode", ]
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.cc b/media/capture/mojom/video_capture_types_mojom_traits.cc index b6a0ebf9..ff08009 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.cc +++ b/media/capture/mojom/video_capture_types_mojom_traits.cc
@@ -1618,20 +1618,6 @@ } // static -bool StructTraits< - media::mojom::VideoCaptureDeviceDescriptorCameraCalibrationDataView, - media::VideoCaptureDeviceDescriptor::CameraCalibration>:: - Read(media::mojom::VideoCaptureDeviceDescriptorCameraCalibrationDataView - data, - media::VideoCaptureDeviceDescriptor::CameraCalibration* output) { - output->focal_length_x = data.focal_length_x(); - output->focal_length_y = data.focal_length_y(); - output->depth_near = data.depth_near(); - output->depth_far = data.depth_far(); - return true; -} - -// static bool StructTraits<media::mojom::VideoCaptureDeviceDescriptorDataView, media::VideoCaptureDeviceDescriptor>:: Read(media::mojom::VideoCaptureDeviceDescriptorDataView data, @@ -1650,8 +1636,6 @@ return false; if (!data.ReadTransportType(&(output->transport_type))) return false; - if (!data.ReadCameraCalibration(&(output->camera_calibration))) - return false; return true; }
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.h b/media/capture/mojom/video_capture_types_mojom_traits.h index 73f6709..4dc3b55 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.h +++ b/media/capture/mojom/video_capture_types_mojom_traits.h
@@ -146,35 +146,6 @@ }; template <> -struct StructTraits< - media::mojom::VideoCaptureDeviceDescriptorCameraCalibrationDataView, - media::VideoCaptureDeviceDescriptor::CameraCalibration> { - static double focal_length_x( - const media::VideoCaptureDeviceDescriptor::CameraCalibration& input) { - return input.focal_length_x; - } - - static double focal_length_y( - const media::VideoCaptureDeviceDescriptor::CameraCalibration& input) { - return input.focal_length_y; - } - - static double depth_near( - const media::VideoCaptureDeviceDescriptor::CameraCalibration& input) { - return input.depth_near; - } - - static double depth_far( - const media::VideoCaptureDeviceDescriptor::CameraCalibration& input) { - return input.depth_far; - } - - static bool Read( - media::mojom::VideoCaptureDeviceDescriptorCameraCalibrationDataView data, - media::VideoCaptureDeviceDescriptor::CameraCalibration* output); -}; - -template <> struct StructTraits<media::mojom::VideoCaptureDeviceDescriptorDataView, media::VideoCaptureDeviceDescriptor> { static const std::string& display_name( @@ -207,11 +178,6 @@ return input.transport_type; } - static base::Optional<media::VideoCaptureDeviceDescriptor::CameraCalibration> - camera_calibration(const media::VideoCaptureDeviceDescriptor& input) { - return input.camera_calibration; - } - static bool Read(media::mojom::VideoCaptureDeviceDescriptorDataView data, media::VideoCaptureDeviceDescriptor* output); };
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index 5129f64..0f17177d 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -193,7 +193,7 @@ base::OnceClosure device_close_callback) { DCHECK(ipc_task_runner_->BelongsToCurrentThread()); - reprocess_manager_->FlushReprocessOptions(); + reprocess_manager_->FlushReprocessOptions(device_descriptor_.device_id); if (!device_context_ || device_context_->GetState() == CameraDeviceContext::State::kStopped || @@ -408,7 +408,8 @@ SortCameraMetadata(&camera_info->static_camera_characteristics); static_metadata_ = std::move(camera_info->static_camera_characteristics); - reprocess_manager_->UpdateSupportedEffects(static_metadata_); + reprocess_manager_->UpdateSupportedEffects(device_descriptor_.device_id, + static_metadata_); const cros::mojom::CameraMetadataEntryPtr* sensor_orientation = GetMetadataEntry( @@ -760,6 +761,7 @@ while (!take_photo_callbacks_.empty()) { reprocess_manager_->ConsumeReprocessOptions( + device_descriptor_.device_id, base::BindOnce( &TakePhotoCallbackBundle, std::move(take_photo_callbacks_.front()), base::BindOnce(&Camera3AController::SetAutoFocusModeForStillCapture,
diff --git a/media/capture/video/chromeos/cros_image_capture_impl.cc b/media/capture/video/chromeos/cros_image_capture_impl.cc index 6574fef2..1bad8a6 100644 --- a/media/capture/video/chromeos/cros_image_capture_impl.cc +++ b/media/capture/video/chromeos/cros_image_capture_impl.cc
@@ -4,10 +4,12 @@ #include "media/capture/video/chromeos/cros_image_capture_impl.h" +#include <string> #include <utility> #include <vector> #include "base/task/post_task.h" +#include "media/base/bind_to_current_loop.h" namespace media { @@ -22,16 +24,20 @@ } void CrosImageCaptureImpl::GetSupportedEffects( + const std::string& device_id, GetSupportedEffectsCallback callback) { reprocess_manager_->GetSupportedEffects( - base::BindOnce(&CrosImageCaptureImpl::OnGetSupportedEffects, - base::Unretained(this), std::move(callback))); + device_id, media::BindToCurrentLoop(base::BindOnce( + &CrosImageCaptureImpl::OnGetSupportedEffects, + base::Unretained(this), std::move(callback)))); } void CrosImageCaptureImpl::SetReprocessOption( + const std::string& device_id, cros::mojom::Effect effect, SetReprocessOptionCallback callback) { - reprocess_manager_->SetReprocessOption(effect, std::move(callback)); + reprocess_manager_->SetReprocessOption( + device_id, effect, media::BindToCurrentLoop(std::move(callback))); } void CrosImageCaptureImpl::OnGetSupportedEffects(
diff --git a/media/capture/video/chromeos/cros_image_capture_impl.h b/media/capture/video/chromeos/cros_image_capture_impl.h index cc9d80c..278a403 100644 --- a/media/capture/video/chromeos/cros_image_capture_impl.h +++ b/media/capture/video/chromeos/cros_image_capture_impl.h
@@ -5,6 +5,8 @@ #ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_CROS_IMAGE_CAPTURE_IMPL_H_ #define MEDIA_CAPTURE_VIDEO_CHROMEOS_CROS_IMAGE_CAPTURE_IMPL_H_ +#include <string> + #include "base/containers/flat_set.h" #include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" #include "media/capture/video/chromeos/reprocess_manager.h" @@ -21,8 +23,10 @@ // cros::mojom::CrosImageCapture implementations. - void GetSupportedEffects(GetSupportedEffectsCallback callback) override; - void SetReprocessOption(cros::mojom::Effect effect, + void GetSupportedEffects(const std::string& device_id, + GetSupportedEffectsCallback callback) override; + void SetReprocessOption(const std::string& device_id, + cros::mojom::Effect effect, SetReprocessOptionCallback callback) override; private:
diff --git a/media/capture/video/chromeos/mojo/cros_image_capture.mojom b/media/capture/video/chromeos/mojo/cros_image_capture.mojom index 88b32ef..b1f20875 100644 --- a/media/capture/video/chromeos/mojo/cros_image_capture.mojom +++ b/media/capture/video/chromeos/mojo/cros_image_capture.mojom
@@ -13,16 +13,21 @@ }; // Interface for Chrome OS specific Image Capture API which supports reprocess -// mechanism. +// mechanism. The |source_id| parameter in following methods might not be the +// actual device id if it is called by renderer. It needs to be +// translated to the actual video device id to be used in CrosImageCapture +// implementation. interface CrosImageCapture { - // Gets supported effects for current active device. - GetSupportedEffects() => (array<Effect> supported_effects); + // Gets supported effects that recognized by CrOS for device. The |source_id| + // might need translation to be actual video device id. + GetSupportedEffects(string source_id) => (array<Effect> supported_effects); // Sets reprocess option to bind with the coming take photo request. When this // method is called, the reprocess option will be queued. All reprocess // options in the queue will be consumed when TakePhoto() method in Image // Capture API is triggered and all the queued reprocess options will be bound - // to that take photo request. - SetReprocessOption(Effect effect) + // to that take photo request. The |source_id| might need translation to be + // actual video device id. + SetReprocessOption(string source_id, Effect effect) => (int32 status, media.mojom.Blob blob); }; \ No newline at end of file
diff --git a/media/capture/video/chromeos/renderer_facing_cros_image_capture.cc b/media/capture/video/chromeos/renderer_facing_cros_image_capture.cc new file mode 100644 index 0000000..184c47e --- /dev/null +++ b/media/capture/video/chromeos/renderer_facing_cros_image_capture.cc
@@ -0,0 +1,63 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/capture/video/chromeos/renderer_facing_cros_image_capture.h" + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/task/post_task.h" +#include "media/base/bind_to_current_loop.h" + +namespace media { + +RendererFacingCrosImageCapture::RendererFacingCrosImageCapture( + cros::mojom::CrosImageCapturePtr api_ptr, + DeviceIdMappingCallback mapping_callback) + : cros_image_capture_(std::move(api_ptr)), + mapping_callback_(std::move(mapping_callback)), + weak_ptr_factory_(this) {} + +RendererFacingCrosImageCapture::~RendererFacingCrosImageCapture() = default; + +void RendererFacingCrosImageCapture::GetSupportedEffectsWithRealId( + GetSupportedEffectsCallback callback, + const base::Optional<std::string>& device_id) { + DCHECK(device_id.has_value()); + cros_image_capture_->GetSupportedEffects(*device_id, std::move(callback)); +} + +void RendererFacingCrosImageCapture::SetReprocessOptionWithRealId( + cros::mojom::Effect effect, + SetReprocessOptionCallback callback, + const base::Optional<std::string>& device_id) { + DCHECK(device_id.has_value()); + cros_image_capture_->SetReprocessOption(*device_id, effect, + std::move(callback)); +} + +void RendererFacingCrosImageCapture::GetSupportedEffects( + const std::string& source_id, + GetSupportedEffectsCallback callback) { + mapping_callback_.Run( + source_id, + media::BindToCurrentLoop(base::BindOnce( + &RendererFacingCrosImageCapture::GetSupportedEffectsWithRealId, + weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); +} + +void RendererFacingCrosImageCapture::SetReprocessOption( + const std::string& source_id, + cros::mojom::Effect effect, + SetReprocessOptionCallback callback) { + mapping_callback_.Run( + source_id, + media::BindToCurrentLoop(base::BindOnce( + &RendererFacingCrosImageCapture::SetReprocessOptionWithRealId, + weak_ptr_factory_.GetWeakPtr(), effect, std::move(callback)))); +} + +} // namespace media \ No newline at end of file
diff --git a/media/capture/video/chromeos/renderer_facing_cros_image_capture.h b/media/capture/video/chromeos/renderer_facing_cros_image_capture.h new file mode 100644 index 0000000..5eac4f9 --- /dev/null +++ b/media/capture/video/chromeos/renderer_facing_cros_image_capture.h
@@ -0,0 +1,64 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_RENDERER_FACING_CROS_IMAGE_CAPTURE_H_ +#define MEDIA_CAPTURE_VIDEO_CHROMEOS_RENDERER_FACING_CROS_IMAGE_CAPTURE_H_ + +#include <string> + +#include "media/capture/capture_export.h" +#include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" + +namespace media { + +// Intermediate layer for communicating from renderer to CrosImageCapture +// implementation. It will map the source id recognized by renderer to the +// actual video device id. +class CAPTURE_EXPORT RendererFacingCrosImageCapture + : public cros::mojom::CrosImageCapture { + public: + using WithRealIdCallback = + base::OnceCallback<void(const base::Optional<std::string>&)>; + using DeviceIdMappingCallback = + base::RepeatingCallback<void(const std::string&, WithRealIdCallback)>; + + // Create an intermediate layer between renderer to the actual + // CrosImageCapture implementation. This class should use |api_ptr| to + // communicate with the actual CrosImageCapture implementation and use + // |mapping_callback| to map the device id for every calls that inputs device + // id. + RendererFacingCrosImageCapture(cros::mojom::CrosImageCapturePtr api_ptr, + DeviceIdMappingCallback mapping_callback); + ~RendererFacingCrosImageCapture() override; + + void GetSupportedEffectsWithRealId( + GetSupportedEffectsCallback callback, + const base::Optional<std::string>& device_id); + + void SetReprocessOptionWithRealId( + cros::mojom::Effect effect, + SetReprocessOptionCallback callback, + const base::Optional<std::string>& device_id); + + // cros::mojom::CrosImageCapture implementations. + void GetSupportedEffects(const std::string& source_id, + GetSupportedEffectsCallback callback) override; + void SetReprocessOption(const std::string& source_id, + cros::mojom::Effect effect, + SetReprocessOptionCallback callback) override; + + private: + cros::mojom::CrosImageCapturePtr cros_image_capture_; + + DeviceIdMappingCallback mapping_callback_; + + base::WeakPtrFactory<RendererFacingCrosImageCapture> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(RendererFacingCrosImageCapture); +}; + +} // namespace media + +#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_RENDERER_FACING_CROS_IMAGE_CAPTURE_H_ \ No newline at end of file
diff --git a/media/capture/video/chromeos/reprocess_manager.cc b/media/capture/video/chromeos/reprocess_manager.cc index d226b28..cb7c017a 100644 --- a/media/capture/video/chromeos/reprocess_manager.cc +++ b/media/capture/video/chromeos/reprocess_manager.cc
@@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/capture/video/chromeos/reprocess_manager.h" + #include <functional> #include <utility> #include "media/capture/video/chromeos/camera_metadata_utils.h" -#include "media/capture/video/chromeos/reprocess_manager.h" namespace media { @@ -32,7 +33,7 @@ // static int ReprocessManager::GetReprocessReturnCode( cros::mojom::Effect effect, - cros::mojom::CameraMetadataPtr* metadata) { + const cros::mojom::CameraMetadataPtr* metadata) { if (effect == cros::mojom::Effect::PORTRAIT_MODE) { auto* portrait_mode_segmentation_result = GetMetadataEntry( *metadata, static_cast<cros::mojom::CameraMetadataTag>( @@ -53,6 +54,7 @@ } void ReprocessManager::SetReprocessOption( + const std::string& device_id, cros::mojom::Effect effect, cros::mojom::CrosImageCapture::SetReprocessOptionCallback reprocess_result_callback) { @@ -60,45 +62,48 @@ FROM_HERE, base::BindOnce( &ReprocessManager::ReprocessManagerImpl::SetReprocessOption, - base::Unretained(impl.get()), effect, + base::Unretained(impl.get()), device_id, effect, std::move(reprocess_result_callback))); } void ReprocessManager::ConsumeReprocessOptions( + const std::string& device_id, media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback) { sequenced_task_runner_->PostTask( FROM_HERE, base::BindOnce( &ReprocessManager::ReprocessManagerImpl::ConsumeReprocessOptions, - base::Unretained(impl.get()), std::move(take_photo_callback), - std::move(consumption_callback))); + base::Unretained(impl.get()), device_id, + std::move(take_photo_callback), std::move(consumption_callback))); } -void ReprocessManager::FlushReprocessOptions() { +void ReprocessManager::FlushReprocessOptions(const std::string& device_id) { sequenced_task_runner_->PostTask( FROM_HERE, base::BindOnce( &ReprocessManager::ReprocessManagerImpl::FlushReprocessOptions, - base::Unretained(impl.get()))); + base::Unretained(impl.get()), device_id)); } void ReprocessManager::GetSupportedEffects( + const std::string& device_id, GetSupportedEffectsCallback callback) { sequenced_task_runner_->PostTask( FROM_HERE, base::BindOnce( &ReprocessManager::ReprocessManagerImpl::GetSupportedEffects, - base::Unretained(impl.get()), std::move(callback))); + base::Unretained(impl.get()), device_id, std::move(callback))); } void ReprocessManager::UpdateSupportedEffects( + const std::string& device_id, const cros::mojom::CameraMetadataPtr& metadata) { sequenced_task_runner_->PostTask( FROM_HERE, base::BindOnce( &ReprocessManager::ReprocessManagerImpl::UpdateSupportedEffects, - base::Unretained(impl.get()), std::cref(metadata))); + base::Unretained(impl.get()), device_id, metadata.Clone())); } ReprocessManager::ReprocessManagerImpl::ReprocessManagerImpl() {} @@ -106,6 +111,7 @@ ReprocessManager::ReprocessManagerImpl::~ReprocessManagerImpl() = default; void ReprocessManager::ReprocessManagerImpl::SetReprocessOption( + const std::string& device_id, cros::mojom::Effect effect, cros::mojom::CrosImageCapture::SetReprocessOptionCallback reprocess_result_callback) { @@ -126,10 +132,11 @@ task.extra_metadata.push_back(std::move(e)); } - reprocess_task_queue_.push(std::move(task)); + reprocess_task_queue_map_[device_id].push(std::move(task)); } void ReprocessManager::ReprocessManagerImpl::ConsumeReprocessOptions( + const std::string& device_id, media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback) { ReprocessTaskQueue result_task_queue; @@ -140,7 +147,7 @@ base::BindOnce(&OnStillCaptureDone, std::move(take_photo_callback)); result_task_queue.push(std::move(still_capture_task)); - auto& task_queue = reprocess_task_queue_; + auto& task_queue = reprocess_task_queue_map_[device_id]; while (!task_queue.empty()) { result_task_queue.push(std::move(task_queue.front())); task_queue.pop(); @@ -148,26 +155,30 @@ std::move(consumption_callback).Run(std::move(result_task_queue)); } -void ReprocessManager::ReprocessManagerImpl::FlushReprocessOptions() { +void ReprocessManager::ReprocessManagerImpl::FlushReprocessOptions( + const std::string& device_id) { auto empty_queue = ReprocessTaskQueue(); - reprocess_task_queue_.swap(empty_queue); + reprocess_task_queue_map_[device_id].swap(empty_queue); } void ReprocessManager::ReprocessManagerImpl::GetSupportedEffects( + const std::string& device_id, GetSupportedEffectsCallback callback) { std::move(callback).Run( - base::flat_set<cros::mojom::Effect>(supported_effects_)); + base::flat_set<cros::mojom::Effect>(supported_effects_map_[device_id])); } void ReprocessManager::ReprocessManagerImpl::UpdateSupportedEffects( - const cros::mojom::CameraMetadataPtr& metadata) { + const std::string& device_id, + const cros::mojom::CameraMetadataPtr metadata) { const cros::mojom::CameraMetadataEntryPtr* portrait_mode = media::GetMetadataEntry( metadata, static_cast<cros::mojom::CameraMetadataTag>(kPortraitModeVendorKey)); - supported_effects_.clear(); + supported_effects_map_[device_id].clear(); if (portrait_mode) { - supported_effects_.insert(cros::mojom::Effect::PORTRAIT_MODE); + supported_effects_map_[device_id].insert( + cros::mojom::Effect::PORTRAIT_MODE); } }
diff --git a/media/capture/video/chromeos/reprocess_manager.h b/media/capture/video/chromeos/reprocess_manager.h index 715081925..436379f 100644 --- a/media/capture/video/chromeos/reprocess_manager.h +++ b/media/capture/video/chromeos/reprocess_manager.h
@@ -7,6 +7,7 @@ #include <queue> #include <set> +#include <string> #include <vector> #include "base/containers/flat_set.h" @@ -53,35 +54,43 @@ ~ReprocessManagerImpl(); void SetReprocessOption( + const std::string& device_id, cros::mojom::Effect effect, cros::mojom::CrosImageCapture::SetReprocessOptionCallback reprocess_result_callback); void ConsumeReprocessOptions( + const std::string& device_id, media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback); - void FlushReprocessOptions(); + void FlushReprocessOptions(const std::string& device_id); - void GetSupportedEffects(GetSupportedEffectsCallback callback); + void GetSupportedEffects(const std::string& device_id, + GetSupportedEffectsCallback callback); - void UpdateSupportedEffects(const cros::mojom::CameraMetadataPtr& metadata); + void UpdateSupportedEffects(const std::string& device_id, + const cros::mojom::CameraMetadataPtr metadata); private: - base::queue<ReprocessTask> reprocess_task_queue_; - base::flat_set<cros::mojom::Effect> supported_effects_; + base::flat_map<std::string, base::queue<ReprocessTask>> + reprocess_task_queue_map_; + base::flat_map<std::string, base::flat_set<cros::mojom::Effect>> + supported_effects_map_; DISALLOW_COPY_AND_ASSIGN(ReprocessManagerImpl); }; - static int GetReprocessReturnCode(cros::mojom::Effect effect, - cros::mojom::CameraMetadataPtr* metadata); + static int GetReprocessReturnCode( + cros::mojom::Effect effect, + const cros::mojom::CameraMetadataPtr* metadata); ReprocessManager(); ~ReprocessManager(); - // Sets the reprocess option for given effect. Each reprocess + // Sets the reprocess option for given device id and effect. Each reprocess // option has a corressponding callback. void SetReprocessOption( + const std::string& device_id, cros::mojom::Effect effect, cros::mojom::CrosImageCapture::SetReprocessOptionCallback reprocess_result_callback); @@ -89,18 +98,21 @@ // Consumes all ReprocessTasks in the queue. A default NO_EFFECT task will be // added on the top of the result queue. void ConsumeReprocessOptions( + const std::string& device_id, media::mojom::ImageCapture::TakePhotoCallback take_photo_callback, base::OnceCallback<void(ReprocessTaskQueue)> consumption_callback); - // Clears all remaining ReprocessTasks in the queue. - void FlushReprocessOptions(); + // Clears all remaining ReprocessTasks in the queue for given device id. + void FlushReprocessOptions(const std::string& device_id); // Gets supported effects for current active device. - void GetSupportedEffects(GetSupportedEffectsCallback callback); + void GetSupportedEffects(const std::string& device_id, + GetSupportedEffectsCallback callback); - // Updates supported effects for given active device. This method should be - // triggered whenever the camera characteristics is updated. - void UpdateSupportedEffects(const cros::mojom::CameraMetadataPtr& metadata); + // Updates supported effects for given device. This method should be triggered + // whenever the camera characteristics is updated. + void UpdateSupportedEffects(const std::string& device_id, + const cros::mojom::CameraMetadataPtr& metadata); private: scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
diff --git a/media/capture/video/fake_video_capture_device.h b/media/capture/video/fake_video_capture_device.h index 164054d1..6154d23 100644 --- a/media/capture/video/fake_video_capture_device.h +++ b/media/capture/video/fake_video_capture_device.h
@@ -102,9 +102,9 @@ // This is a separate struct because read-access to it is shared with several // collaborating classes. struct FakeDeviceState { - FakeDeviceState(float zoom, - float exposure_time, - float focus_distance, + FakeDeviceState(double zoom, + double exposure_time, + double focus_distance, float frame_rate, VideoPixelFormat pixel_format) : zoom(zoom), @@ -117,10 +117,10 @@ : mojom::MeteringMode::CONTINUOUS; } - uint32_t zoom; - uint32_t exposure_time; + double zoom; + double exposure_time; mojom::MeteringMode exposure_mode; - uint32_t focus_distance; + double focus_distance; mojom::MeteringMode focus_mode; VideoCaptureFormat format; };
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc index 6f33ce384..b4fada4de8 100644 --- a/media/capture/video/fake_video_capture_device_factory.cc +++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -16,8 +16,6 @@ namespace { -static const size_t kDepthDeviceIndex = 1; - // Cap the frame rate command line input to reasonable values. static const float kFakeCaptureMinFrameRate = 5.0f; static const float kFakeCaptureMaxFrameRate = 60.0f; @@ -218,18 +216,6 @@ ); entry_index++; } - - // Video device on index |kDepthDeviceIndex| is depth video capture device. - // Fill the camera calibration information only for it. - if (device_descriptors->size() <= kDepthDeviceIndex) - return; - VideoCaptureDeviceDescriptor& depth_device( - (*device_descriptors)[kDepthDeviceIndex]); - depth_device.camera_calibration.emplace(); - depth_device.camera_calibration->focal_length_x = 135.0; - depth_device.camera_calibration->focal_length_y = 135.6; - depth_device.camera_calibration->depth_near = 0.0; - depth_device.camera_calibration->depth_far = 65.535; } void FakeVideoCaptureDeviceFactory::GetSupportedFormats(
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index 9e0bf3c..df0723b 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -312,21 +312,6 @@ } } -TEST_F(FakeVideoCaptureDeviceTest, GetCameraCalibration) { - const size_t device_count = 2; - video_capture_device_factory_->SetToDefaultDevicesConfig(device_count); - video_capture_device_factory_->GetDeviceDescriptors(descriptors_.get()); - ASSERT_EQ(device_count, descriptors_->size()); - ASSERT_FALSE(descriptors_->at(0).camera_calibration); - const VideoCaptureDeviceDescriptor& depth_device = descriptors_->at(1); - EXPECT_EQ("/dev/video1", depth_device.device_id); - ASSERT_TRUE(depth_device.camera_calibration); - EXPECT_EQ(135.0, depth_device.camera_calibration->focal_length_x); - EXPECT_EQ(135.6, depth_device.camera_calibration->focal_length_y); - EXPECT_EQ(0.0, depth_device.camera_calibration->depth_near); - EXPECT_EQ(65.535, depth_device.camera_calibration->depth_far); -} - TEST_F(FakeVideoCaptureDeviceTest, ErrorDeviceReportsError) { auto device = FakeVideoCaptureDeviceFactory::CreateErrorDevice(); ASSERT_TRUE(device);
diff --git a/media/capture/video/video_capture_device_descriptor.h b/media/capture/video/video_capture_device_descriptor.h index c53274d..6d690a4 100644 --- a/media/capture/video/video_capture_device_descriptor.h +++ b/media/capture/video/video_capture_device_descriptor.h
@@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/optional.h" #include "media/base/video_facing.h" #include "media/capture/capture_export.h" @@ -94,21 +93,6 @@ VideoCaptureApi capture_api; VideoCaptureTransportType transport_type; - // Contains camera calibration parameters. - // These parameters apply to both RGB and depth video devices. See also - // https://w3c.github.io/mediacapture-depth/#mediatracksettings-dictionary - // TODO(aleksandar.stojiljkovic): Add principal point and camera distortion - // model and coefficients. See also https://crbug.com/616098 - struct CameraCalibration { - double focal_length_x = 0.0; - double focal_length_y = 0.0; - // depth near and far are used only for depth cameras. - double depth_near = 0.0; - double depth_far = 0.0; - }; - - base::Optional<CameraCalibration> camera_calibration; - private: std::string display_name_; // Name that is intended for display in the UI };
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc index f749ce4..3bada6c 100644 --- a/media/filters/fuchsia/fuchsia_video_decoder.cc +++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -108,15 +108,15 @@ return false; } - size_ = *constraints.per_packet_buffer_bytes_recommended(); + size_ = constraints.per_packet_buffer_bytes_recommended(); if (constraints.has_is_physically_contiguous_required() && - *constraints.is_physically_contiguous_required()) { + constraints.is_physically_contiguous_required()) { if (!constraints.has_very_temp_kludge_bti_handle()) { return false; } - vmo_ = CreateContiguousVmo(size_, - *constraints.very_temp_kludge_bti_handle()); + vmo_ = + CreateContiguousVmo(size_, constraints.very_temp_kludge_bti_handle()); } else { vmo_ = CreateVmo(size_); } @@ -518,23 +518,23 @@ return; } - if (*free_input_packet.buffer_lifetime_ordinal() != + if (free_input_packet.buffer_lifetime_ordinal() != input_buffer_lifetime_ordinal_) { return; } - if (*free_input_packet.packet_index() >= input_buffers_.size()) { + if (free_input_packet.packet_index() >= input_buffers_.size()) { DLOG(ERROR) << "fuchsia.mediacodec sent OnFreeInputPacket() for an unknown " "packet: buffer_lifetime_ordinal=" - << *free_input_packet.buffer_lifetime_ordinal() - << " packet_index=" << *free_input_packet.packet_index(); + << free_input_packet.buffer_lifetime_ordinal() + << " packet_index=" << free_input_packet.packet_index(); OnError(); return; } DCHECK_GT(num_used_input_buffers_, 0); num_used_input_buffers_--; - input_buffers_[*free_input_packet.packet_index()].OnDoneDecoding( + input_buffers_[free_input_packet.packet_index()].OnDoneDecoding( DecodeStatus::OK); // Try to pump input in case it was blocked. @@ -550,21 +550,21 @@ return; } - if (*output_config.stream_lifetime_ordinal() != stream_lifetime_ordinal_) { + if (output_config.stream_lifetime_ordinal() != stream_lifetime_ordinal_) { return; } - auto& format = *output_config.mutable_format_details(); + auto* format = output_config.mutable_format_details(); - if (!format.has_domain() || !format.domain()->is_video() || - !format.domain()->video().is_uncompressed()) { + if (!format->has_domain() || !format->domain().is_video() || + !format->domain().video().is_uncompressed()) { DLOG(ERROR) << "Received OnOutputConfig() with invalid format."; OnError(); return; } if (output_config.has_buffer_constraints_action_required() && - *output_config.buffer_constraints_action_required()) { + output_config.buffer_constraints_action_required()) { if (!output_config.has_buffer_constraints()) { DLOG(ERROR) << "Received OnOutputConfig() which requires buffer " "constraints action, but without buffer constraints."; @@ -579,21 +579,21 @@ } } - output_format_ = std::move(format.mutable_domain()->video().uncompressed()); + output_format_ = std::move(format->mutable_domain()->video().uncompressed()); } void FuchsiaVideoDecoder::OnOutputPacket(fuchsia::media::Packet output_packet, bool error_detected_before, bool error_detected_during) { if (!output_packet.has_header() || - !output_packet.header()->has_buffer_lifetime_ordinal() || - !output_packet.header()->has_packet_index()) { + !output_packet.header().has_buffer_lifetime_ordinal() || + !output_packet.header().has_packet_index()) { DLOG(ERROR) << "Received OnOutputPacket() with missing required fields."; OnError(); return; } - if (*output_packet.header()->buffer_lifetime_ordinal() != + if (output_packet.header().buffer_lifetime_ordinal() != output_buffer_lifetime_ordinal_) { return; } @@ -638,17 +638,16 @@ } if (!layout) { - codec_->RecycleOutputPacket(fidl::Clone(*output_packet.header())); + codec_->RecycleOutputPacket(fidl::Clone(output_packet.header())); return; } base::TimeDelta timestamp; if (output_packet.has_timestamp_ish()) { - timestamp = - base::TimeDelta::FromNanoseconds(*output_packet.timestamp_ish()); + timestamp = base::TimeDelta::FromNanoseconds(output_packet.timestamp_ish()); } - auto packet_index = *output_packet.header()->packet_index(); + auto packet_index = output_packet.header().packet_index(); auto& buffer = output_buffers_[packet_index]; DCHECK_LT(num_used_output_buffers_, static_cast<int>(output_buffers_.size())); @@ -735,21 +734,21 @@ input_buffer_lifetime_ordinal_ += 2; if (!constraints.has_default_settings() || - !constraints.default_settings()->has_packet_count_for_server() || - !constraints.default_settings()->has_packet_count_for_client()) { + !constraints.default_settings().has_packet_count_for_server() || + !constraints.default_settings().has_packet_count_for_client()) { DLOG(ERROR) << "Received InitializeInputBuffers() with missing required fields."; OnError(); return false; } - auto settings = fidl::Clone(*constraints.default_settings()); + auto settings = fidl::Clone(constraints.default_settings()); settings.set_buffer_lifetime_ordinal(input_buffer_lifetime_ordinal_); settings.set_packet_count_for_client(0); codec_->SetInputBufferSettings(fidl::Clone(settings)); int total_buffers = - *settings.packet_count_for_server() + *settings.packet_count_for_client(); + settings.packet_count_for_server() + settings.packet_count_for_client(); std::vector<InputBuffer> new_buffers(total_buffers); for (int i = 0; i < total_buffers; ++i) { @@ -810,7 +809,7 @@ input_buffer_lifetime_ordinal_); packet.mutable_header()->set_packet_index(input_buffer - input_buffers_.begin()); - packet.set_buffer_index(*packet.header()->packet_index()); + packet.set_buffer_index(packet.header().packet_index()); packet.set_timestamp_ish( pending_decodes_.front().buffer().timestamp().InNanoseconds()); packet.set_stream_lifetime_ordinal(stream_lifetime_ordinal_); @@ -830,8 +829,8 @@ fuchsia::media::StreamBufferConstraints constraints) { if (!constraints.has_default_settings() || !constraints.has_packet_count_for_client_max() || - !constraints.default_settings()->has_packet_count_for_server() || - !constraints.default_settings()->has_packet_count_for_client()) { + !constraints.default_settings().has_packet_count_for_server() || + !constraints.default_settings().has_packet_count_for_client()) { DLOG(ERROR) << "Received InitializeOutputBuffers() with missing required fields."; OnError(); @@ -842,17 +841,17 @@ // 2 for each buffer generation. output_buffer_lifetime_ordinal_ += 2; - auto settings = fidl::Clone(*constraints.default_settings()); + auto settings = fidl::Clone(constraints.default_settings()); settings.set_buffer_lifetime_ordinal(output_buffer_lifetime_ordinal_); - max_used_output_buffers_ = std::min( - kMaxUsedOutputFrames, *constraints.packet_count_for_client_max()); + max_used_output_buffers_ = + std::min(kMaxUsedOutputFrames, constraints.packet_count_for_client_max()); settings.set_packet_count_for_client(max_used_output_buffers_); codec_->SetOutputBufferSettings(fidl::Clone(settings)); int total_buffers = - *settings.packet_count_for_server() + *settings.packet_count_for_client(); + settings.packet_count_for_server() + settings.packet_count_for_client(); std::vector<scoped_refptr<OutputBuffer>> new_buffers(total_buffers); for (int i = 0; i < total_buffers; ++i) {
diff --git a/media/gpu/android/image_reader_gl_owner.cc b/media/gpu/android/image_reader_gl_owner.cc index 37c231ac..257130d4 100644 --- a/media/gpu/android/image_reader_gl_owner.cc +++ b/media/gpu/android/image_reader_gl_owner.cc
@@ -19,6 +19,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "gpu/command_buffer/service/abstract_texture.h" #include "gpu/ipc/common/android/android_image_reader_utils.h" +#include "ui/gl/android/android_surface_control_compat.h" #include "ui/gl/gl_fence_android_native_fence_sync.h" #include "ui/gl/gl_utils.h" #include "ui/gl/scoped_binders.h" @@ -100,9 +101,10 @@ AImageReader* reader = nullptr; // The usage flag below should be used when the buffer will be read from by // the GPU as a texture. - const uint64_t usage = mode == Mode::kAImageReaderSecure - ? AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT - : AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + uint64_t usage = mode == Mode::kAImageReaderSecure + ? AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT + : AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + usage |= gl::SurfaceControl::RequiredUsage(); // Create a new reader for images of the desired size and format. media_status_t return_code = loader_.AImageReader_newWithUsage(
diff --git a/media/gpu/vt_video_decode_accelerator_mac.cc b/media/gpu/vt_video_decode_accelerator_mac.cc index 68b7b65..5501c08 100644 --- a/media/gpu/vt_video_decode_accelerator_mac.cc +++ b/media/gpu/vt_video_decode_accelerator_mac.cc
@@ -292,6 +292,27 @@ return false; } +// Use a matrix id that is coherent with a primary id. Useful when we fail to +// parse the matrix. Previously it was always defaulting to MatrixID::BT709 +// See http://crbug.com/788236. +gfx::ColorSpace::MatrixID GetDefaultMatrixID( + const gfx::ColorSpace::PrimaryID primary_id) { + gfx::ColorSpace::MatrixID matrix_id = gfx::ColorSpace::MatrixID::BT709; + + switch (primary_id) { + case gfx::ColorSpace::PrimaryID::BT709: + matrix_id = gfx::ColorSpace::MatrixID::BT709; + break; + case gfx::ColorSpace::PrimaryID::BT470BG: + matrix_id = gfx::ColorSpace::MatrixID::BT470BG; + break; + default: + break; + } + + return matrix_id; +} + gfx::ColorSpace GetImageBufferColorSpace(CVImageBufferRef image_buffer) { // The named primaries. Default to BT709. gfx::ColorSpace::PrimaryID primary_id = gfx::ColorSpace::PrimaryID::BT709; @@ -314,7 +335,7 @@ }; if (!GetImageBufferProperty(image_buffer, kCVImageBufferColorPrimariesKey, primaries, base::size(primaries), &primary_id)) { - DLOG(ERROR) << "Filed to find CVImageBufferRef primaries."; + DLOG(ERROR) << "Failed to find CVImageBufferRef primaries."; } // The named transfer function. @@ -339,7 +360,7 @@ }; if (!GetImageBufferProperty(image_buffer, kCVImageBufferTransferFunctionKey, transfers, base::size(transfers), &transfer_id)) { - DLOG(ERROR) << "Filed to find CVImageBufferRef transfer."; + DLOG(ERROR) << "Failed to find CVImageBufferRef transfer."; } // Transfer functions can also be specified as a gamma value. @@ -356,15 +377,15 @@ transfer_id = gfx::ColorSpace::TransferID::CUSTOM; custom_tr_fn.g = gamma_float; } else { - DLOG(ERROR) << "Filed to get CVImageBufferRef gamma level as float."; + DLOG(ERROR) << "Failed to get CVImageBufferRef gamma level as float."; } } else { - DLOG(ERROR) << "Filed to get CVImageBufferRef gamma level."; + DLOG(ERROR) << "Failed to get CVImageBufferRef gamma level."; } } // Read the RGB to YUV matrix ID. - gfx::ColorSpace::MatrixID matrix_id = gfx::ColorSpace::MatrixID::BT709; + gfx::ColorSpace::MatrixID matrix_id = GetDefaultMatrixID(primary_id); struct { const CFStringRef cfstr; gfx::ColorSpace::MatrixID id; @@ -382,7 +403,7 @@ }}; if (!GetImageBufferProperty(image_buffer, kCVImageBufferYCbCrMatrixKey, matrices, base::size(matrices), &matrix_id)) { - DLOG(ERROR) << "Filed to find CVImageBufferRef YUV matrix."; + DLOG(ERROR) << "Failed to find CVImageBufferRef YUV matrix."; } // It is specified to the decoder to use luma=[16,235] chroma=[16,240] via
diff --git a/media/mojo/services/media_metrics_provider.cc b/media/mojo/services/media_metrics_provider.cc index 9dfa1871..d55d2fe 100644 --- a/media/mojo/services/media_metrics_provider.cc +++ b/media/mojo/services/media_metrics_provider.cc
@@ -4,6 +4,9 @@ #include "media/mojo/services/media_metrics_provider.h" +#include <memory> +#include <utility> + #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "media/mojo/services/video_decode_stats_recorder.h" @@ -21,10 +24,12 @@ MediaMetricsProvider::MediaMetricsProvider( bool is_top_frame, ukm::SourceId source_id, + learning::FeatureValue origin, VideoDecodePerfHistory::SaveCallback save_cb) : player_id_(g_player_id++), is_top_frame_(is_top_frame), source_id_(source_id), + origin_(origin), save_cb_(std::move(save_cb)) {} MediaMetricsProvider::~MediaMetricsProvider() { @@ -77,12 +82,13 @@ // static void MediaMetricsProvider::Create(bool is_top_frame, GetSourceIdCallback get_source_id_cb, + GetOriginCallback get_origin_cb, VideoDecodePerfHistory::SaveCallback save_cb, mojom::MediaMetricsProviderRequest request) { - mojo::MakeStrongBinding( - std::make_unique<MediaMetricsProvider>( - is_top_frame, get_source_id_cb.Run(), std::move(save_cb)), - std::move(request)); + mojo::MakeStrongBinding(std::make_unique<MediaMetricsProvider>( + is_top_frame, get_source_id_cb.Run(), + get_origin_cb.Run(), std::move(save_cb)), + std::move(request)); } void MediaMetricsProvider::Initialize(bool is_mse, @@ -163,9 +169,10 @@ return; } - mojo::MakeStrongBinding(std::make_unique<VideoDecodeStatsRecorder>( - save_cb_, source_id_, is_top_frame_, player_id_), - std::move(request)); + mojo::MakeStrongBinding( + std::make_unique<VideoDecodeStatsRecorder>(save_cb_, source_id_, origin_, + is_top_frame_, player_id_), + std::move(request)); } void MediaMetricsProvider::AddBytesReceived(uint64_t bytes_received) {
diff --git a/media/mojo/services/media_metrics_provider.h b/media/mojo/services/media_metrics_provider.h index 819899b..25c04df 100644 --- a/media/mojo/services/media_metrics_provider.h +++ b/media/mojo/services/media_metrics_provider.h
@@ -10,6 +10,7 @@ #include "media/base/container_names.h" #include "media/base/pipeline_status.h" #include "media/base/timestamp_constants.h" +#include "media/learning/common/value.h" #include "media/mojo/interfaces/media_metrics_provider.mojom.h" #include "media/mojo/services/media_mojo_export.h" #include "media/mojo/services/video_decode_perf_history.h" @@ -24,16 +25,29 @@ public: MediaMetricsProvider(bool is_top_frame, ukm::SourceId source_id, + learning::FeatureValue origin, VideoDecodePerfHistory::SaveCallback save_cb); ~MediaMetricsProvider() override; // Callback for retrieving a ukm::SourceId. using GetSourceIdCallback = base::RepeatingCallback<ukm::SourceId(void)>; + // TODO(liberato): This should be from a FeatureProvider, but the way in which + // we attach LearningHelper more or less precludes it. Per-frame task + // controllers would make this easy, but we bypass that here. + using GetOriginCallback = + base::RepeatingCallback<learning::FeatureValue(void)>; + // Creates a MediaMetricsProvider, |perf_history| may be nullptr if perf // history database recording is disabled. + // + // |get_source_id_cb| and |get_origin_cb| may not be run after this function + // returns. The intention is that they'll be run to produce the constructor + // arguments for MediaMetricsProvider synchronously. They should not be + // copied or moved for later. static void Create(bool is_top_frame, GetSourceIdCallback get_source_id_cb, + GetOriginCallback get_origin_cb, VideoDecodePerfHistory::SaveCallback save_cb, mojom::MediaMetricsProviderRequest request); @@ -63,6 +77,7 @@ const bool is_top_frame_; const ukm::SourceId source_id_; + const learning::FeatureValue origin_; const VideoDecodePerfHistory::SaveCallback save_cb_;
diff --git a/media/mojo/services/media_metrics_provider_unittest.cc b/media/mojo/services/media_metrics_provider_unittest.cc index 892850c..5198b28 100644 --- a/media/mojo/services/media_metrics_provider_unittest.cc +++ b/media/mojo/services/media_metrics_provider_unittest.cc
@@ -41,6 +41,7 @@ is_top_frame, base::BindRepeating(&MediaMetricsProviderTest::GetSourceId, base::Unretained(this)), + base::BindRepeating([]() { return learning::FeatureValue(0); }), VideoDecodePerfHistory::SaveCallback(), mojo::MakeRequest(&provider_)); provider_->Initialize(is_mse, scheme); }
diff --git a/media/mojo/services/video_decode_perf_history.cc b/media/mojo/services/video_decode_perf_history.cc index 505974a1..9d5c8fa 100644 --- a/media/mojo/services/video_decode_perf_history.cc +++ b/media/mojo/services/video_decode_perf_history.cc
@@ -207,6 +207,7 @@ } void VideoDecodePerfHistory::SavePerfRecord(ukm::SourceId source_id, + learning::FeatureValue origin, bool is_top_frame, mojom::PredictionFeatures features, mojom::PredictionTargets targets, @@ -230,8 +231,8 @@ if (db_init_status_ != COMPLETE) { init_deferred_api_calls_.push_back(base::BindOnce( &VideoDecodePerfHistory::SavePerfRecord, weak_ptr_factory_.GetWeakPtr(), - source_id, is_top_frame, std::move(features), std::move(targets), - player_id, std::move(save_done_cb))); + source_id, origin, is_top_frame, std::move(features), + std::move(targets), player_id, std::move(save_done_cb))); InitDatabase(); return; } @@ -244,7 +245,7 @@ targets.frames_power_efficient); if (learning_helper_) - learning_helper_->AppendStats(video_key, new_stats); + learning_helper_->AppendStats(video_key, origin, new_stats); // Get past perf info and report UKM metrics before saving this record. db_->GetDecodeStats(
diff --git a/media/mojo/services/video_decode_perf_history.h b/media/mojo/services/video_decode_perf_history.h index 01da1c9..7d21e12 100644 --- a/media/mojo/services/video_decode_perf_history.h +++ b/media/mojo/services/video_decode_perf_history.h
@@ -74,6 +74,7 @@ // for tests to know the save is complete. using SaveCallback = base::RepeatingCallback<void(ukm::SourceId source_id, + learning::FeatureValue origin, bool is_top_frame, mojom::PredictionFeatures features, mojom::PredictionTargets targets, @@ -118,6 +119,7 @@ // Initiate saving of the provided record. See GetSaveCallback(). void SavePerfRecord(ukm::SourceId source_id, + learning::FeatureValue origin, bool is_top_frame, mojom::PredictionFeatures features, mojom::PredictionTargets targets,
diff --git a/media/mojo/services/video_decode_perf_history_unittest.cc b/media/mojo/services/video_decode_perf_history_unittest.cc index fe27b004..1021a52 100644 --- a/media/mojo/services/video_decode_perf_history_unittest.cc +++ b/media/mojo/services/video_decode_perf_history_unittest.cc
@@ -203,9 +203,9 @@ const ukm::SourceId source_id = test_recorder_->GetNewSourceID(); test_recorder_->UpdateSourceURL(source_id, origin.GetURL()); - perf_history_->GetSaveCallback().Run(source_id, is_top_frame, features, - targets, player_id, - std::move(save_done_cb)); + perf_history_->GetSaveCallback().Run( + source_id, learning::FeatureValue(kOrigin.host()), is_top_frame, + features, targets, player_id, std::move(save_done_cb)); } protected:
diff --git a/media/mojo/services/video_decode_stats_recorder.cc b/media/mojo/services/video_decode_stats_recorder.cc index 4e20506..91718bf 100644 --- a/media/mojo/services/video_decode_stats_recorder.cc +++ b/media/mojo/services/video_decode_stats_recorder.cc
@@ -14,10 +14,12 @@ VideoDecodeStatsRecorder::VideoDecodeStatsRecorder( VideoDecodePerfHistory::SaveCallback save_cb, ukm::SourceId source_id, + learning::FeatureValue origin, bool is_top_frame, uint64_t player_id) : save_cb_(std::move(save_cb)), source_id_(source_id), + origin_(origin), is_top_frame_(is_top_frame), player_id_(player_id) { DCHECK(save_cb_); @@ -77,8 +79,8 @@ // Final argument is an empty save-done-callback. No action to take if save // fails (DB already records UMAs on failure). Callback mainly used by tests. - save_cb_.Run(source_id_, is_top_frame_, features_, targets_, player_id_, - base::OnceClosure()); + save_cb_.Run(source_id_, origin_, is_top_frame_, features_, targets_, + player_id_, base::OnceClosure()); } } // namespace media
diff --git a/media/mojo/services/video_decode_stats_recorder.h b/media/mojo/services/video_decode_stats_recorder.h index 29204e49..ebef85ac 100644 --- a/media/mojo/services/video_decode_stats_recorder.h +++ b/media/mojo/services/video_decode_stats_recorder.h
@@ -10,6 +10,7 @@ #include "base/time/time.h" #include "media/base/video_codecs.h" +#include "media/learning/common/value.h" #include "media/mojo/interfaces/media_types.mojom.h" #include "media/mojo/interfaces/video_decode_stats_recorder.mojom.h" #include "media/mojo/services/media_mojo_export.h" @@ -28,6 +29,7 @@ // be nullptr if database recording is currently disabled. VideoDecodeStatsRecorder(VideoDecodePerfHistory::SaveCallback save_cb, ukm::SourceId source_id, + learning::FeatureValue origin, bool is_top_frame, uint64_t player_id); ~VideoDecodeStatsRecorder() override; @@ -43,6 +45,7 @@ const VideoDecodePerfHistory::SaveCallback save_cb_; const ukm::SourceId source_id_; + const learning::FeatureValue origin_; const bool is_top_frame_; const uint64_t player_id_;
diff --git a/media/mojo/services/watch_time_recorder_unittest.cc b/media/mojo/services/watch_time_recorder_unittest.cc index 646e177..c89ef8b 100644 --- a/media/mojo/services/watch_time_recorder_unittest.cc +++ b/media/mojo/services/watch_time_recorder_unittest.cc
@@ -57,6 +57,8 @@ true /* is_top_frame */, base::BindRepeating(&WatchTimeRecorderTest::GetSourceId, base::Unretained(this)), + base::BindRepeating( + []() { return learning::FeatureValue(0); }) /* origin callback */, VideoDecodePerfHistory::SaveCallback(), mojo::MakeRequest(&provider_)); }
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md index 75ef5a7..55a366c 100644 --- a/mojo/public/cpp/bindings/README.md +++ b/mojo/public/cpp/bindings/README.md
@@ -657,7 +657,7 @@ representative C++ class which is typically wrapped in a `mojo::StructPtr<T>`. Unlike structs, all generated union fields are private and must be retrieved and -manipulated using accessors. A field `foo` is accessible by `foo()` and +manipulated using accessors. A field `foo` is accessible by `get_foo()` and settable by `set_foo()`. There is also a boolean `is_foo()` for each field which indicates whether the union is currently taking on the value of field `foo` in exclusion to all other union fields.
diff --git a/net/BUILD.gn b/net/BUILD.gn index ec176bb..17841dfa 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -391,6 +391,7 @@ "//net/dns", "//net/dns:dns_client", "//net/dns:host_resolver", + "//net/dns:host_resolver_manager", "//net/dns:mdns_client", "//net/dns/public", ] @@ -399,6 +400,7 @@ "//net/dns", "//net/dns:dns_client", "//net/dns:host_resolver", + "//net/dns:host_resolver_manager", "//net/dns:mdns_client", "//net/dns/public", "//net/http:transport_security_state_generated_files", @@ -1795,6 +1797,7 @@ sources += [ "network_error_logging/network_error_logging_service.cc", "network_error_logging/network_error_logging_service.h", + "network_error_logging/persistent_reporting_and_nel_store.h", "reporting/reporting_browsing_data_remover.cc", "reporting/reporting_browsing_data_remover.h", "reporting/reporting_cache.cc", @@ -2221,6 +2224,7 @@ "//net/dns", "//net/dns:dns_client", "//net/dns:host_resolver", + "//net/dns:host_resolver_manager", "//net/dns:mdns_client", "//net/dns/public", "//net/http:transport_security_state_generated_files", @@ -2287,6 +2291,7 @@ "//net/dns", "//net/dns:dns_client", "//net/dns:host_resolver", + "//net/dns:host_resolver_manager", "//net/dns:mdns_client", "//net/dns/public", "//net/http:transport_security_state_generated_files", @@ -2719,6 +2724,8 @@ "test/embedded_test_server/simple_connection_listener.h", "test/event_waiter.h", "test/gtest_util.h", + "test/key_util.cc", + "test/key_util.h", "test/keychain_test_util_mac.cc", "test/keychain_test_util_mac.h", "test/net_test_suite.cc", @@ -4945,7 +4952,6 @@ "http/http_network_layer_unittest.cc", "http/http_network_transaction_ssl_unittest.cc", "http/http_network_transaction_unittest.cc", - "http/http_proxy_client_socket_pool_unittest.cc", "http/http_proxy_client_socket_unittest.cc", "http/http_proxy_connect_job_unittest.cc", "http/http_request_headers_unittest.cc",
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index a3112de..265f752 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -207,7 +207,7 @@ CHECK(false); return NULL; #elif defined(OS_CHROMEOS) - return new NetworkChangeNotifierPosix(CONNECTION_UNKNOWN, SUBTYPE_UNKNOWN); + return new NetworkChangeNotifierPosix(CONNECTION_NONE, SUBTYPE_NONE); #elif defined(OS_LINUX) return new NetworkChangeNotifierLinux(std::unordered_set<std::string>()); #elif defined(OS_MACOSX)
diff --git a/net/cert/x509_util_unittest.cc b/net/cert/x509_util_unittest.cc index 949946c4..c6cb99d0 100644 --- a/net/cert/x509_util_unittest.cc +++ b/net/cert/x509_util_unittest.cc
@@ -13,8 +13,11 @@ #include "crypto/signature_verifier.h" #include "net/cert/x509_certificate.h" #include "net/test/cert_test_util.h" +#include "net/test/key_util.h" #include "net/test/test_data_directory.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/rsa.h" namespace net { @@ -667,70 +670,66 @@ EXPECT_TRUE(channel_bindings.empty()); } +namespace { + +bool DigestSign(EVP_PKEY* key, + const EVP_MD* md, + base::span<const uint8_t> data, + bool is_pss, + std::vector<uint8_t>* digest) { + bssl::ScopedEVP_MD_CTX ctx; + EVP_PKEY_CTX* pctx; + if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr, key)) { + return false; + } + + if (is_pss) { + if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* hash length */)) { + return false; + } + } + + // Determine the maximum length of the signature. + size_t len = 0; + if (!EVP_DigestSign(ctx.get(), nullptr, &len, data.data(), data.size())) { + return false; + } + digest->resize(len); + + // Sign it. + if (!EVP_DigestSign(ctx.get(), digest->data(), &len, data.data(), + data.size())) { + return false; + } + digest->resize(len); + return true; +} + +} // namespace + TEST(X509UtilTest, SignatureVerifierInitWithCertificate) { static const uint8_t kMessage[] = {'h', 'e', 'l', 'l', 'o'}; static const uint8_t kWrongMessage[] = {'n', 'o', 'p', 'e'}; - // Generated with: - // echo -n 'hello' | openssl dgst -sha256 -sign key_usage_rsa.key | xxd -i - static const uint8_t kRSASignaturePKCS1[] = { - 0xbc, 0x13, 0x5e, 0x83, 0x8a, 0x0b, 0xdf, 0x5d, 0x9f, 0x9c, 0xa5, 0x3d, - 0xc1, 0x91, 0x78, 0xe7, 0x3a, 0xda, 0x88, 0x7f, 0x31, 0x7d, 0xd5, 0x41, - 0xb8, 0x16, 0xad, 0x29, 0x28, 0xe1, 0x03, 0xc3, 0x18, 0x2c, 0xf8, 0xe6, - 0x55, 0x6a, 0x7c, 0xd6, 0xa2, 0x87, 0x49, 0xa0, 0x25, 0x96, 0x7e, 0x4e, - 0xe9, 0x0e, 0xd0, 0x8f, 0x43, 0xab, 0x6e, 0x09, 0x4c, 0x2a, 0x51, 0x87, - 0x74, 0x2e, 0x10, 0x1e, 0x10, 0x0c, 0xa1, 0x54, 0xb1, 0x28, 0x3c, 0x05, - 0x2d, 0x1e, 0x40, 0xfe, 0x81, 0xe7, 0xac, 0x65, 0x6c, 0x62, 0xc3, 0x46, - 0x00, 0x5e, 0x3d, 0x1c, 0x38, 0x36, 0xd9, 0xa8, 0xa8, 0x48, 0x3d, 0x1e, - 0x81, 0x5e, 0xdf, 0x8b, 0x34, 0xc7, 0x99, 0x87, 0x46, 0x47, 0xcc, 0xe9, - 0xb0, 0x16, 0xad, 0x97, 0xf5, 0x1d, 0x1a, 0x04, 0xe1, 0x89, 0x86, 0x97, - 0x02, 0x54, 0xfc, 0xc9, 0x0c, 0x86, 0x9b, 0x84, 0x83, 0xa4, 0x13, 0x3b, - 0x6c, 0x3e, 0x80, 0x6a, 0xd7, 0xdd, 0xb3, 0xdc, 0x6a, 0x79, 0xe7, 0x34, - 0x9f, 0x55, 0x23, 0xd2, 0xec, 0x80, 0x20, 0xac, 0x92, 0x96, 0x31, 0xd9, - 0x60, 0x05, 0xf4, 0xdb, 0xd5, 0xd0, 0x51, 0x3e, 0x47, 0x05, 0xef, 0xc1, - 0x4c, 0xea, 0x30, 0xe6, 0xbc, 0x32, 0x25, 0xa5, 0x73, 0xb6, 0x20, 0xbf, - 0xdb, 0x24, 0x1c, 0x79, 0x61, 0x97, 0xbb, 0x29, 0xaf, 0x51, 0xc5, 0x2f, - 0x85, 0x9b, 0xe8, 0xb2, 0x2b, 0x53, 0xd8, 0xeb, 0x3e, 0x2e, 0x53, 0x02, - 0x91, 0xad, 0xd3, 0xbc, 0xcf, 0x80, 0x46, 0x80, 0xbc, 0xa7, 0xab, 0x9e, - 0x23, 0x79, 0x50, 0x23, 0x7d, 0x81, 0x22, 0xfa, 0x22, 0x8f, 0xcd, 0xe4, - 0xed, 0x7c, 0x78, 0xba, 0x63, 0x93, 0x1b, 0x39, 0xb8, 0x5a, 0x35, 0xb7, - 0x77, 0xb1, 0x3e, 0x25, 0xaa, 0x45, 0x67, 0x1a, 0x12, 0x2a, 0x84, 0xff, - 0x3b, 0x2a, 0x9f, 0xe3}; - // Generated with: - // clang-format off - // echo -n 'hello' | openssl dgst -sha256 -sign key_usage_rsa.key -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 | xxd -i - // clang-format on - static const uint8_t kRSASignaturePSS[] = { - 0x0d, 0xe7, 0xe3, 0xdf, 0xe3, 0x05, 0xe3, 0xfa, 0x7d, 0xee, 0x59, 0xa9, - 0xad, 0xa3, 0xd7, 0xf1, 0xf7, 0x79, 0x1e, 0xa7, 0x27, 0x85, 0x1a, 0x83, - 0x3c, 0x82, 0x3a, 0x70, 0xaf, 0x39, 0xbe, 0x67, 0x47, 0x1a, 0xa0, 0xa0, - 0x68, 0x5b, 0x01, 0x49, 0x79, 0x98, 0xf8, 0x9e, 0xc8, 0x73, 0xd4, 0x11, - 0xad, 0x48, 0xa0, 0x46, 0x42, 0xbc, 0x82, 0x6b, 0x4b, 0x17, 0xf3, 0xe1, - 0xf6, 0x5b, 0xc5, 0x3a, 0x30, 0xb7, 0x24, 0x8c, 0x51, 0x2b, 0xaf, 0xb0, - 0x29, 0xa4, 0x4b, 0xfa, 0xd5, 0xf6, 0xf4, 0xf6, 0x1b, 0x0c, 0xd1, 0x3a, - 0xf2, 0x18, 0x3b, 0x80, 0x46, 0x40, 0x2b, 0x0f, 0x6c, 0x83, 0xf1, 0x19, - 0x64, 0x62, 0xf1, 0x80, 0x5d, 0x32, 0x69, 0x11, 0x39, 0x35, 0xf6, 0x42, - 0x7d, 0xe4, 0x16, 0xc3, 0x49, 0x8c, 0xc7, 0x77, 0x55, 0x67, 0x74, 0x45, - 0x5d, 0xc0, 0x8f, 0x72, 0x3e, 0x89, 0x7f, 0xbc, 0x18, 0x4d, 0xfd, 0x9a, - 0xb0, 0x3e, 0x47, 0xa5, 0x55, 0xec, 0x17, 0x7e, 0xe9, 0x46, 0x12, 0x96, - 0xac, 0x5f, 0x81, 0xfa, 0x7f, 0x24, 0xc2, 0x7f, 0xf7, 0xdb, 0xa1, 0x7b, - 0x72, 0xee, 0xcc, 0x62, 0x79, 0x20, 0x35, 0x39, 0xd5, 0xbf, 0xf9, 0x7d, - 0xff, 0x2b, 0x55, 0x62, 0x75, 0x08, 0x88, 0x9c, 0x0e, 0x8d, 0x81, 0x0d, - 0x69, 0x1e, 0x88, 0xcf, 0x1e, 0x31, 0x58, 0xd4, 0x1b, 0x25, 0xd4, 0xe7, - 0x01, 0x20, 0x3f, 0xcb, 0xd0, 0x44, 0xa4, 0xfc, 0x6d, 0x40, 0x04, 0x8e, - 0x2f, 0x05, 0x21, 0xe6, 0xa4, 0xab, 0xc2, 0xe0, 0x0c, 0xd6, 0x43, 0xa1, - 0x33, 0xbc, 0xe3, 0x63, 0xe6, 0xf0, 0x1f, 0x91, 0x09, 0xae, 0x0a, 0x80, - 0x6a, 0xc1, 0xa4, 0x36, 0x0b, 0x65, 0x9e, 0xa5, 0xbf, 0xd0, 0x8d, 0x2c, - 0xe5, 0x75, 0xf3, 0x8c, 0xa9, 0x29, 0x17, 0x3f, 0x81, 0xff, 0xe1, 0x25, - 0xf5, 0x9c, 0x72, 0x8c}; - // Generated with: - // echo -n 'hello' | openssl dgst -sha256 -sign key_usage_p256.key | xxd -i - static const uint8_t kP256Signature[] = { - 0x30, 0x45, 0x02, 0x20, 0x71, 0x7d, 0xb0, 0xb0, 0xc4, 0x3d, 0x44, 0xe7, - 0x7e, 0x31, 0x38, 0xfd, 0xd9, 0xa0, 0x75, 0x10, 0x19, 0x94, 0x9d, 0x1e, - 0x93, 0x91, 0x5e, 0x15, 0x68, 0xd0, 0x7f, 0xef, 0xeb, 0xb6, 0x9f, 0xe0, - 0x02, 0x21, 0x00, 0xbd, 0x00, 0xa8, 0xd9, 0x21, 0x99, 0x94, 0x4b, 0xfe, - 0x70, 0xbc, 0xd4, 0x32, 0x07, 0xab, 0x09, 0x3d, 0xae, 0xe4, 0xc0, 0xfb, - 0x01, 0x0d, 0xb9, 0xc3, 0x45, 0xbc, 0x91, 0xd1, 0x6a, 0xe2, 0xfe}; + + bssl::UniquePtr<EVP_PKEY> rsaKey = + net::key_util::LoadEVP_PKEYFromPEM(net::GetTestCertsDirectory().Append( + FILE_PATH_LITERAL("key_usage_rsa.key"))); + ASSERT_NE(rsaKey, nullptr); + bssl::UniquePtr<EVP_PKEY> p256Key = + net::key_util::LoadEVP_PKEYFromPEM(net::GetTestCertsDirectory().Append( + FILE_PATH_LITERAL("key_usage_p256.key"))); + ASSERT_NE(p256Key, nullptr); + + std::vector<uint8_t> rsaSignaturePKCS1; + ASSERT_TRUE(DigestSign(rsaKey.get(), EVP_sha256(), kMessage, false, + &rsaSignaturePKCS1)); + std::vector<uint8_t> rsaSignaturePSS; + ASSERT_TRUE( + DigestSign(rsaKey.get(), EVP_sha256(), kMessage, true, &rsaSignaturePSS)); + std::vector<uint8_t> p256Signature; + ASSERT_TRUE( + DigestSign(p256Key.get(), EVP_sha256(), kMessage, false, &p256Signature)); struct Test { const char* cert; @@ -740,41 +739,41 @@ } kTests[] = { // The certificate must support the digitalSignature key usage. {"key_usage_p256_digitalsignature.pem", - crypto::SignatureVerifier::ECDSA_SHA256, kP256Signature, true}, + crypto::SignatureVerifier::ECDSA_SHA256, p256Signature, true}, {"key_usage_p256_both.pem", crypto::SignatureVerifier::ECDSA_SHA256, - kP256Signature, true}, + p256Signature, true}, {"key_usage_rsa_digitalsignature.pem", - crypto::SignatureVerifier::RSA_PKCS1_SHA256, kRSASignaturePKCS1, true}, + crypto::SignatureVerifier::RSA_PKCS1_SHA256, rsaSignaturePKCS1, true}, {"key_usage_rsa_digitalsignature.pem", - crypto::SignatureVerifier::RSA_PSS_SHA256, kRSASignaturePSS, true}, + crypto::SignatureVerifier::RSA_PSS_SHA256, rsaSignaturePSS, true}, {"key_usage_rsa_both.pem", crypto::SignatureVerifier::RSA_PKCS1_SHA256, - kRSASignaturePKCS1, true}, + rsaSignaturePKCS1, true}, {"key_usage_rsa_both.pem", crypto::SignatureVerifier::RSA_PSS_SHA256, - kRSASignaturePSS, true}, + rsaSignaturePSS, true}, // Omitting the extension entirely is also accepted. {"key_usage_p256_no_extension.pem", - crypto::SignatureVerifier::ECDSA_SHA256, kP256Signature, true}, + crypto::SignatureVerifier::ECDSA_SHA256, p256Signature, true}, {"key_usage_rsa_no_extension.pem", - crypto::SignatureVerifier::RSA_PKCS1_SHA256, kRSASignaturePKCS1, true}, + crypto::SignatureVerifier::RSA_PKCS1_SHA256, rsaSignaturePKCS1, true}, {"key_usage_rsa_no_extension.pem", - crypto::SignatureVerifier::RSA_PSS_SHA256, kRSASignaturePSS, true}, + crypto::SignatureVerifier::RSA_PSS_SHA256, rsaSignaturePSS, true}, // If the extension is present but digitalSignature is missing, the // signature is rejected. {"key_usage_p256_keyagreement.pem", - crypto::SignatureVerifier::ECDSA_SHA256, kP256Signature, false}, + crypto::SignatureVerifier::ECDSA_SHA256, p256Signature, false}, {"key_usage_rsa_keyencipherment.pem", - crypto::SignatureVerifier::RSA_PKCS1_SHA256, kRSASignaturePKCS1, false}, + crypto::SignatureVerifier::RSA_PKCS1_SHA256, rsaSignaturePKCS1, false}, {"key_usage_rsa_keyencipherment.pem", - crypto::SignatureVerifier::RSA_PSS_SHA256, kRSASignaturePSS, false}, + crypto::SignatureVerifier::RSA_PSS_SHA256, rsaSignaturePSS, false}, // The key and signature must match, rather than only extracting the hash // function. {"key_usage_p256_digitalsignature.pem", - crypto::SignatureVerifier::RSA_PKCS1_SHA256, kP256Signature, false}, + crypto::SignatureVerifier::RSA_PKCS1_SHA256, p256Signature, false}, {"key_usage_rsa_digitalsignature.pem", - crypto::SignatureVerifier::ECDSA_SHA256, kRSASignaturePKCS1, false}, + crypto::SignatureVerifier::ECDSA_SHA256, rsaSignaturePKCS1, false}, }; for (const auto& test : kTests) {
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index 804d9b1..9617604a 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn
@@ -59,7 +59,6 @@ "host_cache.cc", "host_resolver.cc", "host_resolver_manager.cc", - "host_resolver_manager.h", "host_resolver_mdns_listener_impl.cc", "host_resolver_mdns_listener_impl.h", "host_resolver_mdns_task.cc", @@ -109,6 +108,7 @@ public_deps = [ ":dns_client", ":host_resolver", + ":host_resolver_manager", ":mdns_client", "//net:net_public_deps", ] @@ -116,6 +116,7 @@ allow_circular_includes_from = [ ":dns_client", ":host_resolver", + ":host_resolver_manager", ":mdns_client", ] } @@ -133,6 +134,7 @@ # restriction. visibility = [ ":dns", + ":host_resolver_manager", ":mdns_client", "//net", ] @@ -196,6 +198,47 @@ ] } +# Shared mostly-global handler of HostResolver requests. +# +# Typically should only be directly interacted with by NetworkService (or other +# mostly-global creators of request contexts), standalone tools, and tests. Host +# resolution should generally instead go through HostResolvers received from +# URLRequestContext or network service Mojo IPCs. +source_set("host_resolver_manager") { + # Due to circular dependencies, should only be depended on through //net. + # Limit visibility to //net and other source_sets with the same access + # restriction. + visibility = [ + ":dns", + ":host_resolver", + "//net", + ] + + # Whitelist-only access so we can keep track of all usage external to the + # network stack and network service. + friend = [ + # Network stack/service. + "//net/*", + "//services/network/*", + ] + + sources = [] + public = [] + + if (!is_nacl) { + sources += [ "host_resolver_manager.h" ] + } + + deps = [ + ":host_resolver", + "//net:net_deps", + "//net/dns/public", + ] + public_deps = [ + "//net:net_public_deps", + ] +} + # DnsClient interfaces. Primarily intended as part of the implementation of the # standard HostResolver interface, but can be used as an alternative external # interface for advanced usage.
diff --git a/net/dns/public/BUILD.gn b/net/dns/public/BUILD.gn index afe91da..9b20ce9 100644 --- a/net/dns/public/BUILD.gn +++ b/net/dns/public/BUILD.gn
@@ -10,7 +10,7 @@ "//net", "//net/dns:dns_client", "//net/dns:host_resolver", - "//net/dns:host_resolver_impl", + "//net/dns:host_resolver_manager", ] sources = [
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h index 59c8666..fc279b5 100644 --- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h +++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.h
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "net/network_error_logging/network_error_logging_service.h" +#include "net/network_error_logging/persistent_reporting_and_nel_store.h" namespace base { class FilePath; @@ -21,7 +22,7 @@ namespace net { class COMPONENT_EXPORT(NET_EXTRAS) SQLitePersistentReportingAndNELStore - : public NetworkErrorLoggingService::PersistentNELStore { + : public PersistentReportingAndNELStore { public: SQLitePersistentReportingAndNELStore( const base::FilePath& path,
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc deleted file mode 100644 index 54a7cb8..0000000 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ /dev/null
@@ -1,333 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -#include <map> -#include <string> -#include <utility> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/metrics/histogram_tester.h" -#include "build/build_config.h" -#include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/base/test_proxy_delegate.h" -#include "net/http/http_network_session.h" -#include "net/http/http_proxy_client_socket.h" -#include "net/http/http_proxy_connect_job.h" -#include "net/http/http_response_headers.h" -#include "net/log/net_log_with_source.h" -#include "net/nqe/network_quality_estimator_test_util.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/next_proto.h" -#include "net/socket/socket_tag.h" -#include "net/socket/socket_test_util.h" -#include "net/socket/socks_connect_job.h" -#include "net/socket/ssl_connect_job.h" -#include "net/socket/transport_client_socket_pool.h" -#include "net/socket/transport_connect_job.h" -#include "net/spdy/spdy_test_util_common.h" -#include "net/test/gtest_util.h" -#include "net/test/test_with_scoped_task_environment.h" -#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::test::IsError; -using net::test::IsOk; - -namespace net { - -namespace { - -const int kMaxSockets = 32; -const int kMaxSocketsPerGroup = 6; -constexpr base::TimeDelta kUnusedIdleSocketTimeout = - base::TimeDelta::FromSeconds(10); -const char * const kAuthHeaders[] = { - "proxy-authorization", "Basic Zm9vOmJhcg==" -}; -const int kAuthHeadersSize = base::size(kAuthHeaders) / 2; - -enum HttpProxyType { - HTTP, - HTTPS, - SPDY -}; - -const char kHttpProxyHost[] = "httpproxy.example.com"; -const char kHttpsProxyHost[] = "httpsproxy.example.com"; - -} // namespace - -class HttpProxyClientSocketPoolTest - : public ::testing::TestWithParam<HttpProxyType>, - public WithScopedTaskEnvironment { - protected: - HttpProxyClientSocketPoolTest() { - session_deps_.host_resolver->set_synchronous_mode(true); - session_ = CreateNetworkSession(); - common_connect_job_params_ = std::make_unique<CommonConnectJobParams>( - &socket_factory_, session_deps_.host_resolver.get(), - session_->http_auth_cache(), - session_deps_.http_auth_handler_factory.get(), - session_->spdy_session_pool(), session_->quic_stream_factory(), - nullptr /* proxy_delegate */, nullptr /* http_user_agent_settings */, - SSLClientSocketContext(session_deps_.cert_verifier.get(), - session_deps_.channel_id_service.get(), - session_deps_.transport_security_state.get(), - session_deps_.cert_transparency_verifier.get(), - session_deps_.ct_policy_enforcer.get(), - nullptr /* ssl_client_session_cache */), - SSLClientSocketContext( - session_deps_.cert_verifier.get(), - session_deps_.channel_id_service.get(), - session_deps_.transport_security_state.get(), - session_deps_.cert_transparency_verifier.get(), - session_deps_.ct_policy_enforcer.get(), - nullptr /* ssl_client_session_cache_privacy_mode */), - nullptr /* socket_performance_watcher_factory */, &estimator_, - nullptr /* net_log */, nullptr /* websocket_lock_endpoint_manager */); - InitPoolWithProxyDelegate(nullptr); - } - - ~HttpProxyClientSocketPoolTest() override = default; - - void InitPoolWithProxyDelegate(ProxyDelegate* proxy_delegate) { - pool_ = std::make_unique<TransportClientSocketPool>( - kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, - common_connect_job_params_.get(), - session_deps_.ssl_config_service.get()); - } - - void AddAuthToCache() { - const base::string16 kFoo(base::ASCIIToUTF16("foo")); - const base::string16 kBar(base::ASCIIToUTF16("bar")); - GURL proxy_url(GetParam() == HTTP - ? (std::string("http://") + kHttpProxyHost) - : (std::string("https://") + kHttpsProxyHost)); - session_->http_auth_cache()->Add(proxy_url, - "MyRealm1", - HttpAuth::AUTH_SCHEME_BASIC, - "Basic realm=MyRealm1", - AuthCredentials(kFoo, kBar), - "/"); - } - - scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const { - if (GetParam() != HTTP) - return nullptr; - return new TransportSocketParams(HostPortPair(kHttpProxyHost, 80), false, - OnHostResolutionCallback()); - } - - scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const { - if (GetParam() == HTTP) - return nullptr; - return new SSLSocketParams( - new TransportSocketParams(HostPortPair(kHttpsProxyHost, 443), false, - OnHostResolutionCallback()), - nullptr, nullptr, HostPortPair(kHttpsProxyHost, 443), SSLConfig(), - PRIVACY_MODE_DISABLED); - } - - // Returns the a correctly constructed HttpProxyParms - // for the HTTP or HTTPS proxy. - scoped_refptr<TransportClientSocketPool::SocketParams> CreateTunnelParams() { - return TransportClientSocketPool::SocketParams:: - CreateFromHttpProxySocketParams( - base::MakeRefCounted<HttpProxySocketParams>( - CreateHttpProxyParams(), CreateHttpsProxyParams(), - quic::QUIC_VERSION_UNSUPPORTED, - HostPortPair("www.google.com", 443), - /*is_trusted_proxy=*/false, /*tunnel=*/true, - TRAFFIC_ANNOTATION_FOR_TESTS)); - } - - static ClientSocketPool::GroupId group_id() { - return ClientSocketPool::GroupId(HostPortPair("www.google.com", 443), - ClientSocketPool::SocketType::kHttp, - false /* privacy_mode */); - } - - MockTaggingClientSocketFactory* socket_factory() { return &socket_factory_; } - - void Initialize(base::span<const MockRead> reads, - base::span<const MockWrite> writes, - base::span<const MockRead> spdy_reads, - base::span<const MockWrite> spdy_writes) { - if (GetParam() == SPDY) { - data_.reset(new SequencedSocketData(spdy_reads, spdy_writes)); - } else { - data_.reset(new SequencedSocketData(reads, writes)); - } - - data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); - - socket_factory()->AddSocketDataProvider(data_.get()); - - if (GetParam() != HTTP) { - ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK)); - if (GetParam() == SPDY) { - InitializeSpdySsl(); - } - socket_factory()->AddSSLSocketDataProvider(ssl_data_.get()); - } - } - - void InitializeSpdySsl() { ssl_data_->next_proto = kProtoHTTP2; } - - std::unique_ptr<HttpNetworkSession> CreateNetworkSession() { - return SpdySessionDependencies::SpdyCreateSession(&session_deps_); - } - - const base::HistogramTester& histogram_tester() { return histogram_tester_; } - - protected: - MockTaggingClientSocketFactory socket_factory_; - SpdySessionDependencies session_deps_; - - TestNetworkQualityEstimator estimator_; - - std::unique_ptr<HttpNetworkSession> session_; - - std::unique_ptr<CommonConnectJobParams> common_connect_job_params_; - - base::HistogramTester histogram_tester_; - - SpdyTestUtil spdy_util_; - std::unique_ptr<SSLSocketDataProvider> ssl_data_; - std::unique_ptr<SequencedSocketData> data_; - std::unique_ptr<TransportClientSocketPool> pool_; - ClientSocketHandle handle_; - TestCompletionCallback callback_; -}; - -// All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY) -// and SPDY. -INSTANTIATE_TEST_SUITE_P(HttpProxyType, - HttpProxyClientSocketPoolTest, - ::testing::Values(HTTP, HTTPS, SPDY)); - -TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) { - if (GetParam() == HTTP) - return; - data_.reset(new SequencedSocketData()); - data_->set_connect_data(MockConnect(ASYNC, OK)); - socket_factory()->AddSocketDataProvider(data_.get()); - - ssl_data_.reset(new SSLSocketDataProvider(ASYNC, - ERR_SSL_CLIENT_AUTH_CERT_NEEDED)); - if (GetParam() == SPDY) { - InitializeSpdySsl(); - } - socket_factory()->AddSSLSocketDataProvider(ssl_data_.get()); - - int rv = handle_.Init( - group_id(), CreateTunnelParams(), LOW, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, callback_.callback(), - ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - EXPECT_FALSE(handle_.is_initialized()); - EXPECT_FALSE(handle_.socket()); - - EXPECT_THAT(callback_.WaitForResult(), - IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED)); - - EXPECT_FALSE(handle_.is_initialized()); - EXPECT_FALSE(handle_.socket()); - histogram_tester().ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Secure.Error", 1); - histogram_tester().ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Insecure.Error", 0); -} - -TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) { - const std::string redirectTarget = "https://foo.google.com/"; - - const std::string responseText = "HTTP/1.1 302 Found\r\n" - "Location: " + redirectTarget + "\r\n" - "Set-Cookie: foo=bar\r\n" - "\r\n"; - MockWrite writes[] = { - MockWrite(ASYNC, 0, - "CONNECT www.google.com:443 HTTP/1.1\r\n" - "Host: www.google.com:443\r\n" - "Proxy-Connection: keep-alive\r\n" - "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), - }; - MockRead reads[] = { - MockRead(ASYNC, 1, responseText.c_str()), - }; - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - kAuthHeaders, kAuthHeadersSize, 1, - HttpProxyConnectJob::kH2QuicTunnelPriority, - HostPortPair("www.google.com", 443))); - spdy::SpdySerializedFrame rst( - spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); - - MockWrite spdy_writes[] = { - CreateMockWrite(req, 0, ASYNC), CreateMockWrite(rst, 3, ASYNC), - }; - - const char* const responseHeaders[] = { - "location", redirectTarget.c_str(), - "set-cookie", "foo=bar", - }; - const int responseHeadersSize = base::size(responseHeaders) / 2; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError( - "302", responseHeaders, responseHeadersSize, 1)); - MockRead spdy_reads[] = { - CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 2), - }; - - Initialize(reads, writes, spdy_reads, spdy_writes); - AddAuthToCache(); - - int rv = handle_.Init( - group_id(), CreateTunnelParams(), LOW, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, callback_.callback(), - ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - EXPECT_FALSE(handle_.is_initialized()); - EXPECT_FALSE(handle_.socket()); - - rv = callback_.WaitForResult(); - - if (GetParam() == HTTP) { - // We don't trust 302 responses to CONNECT from HTTP proxies. - EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED)); - EXPECT_FALSE(handle_.is_initialized()); - EXPECT_FALSE(handle_.socket()); - } else { - // Expect ProxyClientSocket to return the proxy's response, sanitized. - EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)); - EXPECT_TRUE(handle_.is_initialized()); - ASSERT_TRUE(handle_.socket()); - - const ProxyClientSocket* tunnel_socket = - static_cast<ProxyClientSocket*>(handle_.socket()); - const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo(); - const HttpResponseHeaders* headers = response->headers.get(); - - // Make sure Set-Cookie header was stripped. - EXPECT_FALSE(headers->HasHeader("set-cookie")); - - // Make sure Content-Length: 0 header was added. - EXPECT_TRUE(headers->HasHeaderValue("content-length", "0")); - - // Make sure Location header was included and correct. - std::string location; - EXPECT_TRUE(headers->IsRedirect(&location)); - EXPECT_EQ(location, redirectTarget); - } -} - -} // namespace net
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index f9a9adc..05996f9 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -228,8 +228,6 @@ std::unique_ptr<HttpNetworkSession> session_; - base::HistogramTester histogram_tester_; - base::FieldTrialList field_trial_list_; SpdyTestUtil spdy_util_; @@ -247,10 +245,10 @@ TEST_P(HttpProxyConnectJobTest, NoTunnel) { InitProxyDelegate(); - int loop_iterations = 0; for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { SCOPED_TRACE(io_mode); session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + base::HistogramTester histogram_tester; Initialize(base::span<MockRead>(), base::span<MockWrite>(), base::span<MockRead>(), base::span<MockWrite>(), io_mode); @@ -262,14 +260,12 @@ io_mode == SYNCHRONOUS); EXPECT_FALSE(proxy_delegate_->on_before_tunnel_request_called()); - ++loop_iterations; bool is_secure_proxy = GetParam() == HTTPS || GetParam() == SPDY; - histogram_tester_.ExpectTotalCount( + histogram_tester.ExpectTotalCount( "Net.HttpProxy.ConnectLatency.Insecure.Success", - is_secure_proxy ? 0 : loop_iterations); - histogram_tester_.ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Secure.Success", - is_secure_proxy ? loop_iterations : 0); + is_secure_proxy ? 0 : 1); + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Secure.Success", is_secure_proxy ? 1 : 0); } } @@ -861,10 +857,10 @@ // established. if (GetParam() == SPDY) return; - int loop_iterations = 0; for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { SCOPED_TRACE(io_mode); session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + base::HistogramTester histogram_tester; SequencedSocketData data; data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_CLOSED)); @@ -877,24 +873,21 @@ connect_job.get(), ERR_PROXY_CONNECTION_FAILED, io_mode == SYNCHRONOUS); bool is_secure_proxy = GetParam() == HTTPS; - ++loop_iterations; - histogram_tester_.ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Insecure.Error", - is_secure_proxy ? 0 : loop_iterations); - histogram_tester_.ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Secure.Error", - is_secure_proxy ? loop_iterations : 0); + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Insecure.Error", is_secure_proxy ? 0 : 1); + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Secure.Error", is_secure_proxy ? 1 : 0); } } TEST_P(HttpProxyConnectJobTest, SSLError) { if (GetParam() == HTTP) return; - int loop_iterations = 0; for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { SCOPED_TRACE(io_mode); session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + base::HistogramTester histogram_tester; SequencedSocketData data; data.set_connect_data(MockConnect(io_mode, OK)); @@ -913,10 +906,9 @@ ERR_PROXY_CERTIFICATE_INVALID, io_mode == SYNCHRONOUS); - ++loop_iterations; - histogram_tester_.ExpectTotalCount( - "Net.HttpProxy.ConnectLatency.Secure.Error", loop_iterations); - histogram_tester_.ExpectTotalCount( + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Secure.Error", 1); + histogram_tester.ExpectTotalCount( "Net.HttpProxy.ConnectLatency.Insecure.Error", 0); } } @@ -1048,6 +1040,136 @@ } } +TEST_P(HttpProxyConnectJobTest, SslClientAuth) { + if (GetParam() == HTTP) + return; + for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { + SCOPED_TRACE(io_mode); + session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + base::HistogramTester histogram_tester; + + SequencedSocketData socket_data(MockConnect(io_mode, OK), + base::span<const MockRead>(), + base::span<const MockWrite>()); + session_deps_.socket_factory->AddSocketDataProvider(&socket_data); + SSLSocketDataProvider ssl_data(io_mode, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); + if (GetParam() == SPDY) + InitializeSpdySsl(&ssl_data); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data); + + // Redirects in the HTTPS case return errors, but also return sockets. + TestConnectJobDelegate test_delegate; + std::unique_ptr<ConnectJob> connect_job = + CreateConnectJobForTunnel(&test_delegate); + test_delegate.StartJobExpectingResult(connect_job.get(), + ERR_SSL_CLIENT_AUTH_CERT_NEEDED, + io_mode == SYNCHRONOUS); + + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Secure.Error", 1); + histogram_tester.ExpectTotalCount( + "Net.HttpProxy.ConnectLatency.Insecure.Error", 0); + } +} + +TEST_P(HttpProxyConnectJobTest, TunnelSetupRedirect) { + const std::string kRedirectTarget = "https://foo.google.com/"; + + for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { + SCOPED_TRACE(io_mode); + session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + + const std::string kResponseText = + "HTTP/1.1 302 Found\r\n" + "Location: " + + kRedirectTarget + + "\r\n" + "Set-Cookie: foo=bar\r\n" + "\r\n"; + + MockWrite writes[] = { + MockWrite(io_mode, 0, + "CONNECT www.endpoint.test:443 HTTP/1.1\r\n" + "Host: www.endpoint.test:443\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; + MockRead reads[] = { + MockRead(io_mode, 1, kResponseText.c_str()), + }; + SpdyTestUtil spdy_util; + spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyConnect( + nullptr /* extra_headers */, 0 /* extra_header_count */, 1, + DEFAULT_PRIORITY, HostPortPair(kEndpointHost, 443))); + spdy::SpdySerializedFrame rst( + spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); + + MockWrite spdy_writes[] = { + CreateMockWrite(req, 0, io_mode), + CreateMockWrite(rst, 3, io_mode), + }; + + const char* const responseHeaders[] = { + "location", + kRedirectTarget.c_str(), + "set-cookie", + "foo=bar", + }; + const int responseHeadersSize = base::size(responseHeaders) / 2; + spdy::SpdySerializedFrame resp(spdy_util.ConstructSpdyReplyError( + "302", responseHeaders, responseHeadersSize, 1)); + MockRead spdy_reads[] = { + CreateMockRead(resp, 1, ASYNC), + MockRead(ASYNC, 0, 2), + }; + + Initialize(reads, writes, spdy_reads, spdy_writes, io_mode); + + // Redirects in the HTTPS case return errors, but also return sockets. + TestConnectJobDelegate test_delegate( + GetParam() == HTTP + ? TestConnectJobDelegate::SocketExpected::ON_SUCCESS_ONLY + : TestConnectJobDelegate::SocketExpected::ALWAYS); + std::unique_ptr<ConnectJob> connect_job = + CreateConnectJobForTunnel(&test_delegate); + + // H2 never completes synchronously. + bool expect_sync_result = (io_mode == SYNCHRONOUS && GetParam() != SPDY); + + if (GetParam() == HTTP) { + // We don't trust 302 responses to CONNECT from HTTP proxies. + test_delegate.StartJobExpectingResult( + connect_job.get(), ERR_TUNNEL_CONNECTION_FAILED, expect_sync_result); + EXPECT_FALSE(test_delegate.socket()); + } else { + // Expect ProxyClientSocket to return the proxy's response, sanitized. + test_delegate.StartJobExpectingResult( + connect_job.get(), ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, + expect_sync_result); + ASSERT_TRUE(test_delegate.socket()); + + const ProxyClientSocket* tunnel_socket = + static_cast<ProxyClientSocket*>(test_delegate.socket()); + const HttpResponseInfo* response = + tunnel_socket->GetConnectResponseInfo(); + const HttpResponseHeaders* headers = response->headers.get(); + + // Make sure Set-Cookie header was stripped. + EXPECT_FALSE(headers->HasHeader("set-cookie")); + + // Make sure Content-Length: 0 header was added. + EXPECT_TRUE(headers->HasHeaderValue("content-length", "0")); + + // Make sure Location header was included and correct. + std::string location; + EXPECT_TRUE(headers->IsRedirect(&location)); + EXPECT_EQ(location, kRedirectTarget); + } + + // Need to close the session to prevent reuse in the next loop iteration. + session_->spdy_session_pool()->CloseAllSessions(); + } +} + // Test timeouts in the case of an auth challenge and response. TEST_P(HttpProxyConnectJobTest, TestTimeoutsAuthChallenge) { // Wait until this amount of time before something times out.
diff --git a/net/network_error_logging/network_error_logging_service.h b/net/network_error_logging/network_error_logging_service.h index 09cffe32..600b70d2 100644 --- a/net/network_error_logging/network_error_logging_service.h +++ b/net/network_error_logging/network_error_logging_service.h
@@ -268,6 +268,7 @@ DISALLOW_COPY_AND_ASSIGN(NetworkErrorLoggingService); }; +// Persistent storage for NEL policies. class NET_EXPORT NetworkErrorLoggingService::PersistentNELStore { public: using NELPoliciesLoadedCallback =
diff --git a/net/network_error_logging/persistent_reporting_and_nel_store.h b/net/network_error_logging/persistent_reporting_and_nel_store.h new file mode 100644 index 0000000..ac97e912 --- /dev/null +++ b/net/network_error_logging/persistent_reporting_and_nel_store.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_NETWORK_ERROR_LOGGING_PERSISTENT_REPORTING_AND_NEL_STORE_H_ +#define NET_NETWORK_ERROR_LOGGING_PERSISTENT_REPORTING_AND_NEL_STORE_H_ + +#include "net/network_error_logging/network_error_logging_service.h" +#include "net/reporting/reporting_cache.h" + +namespace net { + +// Stores Reporting reports, Reporting clients, and NEL policies. +class NET_EXPORT PersistentReportingAndNELStore + : public ReportingCache::PersistentReportingStore, + public NetworkErrorLoggingService::PersistentNELStore {}; + +} // namespace net + +#endif // NET_NETWORK_ERROR_LOGGING_PERSISTENT_REPORTING_AND_NEL_STORE_H_
diff --git a/net/reporting/reporting_cache.h b/net/reporting/reporting_cache.h index 18ed839..fc610a1 100644 --- a/net/reporting/reporting_cache.h +++ b/net/reporting/reporting_cache.h
@@ -35,6 +35,8 @@ // "doomed", which will cause it to be deallocated once it is no longer pending. class NET_EXPORT ReportingCache { public: + class PersistentReportingStore; + // Information about the number of deliveries that we've attempted for each // origin and endpoint. struct ClientStatistics { @@ -216,6 +218,21 @@ const ReportingReport* report) const = 0; }; +// Persistent storage for Reporting reports and clients. +class NET_EXPORT ReportingCache::PersistentReportingStore { + public: + PersistentReportingStore() = default; + virtual ~PersistentReportingStore() = default; + + // TODO(chlily): methods to load, add, update, delete, etc. will be added. + + // Flushes the store. + virtual void Flush() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(PersistentReportingStore); +}; + } // namespace net #endif // NET_REPORTING_REPORTING_CACHE_H_
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 6e32c8d..9b346bb 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -71,10 +71,6 @@ // once https://crbug.com/458365 is resolved. static void SetSSLKeyLogger(std::unique_ptr<SSLKeyLogger> logger); - // ClearSessionCache clears the SSL session cache, used to resume SSL - // sessions. - static void ClearSessionCache(); - protected: void set_signed_cert_timestamps_received( bool signed_cert_timestamps_received) {
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index b7ab581..0abb7fd0 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -73,6 +73,7 @@ #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "net/test/gtest_util.h" +#include "net/test/key_util.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "net/test/test_data_directory.h" #include "net/test/test_with_scoped_task_environment.h" @@ -3361,42 +3362,6 @@ EXPECT_EQ(kProtoUnknown, sock_->GetNegotiatedProtocol()); } -namespace { - -bssl::UniquePtr<EVP_PKEY> LoadEVP_PKEY(const base::FilePath& filepath) { - std::string data; - if (!base::ReadFileToString(filepath, &data)) { - LOG(ERROR) << "Could not read private key file: " << filepath.value(); - return nullptr; - } - bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), - static_cast<int>(data.size()))); - if (!bio) { - LOG(ERROR) << "Could not allocate BIO for buffer?"; - return nullptr; - } - bssl::UniquePtr<EVP_PKEY> result( - PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); - if (!result) { - LOG(ERROR) << "Could not decode private key file: " << filepath.value(); - return nullptr; - } - return result; -} - -// Loads a PEM-encoded private key file into a SSLPrivateKey object. -// |filepath| is the private key file path. -// Returns the new SSLPrivateKey. -scoped_refptr<SSLPrivateKey> LoadPrivateKeyOpenSSL( - const base::FilePath& filepath) { - bssl::UniquePtr<EVP_PKEY> key = LoadEVP_PKEY(filepath); - if (!key) - return nullptr; - return WrapOpenSSLPrivateKey(std::move(key)); -} - -} // namespace - // Connect to a server requesting client authentication, do not send // any client certificates. It should refuse the connection. TEST_F(SSLClientSocketTest, NoCert) { @@ -3452,7 +3417,7 @@ ssl_config.send_client_cert = true; ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem"); ssl_config.client_private_key = - LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); + key_util::LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); int rv; ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv)); @@ -4252,7 +4217,7 @@ config.send_client_cert = true; config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem"); config.client_private_key = - LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); + key_util::LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); std::unique_ptr<SSLClientSocket> sock(CreateSSLClientSocket( std::move(transport), spawned_test_server()->host_port_pair(), config)); @@ -4348,7 +4313,7 @@ config.send_client_cert = true; config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem"); config.client_private_key = - LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); + key_util::LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key")); std::unique_ptr<SSLClientSocket> sock(CreateSSLClientSocket( std::move(transport), spawned_test_server()->host_port_pair(), config)); @@ -4737,7 +4702,7 @@ ImportCertFromFile(certs_dir, "ok_cert.pem"); ASSERT_TRUE(cert); bssl::UniquePtr<EVP_PKEY> pkey = - LoadEVP_PKEY(certs_dir.AppendASCII("ok_cert.pem")); + key_util::LoadEVP_PKEYFromPEM(certs_dir.AppendASCII("ok_cert.pem")); ASSERT_TRUE(pkey); std::unique_ptr<crypto::RSAPrivateKey> key = crypto::RSAPrivateKey::CreateFromKey(pkey.get());
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 160d20f..a896d1d 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -1540,6 +1540,118 @@ // auth over HTTP2. } +TEST_F(TransportClientSocketPoolTest, HttpTunnelSetupRedirect) { + const HostPortPair kEndpoint("host.test", 443); + const HostPortPair kProxy("proxy.test", 443); + + const std::string kRedirectTarget = "https://some.other.host.test/"; + + const std::string kResponseText = + "HTTP/1.1 302 Found\r\n" + "Location: " + + kRedirectTarget + + "\r\n" + "Set-Cookie: foo=bar\r\n" + "\r\n"; + + for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) { + SCOPED_TRACE(io_mode); + session_deps_.host_resolver->set_synchronous_mode(io_mode == SYNCHRONOUS); + + for (bool use_https_proxy : {false, true}) { + SCOPED_TRACE(use_https_proxy); + MockWrite writes[] = { + MockWrite(ASYNC, 0, + "CONNECT host.test:443 HTTP/1.1\r\n" + "Host: host.test:443\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"), + }; + MockRead reads[] = { + MockRead(ASYNC, 1, kResponseText.c_str()), + }; + + SequencedSocketData data(reads, writes); + tagging_client_socket_factory_.AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(ASYNC, OK); + tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl); + + ClientSocketHandle handle; + TestCompletionCallback callback; + + scoped_refptr<TransportSocketParams> transport_params = + base::MakeRefCounted<TransportSocketParams>( + kProxy, false /* disable_resolver_cache */, + OnHostResolutionCallback()); + + scoped_refptr<SSLSocketParams> proxy_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + transport_params, nullptr /* socks_proxy_params */, + nullptr /* http_proxy_params */, kProxy, GetSSLConfig(), + PRIVACY_MODE_DISABLED); + + scoped_refptr<HttpProxySocketParams> http_proxy_params = + base::MakeRefCounted<HttpProxySocketParams>( + use_https_proxy ? nullptr : transport_params, + use_https_proxy ? proxy_ssl_params : nullptr, + quic::QUIC_VERSION_UNSUPPORTED, kEndpoint, + false /* is_trusted_proxy */, true /* tunnel */, + TRAFFIC_ANNOTATION_FOR_TESTS); + scoped_refptr<SSLSocketParams> endpoint_ssl_params = + base::MakeRefCounted<SSLSocketParams>( + nullptr /* direct_params */, nullptr /* socks_proxy_params */, + http_proxy_params, kEndpoint, GetSSLConfig(), + PRIVACY_MODE_DISABLED); + + // Whether the proxy is HTTPS or not, always connecting to an HTTPS site + // through it. + scoped_refptr<TransportClientSocketPool::SocketParams> pool_params = + TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams( + endpoint_ssl_params); + + int rv = handle.Init( + ClientSocketPool::GroupId(kEndpoint, + ClientSocketPool::SocketType::kSsl, + false /* privacy_mode */), + pool_params, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), tagging_pool_.get(), + NetLogWithSource()); + rv = callback.GetResult(rv); + + if (!use_https_proxy) { + // We don't trust 302 responses to CONNECT from HTTP proxies. + EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED)); + EXPECT_FALSE(handle.is_initialized()); + EXPECT_FALSE(handle.release_pending_http_proxy_socket()); + } else { + // Expect ProxyClientSocket to return the proxy's response, sanitized. + EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)); + EXPECT_FALSE(handle.is_initialized()); + + std::unique_ptr<StreamSocket> stream_socket = + handle.release_pending_http_proxy_socket(); + ASSERT_TRUE(stream_socket); + const ProxyClientSocket* tunnel_socket = + static_cast<ProxyClientSocket*>(stream_socket.get()); + const HttpResponseInfo* response = + tunnel_socket->GetConnectResponseInfo(); + const HttpResponseHeaders* headers = response->headers.get(); + + // Make sure Set-Cookie header was stripped. + EXPECT_FALSE(headers->HasHeader("set-cookie")); + + // Make sure Content-Length: 0 header was added. + EXPECT_TRUE(headers->HasHeaderValue("content-length", "0")); + + // Make sure Location header was included and correct. + std::string location; + EXPECT_TRUE(headers->IsRedirect(&location)); + EXPECT_EQ(location, kRedirectTarget); + } + } + } +} + // Test that SocketTag passed into TransportClientSocketPool is applied to // returned sockets. #if defined(OS_ANDROID)
diff --git a/net/test/key_util.cc b/net/test/key_util.cc new file mode 100644 index 0000000..be701a9 --- /dev/null +++ b/net/test/key_util.cc
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/test/key_util.h" + +#include <string> +#include <utility> + +#include "base/files/file_util.h" +#include "base/logging.h" +#include "net/ssl/ssl_private_key.h" +#include "net/ssl/test_ssl_private_key.h" +#include "third_party/boringssl/src/include/openssl/bio.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/pem.h" + +namespace net { + +namespace key_util { + +bssl::UniquePtr<EVP_PKEY> LoadEVP_PKEYFromPEM(const base::FilePath& filepath) { + std::string data; + if (!base::ReadFileToString(filepath, &data)) { + LOG(ERROR) << "Could not read private key file: " << filepath.value(); + return nullptr; + } + bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(const_cast<char*>(data.data()), + static_cast<int>(data.size()))); + if (!bio) { + LOG(ERROR) << "Could not allocate BIO for buffer?"; + return nullptr; + } + bssl::UniquePtr<EVP_PKEY> result( + PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr)); + if (!result) { + LOG(ERROR) << "Could not decode private key file: " << filepath.value(); + return nullptr; + } + return result; +} + +scoped_refptr<SSLPrivateKey> LoadPrivateKeyOpenSSL( + const base::FilePath& filepath) { + bssl::UniquePtr<EVP_PKEY> key = LoadEVP_PKEYFromPEM(filepath); + if (!key) + return nullptr; + return WrapOpenSSLPrivateKey(std::move(key)); +} + +} // namespace key_util + +} // namespace net
diff --git a/net/test/key_util.h b/net/test/key_util.h new file mode 100644 index 0000000..edef8be --- /dev/null +++ b/net/test/key_util.h
@@ -0,0 +1,35 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_TEST_KEY_UTIL_H_ +#define NET_TEST_KEY_UTIL_H_ + +#include "base/memory/scoped_refptr.h" +#include "third_party/boringssl/src/include/openssl/base.h" + +namespace base { +class FilePath; +} + +namespace net { + +class SSLPrivateKey; + +namespace key_util { + +// Loads a PEM-encoded private key file from |filepath| into an EVP_PKEY object. +// Returns the new EVP_PKEY or nullptr on error. +bssl::UniquePtr<EVP_PKEY> LoadEVP_PKEYFromPEM(const base::FilePath& filepath); + +// Loads a PEM-encoded private key file into a SSLPrivateKey object. +// |filepath| is the private key file path. +// Returns the new SSLPrivateKey. +scoped_refptr<SSLPrivateKey> LoadPrivateKeyOpenSSL( + const base::FilePath& filepath); + +} // namespace key_util + +} // namespace net + +#endif // NET_TEST_KEY_UTIL_H_
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn index 5cc436aa..a292bda3 100644 --- a/remoting/signaling/BUILD.gn +++ b/remoting/signaling/BUILD.gn
@@ -10,6 +10,8 @@ "delegating_signal_strategy.h", "ftl_grpc_context.cc", "ftl_grpc_context.h", + "ftl_messaging_client.cc", + "ftl_messaging_client.h", "iq_sender.cc", "iq_sender.h", "jid_util.cc", @@ -59,6 +61,8 @@ sources -= [ "ftl_grpc_context.cc", "ftl_grpc_context.h", + "ftl_messaging_client.cc", + "ftl_messaging_client.h", "log_to_server.cc", "server_log_entry.cc", "xmpp_signal_strategy.cc", @@ -85,6 +89,8 @@ sources = [ "fake_signal_strategy.cc", "fake_signal_strategy.h", + "ftl_grpc_test_environment.cc", + "ftl_grpc_test_environment.h", "mock_signal_strategy.cc", "mock_signal_strategy.h", ] @@ -100,6 +106,7 @@ sources = [ "ftl_grpc_context_unittest.cc", + "ftl_messaging_client_unittest.cc", "iq_sender_unittest.cc", "jid_util_unittest.cc", "log_to_server_unittest.cc",
diff --git a/remoting/signaling/ftl_grpc_test_environment.cc b/remoting/signaling/ftl_grpc_test_environment.cc new file mode 100644 index 0000000..7465d80 --- /dev/null +++ b/remoting/signaling/ftl_grpc_test_environment.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/signaling/ftl_grpc_test_environment.h" + +#include <utility> + +#include "remoting/base/fake_oauth_token_getter.h" +#include "remoting/signaling/ftl_grpc_context.h" + +namespace remoting { +namespace test { + +FtlGrpcTestEnvironment::FtlGrpcTestEnvironment( + std::shared_ptr<grpc::ChannelInterface> channel) { + token_getter_ = std::make_unique<FakeOAuthTokenGetter>( + OAuthTokenGetter::Status::SUCCESS, "fake_user_email", + "fake_access_token"); + context_ = std::make_unique<FtlGrpcContext>(token_getter_.get()); + context_->SetChannelForTesting(channel); +} + +FtlGrpcTestEnvironment::~FtlGrpcTestEnvironment() = default; + +} // namespace test +} // namespace remoting
diff --git a/remoting/signaling/ftl_grpc_test_environment.h b/remoting/signaling/ftl_grpc_test_environment.h new file mode 100644 index 0000000..fd89119 --- /dev/null +++ b/remoting/signaling/ftl_grpc_test_environment.h
@@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_SIGNALING_FTL_GRPC_TEST_ENVIRONMENT_H_ +#define REMOTING_SIGNALING_FTL_GRPC_TEST_ENVIRONMENT_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/sequenced_task_runner.h" + +namespace grpc { +class ChannelInterface; +} // namespace grpc + +namespace remoting { + +class FakeOAuthTokenGetter; +class FtlGrpcContext; + +namespace test { + +// This class creates FtlGrpcContext with fake OAuthTokenGetter and connects it +// with the test channel. +class FtlGrpcTestEnvironment final { + public: + // TODO(yuweih): Typedef std::shared_ptr since it's not used in Chromium. + explicit FtlGrpcTestEnvironment( + std::shared_ptr<grpc::ChannelInterface> channel); + ~FtlGrpcTestEnvironment(); + + FtlGrpcContext* context() { return context_.get(); } + + private: + std::unique_ptr<FakeOAuthTokenGetter> token_getter_; + std::unique_ptr<FtlGrpcContext> context_; + + DISALLOW_COPY_AND_ASSIGN(FtlGrpcTestEnvironment); +}; + +} // namespace test +} // namespace remoting + +#endif // REMOTING_SIGNALING_FTL_GRPC_TEST_ENVIRONMENT_H_
diff --git a/remoting/signaling/ftl_messaging_client.cc b/remoting/signaling/ftl_messaging_client.cc new file mode 100644 index 0000000..106f71d --- /dev/null +++ b/remoting/signaling/ftl_messaging_client.cc
@@ -0,0 +1,110 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/signaling/ftl_messaging_client.h" + +#include <utility> + +#include "base/callback.h" +#include "base/logging.h" +#include "remoting/signaling/ftl_grpc_context.h" + +namespace remoting { + +namespace { + +void AddMessageToAckRequest(const ftl::InboxMessage& message, + ftl::AckMessagesRequest* request) { + ftl::ReceiverMessage* receiver_message = request->add_messages(); + receiver_message->set_message_id(message.message_id()); + receiver_message->set_allocated_receiver_id( + new ftl::Id(message.receiver_id())); +} + +} // namespace + +FtlMessagingClient::FtlMessagingClient(FtlGrpcContext* context) + : weak_factory_(this) { + context_ = context; + messaging_stub_ = Messaging::NewStub(context_->channel()); +} + +FtlMessagingClient::~FtlMessagingClient() = default; + +std::unique_ptr<FtlMessagingClient::MessageCallbackSubscription> +FtlMessagingClient::RegisterMessageCallback(const MessageCallback& callback) { + return callback_list_.Add(callback); +} + +void FtlMessagingClient::PullMessages(DoneCallback on_done) { + context_->ExecuteRpc( + base::BindOnce(&Messaging::Stub::AsyncPullMessages, + base::Unretained(messaging_stub_.get())), + ftl::PullMessagesRequest(), + base::BindOnce(&FtlMessagingClient::OnPullMessagesResponse, + weak_factory_.GetWeakPtr(), std::move(on_done))); +} + +void FtlMessagingClient::OnPullMessagesResponse( + DoneCallback on_done, + const grpc::Status& status, + const ftl::PullMessagesResponse& response) { + if (!status.ok()) { + LOG(ERROR) << "Failed to pull messages. " + << "Error code: " << status.error_code() + << ", message: " << status.error_message(); + std::move(on_done).Run(status); + return; + } + + ftl::AckMessagesRequest ack_request; + for (const auto& message : response.messages()) { + RunMessageCallbacks(message); + AddMessageToAckRequest(message, &ack_request); + } + + if (ack_request.messages_size() == 0) { + LOG(WARNING) << "No new message is received."; + std::move(on_done).Run(status); + return; + } + + // TODO(yuweih): May need retry logic. + VLOG(0) << "Acking " << ack_request.messages_size() << " messages"; + + AckMessages(ack_request, std::move(on_done)); +} + +void FtlMessagingClient::AckMessages(const ftl::AckMessagesRequest& request, + DoneCallback on_done) { + context_->ExecuteRpc( + base::BindOnce(&Messaging::Stub::AsyncAckMessages, + base::Unretained(messaging_stub_.get())), + request, + base::BindOnce(&FtlMessagingClient::OnAckMessagesResponse, + weak_factory_.GetWeakPtr(), std::move(on_done))); +} + +void FtlMessagingClient::OnAckMessagesResponse( + DoneCallback on_done, + const grpc::Status& status, + const ftl::AckMessagesResponse& response) { + std::move(on_done).Run(status); +} + +void FtlMessagingClient::RunMessageCallbacks(const ftl::InboxMessage& message) { + if (message.message_type() != + ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE) { + LOG(WARNING) << "Received message with unknown type: " + << message.message_type() + << ", sender: " << message.sender_id().id(); + return; + } + + ftl::ChromotingMessage chromoting_message; + chromoting_message.ParseFromString(message.message()); + callback_list_.Notify(message.sender_id().id(), chromoting_message.message()); +} + +} // namespace remoting
diff --git a/remoting/signaling/ftl_messaging_client.h b/remoting/signaling/ftl_messaging_client.h new file mode 100644 index 0000000..f5f7e42 --- /dev/null +++ b/remoting/signaling/ftl_messaging_client.h
@@ -0,0 +1,75 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_SIGNALING_FTL_MESSAGING_CLIENT_H_ +#define REMOTING_SIGNALING_FTL_MESSAGING_CLIENT_H_ + +#include <memory> +#include <string> + +#include "base/callback_forward.h" +#include "base/callback_list.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "remoting/signaling/ftl_services.grpc.pb.h" + +namespace remoting { + +class FtlGrpcContext; + +// A class for sending and receiving messages via the FTL API. +class FtlMessagingClient final { + public: + using MessageCallback = + base::RepeatingCallback<void(const std::string& sender_id, + const std::string& message)>; + using MessageCallbackSubscription = + base::CallbackList<void(const std::string&, + const std::string&)>::Subscription; + using DoneCallback = base::OnceCallback<void(const grpc::Status& status)>; + + explicit FtlMessagingClient(FtlGrpcContext* context); + ~FtlMessagingClient(); + + // Registers a callback which is run for each new message received. + // Simply delete the returned subscription object to unregister. The + // subscription object must be deleted before |this| is deleted. + std::unique_ptr<MessageCallbackSubscription> RegisterMessageCallback( + const MessageCallback& callback); + + // Retrieves messages from the user's inbox over slow path and calls the + // registered MessageCallback on every received message. + // |on_done| is called once the messages have been received and acked on the + // server's inbox. + void PullMessages(DoneCallback on_done); + + private: + using Messaging = + google::internal::communications::instantmessaging::v1::Messaging; + + void OnPullMessagesResponse(DoneCallback on_done, + const grpc::Status& status, + const ftl::PullMessagesResponse& response); + + void AckMessages(const ftl::AckMessagesRequest& request, + DoneCallback on_done); + + void OnAckMessagesResponse(DoneCallback on_done, + const grpc::Status& status, + const ftl::AckMessagesResponse& response); + + void RunMessageCallbacks(const ftl::InboxMessage& message); + + FtlGrpcContext* context_; + std::unique_ptr<Messaging::Stub> messaging_stub_; + base::CallbackList<void(const std::string&, const std::string&)> + callback_list_; + + base::WeakPtrFactory<FtlMessagingClient> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(FtlMessagingClient); +}; + +} // namespace remoting + +#endif // REMOTING_SIGNALING_FTL_MESSAGING_CLIENT_H_
diff --git a/remoting/signaling/ftl_messaging_client_unittest.cc b/remoting/signaling/ftl_messaging_client_unittest.cc new file mode 100644 index 0000000..5b27d4b --- /dev/null +++ b/remoting/signaling/ftl_messaging_client_unittest.cc
@@ -0,0 +1,234 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/signaling/ftl_messaging_client.h" + +#include <algorithm> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/logging.h" +#include "base/run_loop.h" +#include "base/task/post_task.h" +#include "base/test/bind_test_util.h" +#include "base/test/mock_callback.h" +#include "base/test/scoped_task_environment.h" +#include "remoting/signaling/ftl_grpc_test_environment.h" +#include "remoting/signaling/ftl_services.grpc.pb.h" +#include "remoting/signaling/grpc_support/grpc_async_test_server.h" +#include "remoting/signaling/grpc_support/grpc_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +namespace { + +using ::testing::Return; + +using PullMessagesResponder = + test::GrpcServerResponder<ftl::PullMessagesResponse>; +using AckMessagesResponder = + test::GrpcServerResponder<ftl::AckMessagesResponse>; + +constexpr char kFakeSenderId[] = "fake_sender@gmail.com"; +constexpr char kFakeReceiverId[] = "fake_receiver@gmail.com"; +constexpr char kMessage1Id[] = "msg_1"; +constexpr char kMessage2Id[] = "msg_1"; +constexpr char kMessage1Text[] = "Message 1"; +constexpr char kMessage2Text[] = "Message 2"; + +ftl::InboxMessage CreateMessage(const std::string& message_id, + const std::string& message_text) { + ftl::InboxMessage message; + message.mutable_sender_id()->set_id(kFakeSenderId); + message.mutable_receiver_id()->set_id(kFakeReceiverId); + message.set_message_type(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE); + message.set_message_id(message_id); + ftl::ChromotingMessage crd_message; + crd_message.set_message(message_text); + std::string serialized_message; + bool succeeded = crd_message.SerializeToString(&serialized_message); + EXPECT_TRUE(succeeded); + message.set_message(serialized_message); + return message; +} + +} // namespace + +class FtlMessagingClientTest : public testing::Test { + public: + void SetUp() override; + void TearDown() override; + + protected: + // Calls are scheduled sequentially and handled on the server thread. + void ServerWaitAndRespondToPullMessagesRequest( + const ftl::PullMessagesResponse& response, + const grpc::Status& status); + void ServerWaitAndRespondToAckMessagesRequest( + base::OnceCallback<grpc::Status(const ftl::AckMessagesRequest&)> handler, + base::OnceClosure on_done); + + std::unique_ptr<FtlMessagingClient> messaging_client_; + + private: + using Messaging = + google::internal::communications::instantmessaging::v1::Messaging; + + std::unique_ptr<test::GrpcAsyncTestServer> server_; + std::unique_ptr<test::FtlGrpcTestEnvironment> test_environment_; + scoped_refptr<base::SequencedTaskRunner> server_task_runner_; + base::test::ScopedTaskEnvironment scoped_task_environment_; +}; + +void FtlMessagingClientTest::SetUp() { + server_task_runner_ = + base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()}); + server_ = std::make_unique<test::GrpcAsyncTestServer>( + std::make_unique<Messaging::AsyncService>()); + test_environment_ = std::make_unique<test::FtlGrpcTestEnvironment>( + server_->CreateInProcessChannel()); + messaging_client_ = + std::make_unique<FtlMessagingClient>(test_environment_->context()); +} + +void FtlMessagingClientTest::TearDown() { + messaging_client_.reset(); + test_environment_.reset(); +} + +void FtlMessagingClientTest::ServerWaitAndRespondToPullMessagesRequest( + const ftl::PullMessagesResponse& response, + const grpc::Status& status) { + server_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + [](const ftl::PullMessagesResponse& response, + const grpc::Status& status, test::GrpcAsyncTestServer* server) { + ftl::PullMessagesRequest request; + auto responder = server->HandleRequest( + &Messaging::AsyncService::RequestPullMessages, &request); + responder->Respond(response, status); + }, + response, status, server_.get())); +} + +void FtlMessagingClientTest::ServerWaitAndRespondToAckMessagesRequest( + base::OnceCallback<grpc::Status(const ftl::AckMessagesRequest&)> handler, + base::OnceClosure on_done) { + server_task_runner_->PostTaskAndReply( + FROM_HERE, + base::BindOnce( + [](base::OnceCallback<grpc::Status(const ftl::AckMessagesRequest&)> + handler, + test::GrpcAsyncTestServer* server) { + ftl::AckMessagesRequest request; + auto responder = server->HandleRequest( + &Messaging::AsyncService::RequestAckMessages, &request); + grpc::Status status = std::move(handler).Run(request); + responder->Respond(ftl::AckMessagesResponse(), status); + }, + std::move(handler), server_.get()), + std::move(on_done)); +} + +TEST_F(FtlMessagingClientTest, TestPullMessages_ReturnsNoMessage) { + base::RunLoop run_loop; + auto subscription = messaging_client_->RegisterMessageCallback( + base::BindRepeating([](const std::string& sender_id, + const std::string& message) { NOTREACHED(); })); + messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::OK, &run_loop)); + ServerWaitAndRespondToPullMessagesRequest(ftl::PullMessagesResponse(), + grpc::Status::OK); + run_loop.Run(); +} + +TEST_F(FtlMessagingClientTest, TestPullMessages_Unauthenticated) { + base::RunLoop run_loop; + auto subscription = messaging_client_->RegisterMessageCallback( + base::BindRepeating([](const std::string& sender_id, + const std::string& message) { NOTREACHED(); })); + messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::UNAUTHENTICATED, &run_loop)); + ServerWaitAndRespondToPullMessagesRequest( + ftl::PullMessagesResponse(), + grpc::Status(grpc::StatusCode::UNAUTHENTICATED, "Unauthenticated")); + run_loop.Run(); +} + +TEST_F(FtlMessagingClientTest, TestPullMessages_IgnoresUnknownMessageType) { + base::RunLoop run_loop; + + auto subscription = messaging_client_->RegisterMessageCallback( + base::BindRepeating([](const std::string& sender_id, + const std::string& message) { NOTREACHED(); })); + + messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::OK, &run_loop)); + + ftl::PullMessagesResponse response; + ftl::InboxMessage* message = response.add_messages(); + message->set_message_id(kMessage1Id); + message->mutable_sender_id()->set_id(kFakeSenderId); + message->mutable_receiver_id()->set_id(kFakeReceiverId); + message->set_message_type(ftl::InboxMessage_MessageType_UNKNOWN); + ServerWaitAndRespondToPullMessagesRequest(response, grpc::Status::OK); + ServerWaitAndRespondToAckMessagesRequest( + base::BindLambdaForTesting([&](const ftl::AckMessagesRequest& request) { + EXPECT_EQ(1, request.messages_size()); + EXPECT_EQ(kFakeReceiverId, request.messages(0).receiver_id().id()); + EXPECT_EQ(kMessage1Id, request.messages(0).message_id()); + return grpc::Status::OK; + }), + base::DoNothing()); + run_loop.Run(); +} + +TEST_F(FtlMessagingClientTest, TestPullMessages_ReturnsAndAcksTwoMessages) { + base::RunLoop run_loop; + + base::MockCallback<base::RepeatingCallback<void(const std::string& sender_id, + const std::string& message)>> + mock_on_incoming_msg; + + EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kMessage1Text)) + .WillOnce(Return()); + EXPECT_CALL(mock_on_incoming_msg, Run(kFakeSenderId, kMessage2Text)) + .WillOnce(Return()); + + auto subscription = + messaging_client_->RegisterMessageCallback(mock_on_incoming_msg.Get()); + + messaging_client_->PullMessages(test::CheckStatusThenQuitRunLoopCallback( + FROM_HERE, grpc::StatusCode::OK, &run_loop)); + + ftl::PullMessagesResponse pull_messages_response; + ftl::InboxMessage* message = pull_messages_response.add_messages(); + *message = CreateMessage(kMessage1Id, kMessage1Text); + message = pull_messages_response.add_messages(); + *message = CreateMessage(kMessage2Id, kMessage2Text); + ServerWaitAndRespondToPullMessagesRequest(pull_messages_response, + grpc::Status::OK); + + ServerWaitAndRespondToAckMessagesRequest( + base::BindLambdaForTesting([&](const ftl::AckMessagesRequest& request) { + EXPECT_EQ(2, request.messages_size()); + EXPECT_EQ(kFakeReceiverId, request.messages(0).receiver_id().id()); + EXPECT_EQ(kFakeReceiverId, request.messages(1).receiver_id().id()); + EXPECT_EQ(kMessage1Id, request.messages(0).message_id()); + EXPECT_EQ(kMessage2Id, request.messages(1).message_id()); + return grpc::Status::OK; + }), + base::DoNothing()); + + run_loop.Run(); +} + +} // namespace remoting
diff --git a/remoting/test/ftl_signaling_playground.cc b/remoting/test/ftl_signaling_playground.cc index bf0056be..01702d2 100644 --- a/remoting/test/ftl_signaling_playground.cc +++ b/remoting/test/ftl_signaling_playground.cc
@@ -148,7 +148,12 @@ ftl_context_ = std::make_unique<FtlGrpcContext>(token_getter_.get()); peer_to_peer_stub_ = PeerToPeer::NewStub(ftl_context_->channel()); registration_stub_ = Registration::NewStub(ftl_context_->channel()); - messaging_stub_ = Messaging::NewStub(ftl_context_->channel()); + + message_subscription_.reset(); + messaging_client_ = std::make_unique<FtlMessagingClient>(ftl_context_.get()); + message_subscription_ = messaging_client_->RegisterMessageCallback( + base::BindRepeating(&FtlSignalingPlayground::OnMessageReceived, + weak_factory_.GetWeakPtr())); } void FtlSignalingPlayground::AuthenticateAndResetServices() { @@ -317,88 +322,34 @@ } void FtlSignalingPlayground::PullMessages(base::OnceClosure on_done) { - DCHECK(messaging_stub_); + DCHECK(messaging_client_); VLOG(0) << "Running PullMessages..."; - ftl_context_->ExecuteRpc( - base::BindOnce(&Messaging::Stub::AsyncPullMessages, - base::Unretained(messaging_stub_.get())), - ftl::PullMessagesRequest(), + messaging_client_->PullMessages( base::BindOnce(&FtlSignalingPlayground::OnPullMessagesResponse, weak_factory_.GetWeakPtr(), std::move(on_done))); } void FtlSignalingPlayground::OnPullMessagesResponse( base::OnceClosure on_done, - const grpc::Status& status, - const ftl::PullMessagesResponse& response) { + const grpc::Status& status) { if (!status.ok()) { if (status.error_code() == grpc::StatusCode::UNAUTHENTICATED) { fprintf(stderr, "Please run SignInGaia first\n"); } else { HandleGrpcStatusError(status); } - std::move(on_done).Run(); - return; - } - - ftl::AckMessagesRequest ack_request; - printf("pull_all=%d\n", response.pulled_all()); - for (const auto& message : response.messages()) { - printf( - "Message:\n" - " message_type=%d\n" - " message_id=%s\n" - " sender_id.id=%s\n" - " receiver_id.id=%s\n", - message.message_type(), message.message_id().c_str(), - message.sender_id().id().c_str(), message.receiver_id().id().c_str()); - - if (message.message_type() == - ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE) { - ftl::ChromotingMessage chromoting_message; - chromoting_message.ParseFromString(message.message()); - printf(" message(ChromotingMessage deserialized)=%s\n", - chromoting_message.message().c_str()); - } else { - std::string message_base64; - base::Base64Encode(message.message(), &message_base64); - printf(" message(base64)=%s\n", message_base64.c_str()); - } - - ftl::ReceiverMessage* receiver_message = ack_request.add_messages(); - receiver_message->set_message_id(message.message_id()); - receiver_message->set_allocated_receiver_id( - new ftl::Id(message.receiver_id())); - } - - if (ack_request.messages_size() == 0) { - VLOG(0) << "No message has been received"; - std::move(on_done).Run(); - return; - } - - // TODO(yuweih): Might need retry logic. - VLOG(0) << "Acking " << ack_request.messages_size() << " messages"; - - ftl_context_->ExecuteRpc( - base::BindOnce(&Messaging::Stub::AsyncAckMessages, - base::Unretained(messaging_stub_.get())), - ack_request, - base::BindOnce(&FtlSignalingPlayground::OnAckMessagesResponse, - weak_factory_.GetWeakPtr(), std::move(on_done))); -} - -void FtlSignalingPlayground::OnAckMessagesResponse( - base::OnceClosure on_done, - const grpc::Status& status, - const ftl::AckMessagesResponse& response) { - if (status.ok()) { - VLOG(0) << "Messages acked"; - } else { - HandleGrpcStatusError(status); } std::move(on_done).Run(); } +void FtlSignalingPlayground::OnMessageReceived(const std::string& sender_id, + const std::string& message) { + printf( + "Received message:\n" + " Sender ID=%s\n" + " Message=%s\n", + sender_id.c_str(), message.c_str()); +} + } // namespace remoting
diff --git a/remoting/test/ftl_signaling_playground.h b/remoting/test/ftl_signaling_playground.h index 799c54f55..910ffa5 100644 --- a/remoting/test/ftl_signaling_playground.h +++ b/remoting/test/ftl_signaling_playground.h
@@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "remoting/base/oauth_token_getter.h" #include "remoting/signaling/ftl_grpc_context.h" +#include "remoting/signaling/ftl_messaging_client.h" namespace remoting { @@ -36,8 +37,6 @@ google::internal::communications::instantmessaging::v1::PeerToPeer; using Registration = google::internal::communications::instantmessaging::v1::Registration; - using Messaging = - google::internal::communications::instantmessaging::v1::Messaging; void StartLoop(); void ResetServices(); @@ -60,20 +59,22 @@ void PullMessages(base::OnceClosure on_done); void OnPullMessagesResponse(base::OnceClosure on_done, - const grpc::Status& status, - const ftl::PullMessagesResponse& response); - void OnAckMessagesResponse(base::OnceClosure on_done, - const grpc::Status& status, - const ftl::AckMessagesResponse& response); + const grpc::Status& status); + void OnMessageReceived(const std::string& sender_id, + const std::string& message); std::unique_ptr<test::TestTokenStorage> storage_; std::unique_ptr<TestOAuthTokenGetterFactory> token_getter_factory_; std::unique_ptr<OAuthTokenGetter> token_getter_; std::unique_ptr<FtlGrpcContext> ftl_context_; + // Subscription must be deleted before |messaging_client_|. + std::unique_ptr<FtlMessagingClient> messaging_client_; + std::unique_ptr<FtlMessagingClient::MessageCallbackSubscription> + message_subscription_; + std::unique_ptr<PeerToPeer::Stub> peer_to_peer_stub_; std::unique_ptr<Registration::Stub> registration_stub_; - std::unique_ptr<Messaging::Stub> messaging_stub_; base::WeakPtrFactory<FtlSignalingPlayground> weak_factory_; DISALLOW_COPY_AND_ASSIGN(FtlSignalingPlayground);
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index f689fb9..b3bf7a5 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -70,7 +70,6 @@ IdentityManager::~IdentityManager() { signin_manager_->ClearObserver(); - signin_manager_->Shutdown(); token_service_->RemoveObserver(this); token_service_->RemoveDiagnosticsObserver(this); account_tracker_service_->RemoveObserver(this);
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc index 665a56b..dde8a50 100644 --- a/services/identity/public/cpp/identity_test_environment.cc +++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -42,19 +42,10 @@ class IdentityManagerDependenciesOwner { public: IdentityManagerDependenciesOwner( - network::TestURLLoaderFactory* test_url_loader_factory, sync_preferences::TestingPrefServiceSyncable* pref_service, TestSigninClient* test_signin_client); ~IdentityManagerDependenciesOwner(); - AccountTrackerService* account_tracker_service(); - - AccountFetcherService* account_fetcher_service(); - - FakeProfileOAuth2TokenService* token_service(); - - GaiaCookieManagerService* gaia_cookie_manager_service(); - sync_preferences::TestingPrefServiceSyncable* pref_service(); TestSigninClient* signin_client(); @@ -69,16 +60,11 @@ std::unique_ptr<TestSigninClient> owned_signin_client_; TestSigninClient* raw_signin_client_ = nullptr; - AccountTrackerService account_tracker_; - AccountFetcherService account_fetcher_; - FakeProfileOAuth2TokenService token_service_; - std::unique_ptr<GaiaCookieManagerService> gaia_cookie_manager_service_; DISALLOW_COPY_AND_ASSIGN(IdentityManagerDependenciesOwner); }; IdentityManagerDependenciesOwner::IdentityManagerDependenciesOwner( - network::TestURLLoaderFactory* test_url_loader_factory, sync_preferences::TestingPrefServiceSyncable* pref_service_param, TestSigninClient* signin_client_param) : owned_pref_service_( @@ -91,57 +77,9 @@ signin_client_param ? nullptr : std::make_unique<TestSigninClient>(pref_service())), - raw_signin_client_(signin_client_param), - token_service_(pref_service()) { - if (test_url_loader_factory != nullptr) { - gaia_cookie_manager_service_ = std::make_unique<GaiaCookieManagerService>( - &token_service_, signin_client(), - base::BindRepeating( - [](network::TestURLLoaderFactory* test_url_loader_factory) - -> scoped_refptr<network::SharedURLLoaderFactory> { - return test_url_loader_factory->GetSafeWeakWrapper(); - }, - test_url_loader_factory)); - } else { - gaia_cookie_manager_service_ = std::make_unique<GaiaCookieManagerService>( - &token_service_, signin_client()); - } - AccountTrackerService::RegisterPrefs(pref_service()->registry()); - AccountFetcherService::RegisterPrefs(pref_service()->registry()); - ProfileOAuth2TokenService::RegisterProfilePrefs(pref_service()->registry()); - SigninManagerBase::RegisterProfilePrefs(pref_service()->registry()); - SigninManagerBase::RegisterPrefs(pref_service()->registry()); + raw_signin_client_(signin_client_param) {} - account_tracker_.Initialize(pref_service(), base::FilePath()); - account_fetcher_.Initialize( - signin_client(), &token_service_, &account_tracker_, - std::make_unique<image_fetcher::FakeImageDecoder>()); -} - -IdentityManagerDependenciesOwner::~IdentityManagerDependenciesOwner() { - account_fetcher_.Shutdown(); - account_tracker_.Shutdown(); -} - -AccountTrackerService* -IdentityManagerDependenciesOwner::account_tracker_service() { - return &account_tracker_; -} - -AccountFetcherService* -IdentityManagerDependenciesOwner::account_fetcher_service() { - return &account_fetcher_; -} - -FakeProfileOAuth2TokenService* -IdentityManagerDependenciesOwner::token_service() { - return &token_service_; -} - -GaiaCookieManagerService* -IdentityManagerDependenciesOwner::gaia_cookie_manager_service() { - return gaia_cookie_manager_service_.get(); -} +IdentityManagerDependenciesOwner::~IdentityManagerDependenciesOwner() = default; sync_preferences::TestingPrefServiceSyncable* IdentityManagerDependenciesOwner::pref_service() { @@ -172,7 +110,6 @@ test_url_loader_factory, account_consistency, std::make_unique<IdentityManagerDependenciesOwner>( - test_url_loader_factory, pref_service, test_signin_client), /*identity_manager=*/nullptr) {} @@ -222,14 +159,50 @@ gaia_cookie_manager_service || identity_manager)); dependencies_owner_ = std::move(dependencies_owner); - - account_tracker_service_ = dependencies_owner_->account_tracker_service(); - account_fetcher_service_ = dependencies_owner_->account_fetcher_service(); - token_service_ = dependencies_owner_->token_service(); - gaia_cookie_manager_service_ = - dependencies_owner_->gaia_cookie_manager_service(); - pref_service_ = dependencies_owner_->pref_service(); test_signin_client = dependencies_owner_->signin_client(); + sync_preferences::TestingPrefServiceSyncable* test_pref_service = + dependencies_owner_->pref_service(); + + pref_service_ = test_pref_service; + + AccountTrackerService::RegisterPrefs(test_pref_service->registry()); + AccountFetcherService::RegisterPrefs(test_pref_service->registry()); + ProfileOAuth2TokenService::RegisterProfilePrefs( + test_pref_service->registry()); + SigninManagerBase::RegisterProfilePrefs(test_pref_service->registry()); + SigninManagerBase::RegisterPrefs(test_pref_service->registry()); + + owned_token_service_ = + std::make_unique<FakeProfileOAuth2TokenService>(test_pref_service); + token_service_ = owned_token_service_.get(); + + owned_account_tracker_service_ = std::make_unique<AccountTrackerService>(); + owned_account_tracker_service_->Initialize(test_pref_service, + base::FilePath()); + account_tracker_service_ = owned_account_tracker_service_.get(); + + owned_account_fetcher_service_ = std::make_unique<AccountFetcherService>(); + owned_account_fetcher_service_->Initialize( + test_signin_client, token_service_, account_tracker_service_, + std::make_unique<image_fetcher::FakeImageDecoder>()); + account_fetcher_service_ = owned_account_fetcher_service_.get(); + + if (test_url_loader_factory != nullptr) { + owned_gaia_cookie_manager_service_ = + std::make_unique<GaiaCookieManagerService>( + token_service_, test_signin_client, + base::BindRepeating( + [](network::TestURLLoaderFactory* test_url_loader_factory) + -> scoped_refptr<network::SharedURLLoaderFactory> { + return test_url_loader_factory->GetSafeWeakWrapper(); + }, + test_url_loader_factory)); + } else { + owned_gaia_cookie_manager_service_ = + std::make_unique<GaiaCookieManagerService>(token_service_, + test_signin_client); + } + gaia_cookie_manager_service_ = owned_gaia_cookie_manager_service_.get(); } else { DCHECK(pref_service_ && account_tracker_service && account_fetcher_service && token_service && @@ -303,6 +276,14 @@ } IdentityTestEnvironment::~IdentityTestEnvironment() { + if (owned_account_fetcher_service_) { + owned_account_fetcher_service_->Shutdown(); + } + + if (owned_account_tracker_service_) { + owned_account_tracker_service_->Shutdown(); + } + identity_manager()->RemoveDiagnosticsObserver(this); }
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h index f1c30fe1..0828179 100644 --- a/services/identity/public/cpp/identity_test_environment.h +++ b/services/identity/public/cpp/identity_test_environment.h
@@ -371,6 +371,22 @@ // IdentityTestEnvironment's constructor. std::unique_ptr<TestSigninClient> owned_signin_client_; + // This will be null if a AccountTrackerService was provided to + // IdentityTestEnvironment's constructor. + std::unique_ptr<AccountTrackerService> owned_account_tracker_service_; + + // This will be null if a AccountFetcherService was provided to + // IdentityTestEnvironment's constructor. + std::unique_ptr<AccountFetcherService> owned_account_fetcher_service_; + + // This will be null if a FakeProfileOAuth2TokenService was provided to + // IdentityTestEnvironment's constructor. + std::unique_ptr<FakeProfileOAuth2TokenService> owned_token_service_; + + // This will be null if a GaiaCookieManagerService was provided to + // IdentityTestEnvironment's constructor. + std::unique_ptr<GaiaCookieManagerService> owned_gaia_cookie_manager_service_; + // Depending on which constructor is used, exactly one of these will be // non-null. See the documentation on the constructor wherein IdentityManager // is passed in for required lifetime invariants in that case.
diff --git a/services/network/network_service_unittest.cc b/services/network/network_service_unittest.cc index c08ae8f..fcc07ea 100644 --- a/services/network/network_service_unittest.cc +++ b/services/network/network_service_unittest.cc
@@ -1312,9 +1312,9 @@ public: NetworkChangeTest() : scoped_task_environment_( - base::test::ScopedTaskEnvironment::MainThreadType::IO) { - service_ = NetworkService::CreateForTesting(); - } + base::test::ScopedTaskEnvironment::MainThreadType::IO), + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), + service_(NetworkService::CreateForTesting()) {} ~NetworkChangeTest() override {} @@ -1322,12 +1322,13 @@ private: base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; std::unique_ptr<NetworkService> service_; }; -// mojom:NetworkChangeManager isn't supported on these platforms. +// mojom:NetworkChangeManager isn't supported on iOS. // See the same ifdef in CreateNetworkChangeNotifierIfNeeded. -#if defined(OS_CHROMEOS) || defined(OS_FUCHSIA) || defined(OS_IOS) +#if defined(OS_IOS) #define MAYBE_NetworkChangeManagerRequest DISABLED_NetworkChangeManagerRequest #else #define MAYBE_NetworkChangeManagerRequest NetworkChangeManagerRequest @@ -1344,6 +1345,7 @@ NetworkServiceNetworkChangeTest() : task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO), + network_change_notifier_(net::NetworkChangeNotifier::CreateMock()), service_(NetworkService::CreateForTesting( test_connector_factory_.RegisterInstance(kNetworkServiceName))) { test_connector_factory_.GetDefaultConnector()->BindInterface( @@ -1354,13 +1356,10 @@ mojom::NetworkService* service() { return network_service_.get(); } - void SimulateNetworkChange() { - // This posts a task to simulate a network change notification - } - private: base::test::ScopedTaskEnvironment task_environment_; service_manager::TestConnectorFactory test_connector_factory_; + std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; std::unique_ptr<NetworkService> service_; mojom::NetworkServicePtr network_service_;
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc index add4f1cf..53d1069 100644 --- a/services/tracing/public/cpp/perfetto/producer_client.cc +++ b/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -136,8 +136,15 @@ FROM_HERE, base::BindOnce(std::move(callback), std::move(producer_client), mojo::MakeRequest(&producer_host_))); - for (auto* data_source : data_sources_) { - RegisterDataSourceWithHost(data_source); + // TODO(oysteine) We register the data sources in reverse as a temporary + // workaround to make sure that the TraceEventDataSource is registered + // *after* the MetadataSource, as the logic which waits for trace clients + // to be "ready" (in the tracing coordinator) waits for the TraceLog to + // be enabled, which is done by the TraceEventDataSource. We need to register + // the MetadataSource first to ensure that it's also ready. Once the + // Perfetto Observer interface is ready, we can remove this. + for (auto it = data_sources_.rbegin(); it != data_sources_.rend(); ++it) { + RegisterDataSourceWithHost(*it); } }
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index 520f4567..608183a 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -32,6 +32,10 @@ #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" +#if DCHECK_IS_ON() +#include "base/task/task_scheduler/scheduler_lock_impl.h" +#endif + using TraceLog = base::trace_event::TraceLog; using TraceEvent = base::trace_event::TraceEvent; using TraceConfig = base::trace_event::TraceConfig; @@ -374,6 +378,16 @@ } } +#if DCHECK_IS_ON() + // Trace events emitted by the task queue itself can happen while the task + // queue is locked, posting to it reentrantly would deadlock so these events + // need to be flagged so we can avoid PostTasks while they're being emitted. + // TODO(oysteine): Avoid PostTasks for events with this flag set. + if (!(trace_event->flags() & TRACE_EVENT_FLAG_DISALLOW_POSTTASK)) { + base::internal::SchedulerLockImpl::AssertNoLockHeldOnCurrentThread(); + } +#endif + if (!thread_local_event_sink) { thread_local_event_sink = GetInstance()->CreateThreadLocalEventSink(thread_will_flush);
diff --git a/services/tracing/public/cpp/trace_event_args_whitelist.cc b/services/tracing/public/cpp/trace_event_args_whitelist.cc index c370c774..908d35b 100644 --- a/services/tracing/public/cpp/trace_event_args_whitelist.cc +++ b/services/tracing/public/cpp/trace_event_args_whitelist.cc
@@ -33,6 +33,7 @@ "class", "line", "should_background", "has_pending_views", "bytes_allocated", nullptr}; const char* const kV8GCAllowedArgs[] = {"num_items", "num_tasks", nullptr}; +const char* const kTopLevelFlowAllowedArgs[] = {"task_queue_name", nullptr}; const WhitelistEntry kEventArgsWhitelist[] = { {"__metadata", "thread_name", nullptr}, @@ -63,6 +64,8 @@ {"ui", "CachedFontLinkSettings::GetLinkedFonts", nullptr}, {"ui", "QueryLinkedFontsFromRegistry", nullptr}, {"ui", "UserEvent", nullptr}, + {TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), "SequenceManager::PostTask", + kTopLevelFlowAllowedArgs}, {nullptr, nullptr, nullptr}}; const char* kMetadataWhitelist[] = {"chrome-bitness",
diff --git a/services/viz/privileged/cpp/OWNERS b/services/viz/privileged/cpp/OWNERS index 5bbfa69c..868378c 100644 --- a/services/viz/privileged/cpp/OWNERS +++ b/services/viz/privileged/cpp/OWNERS
@@ -1,2 +1,4 @@ per-file *.typemap=set noparent per-file *.typemap=file://ipc/SECURITY_OWNERS +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/services/viz/privileged/cpp/overlay_strategy.typemap b/services/viz/privileged/cpp/overlay_strategy.typemap new file mode 100644 index 0000000..216509d --- /dev/null +++ b/services/viz/privileged/cpp/overlay_strategy.typemap
@@ -0,0 +1,15 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = + "//services/viz/privileged/interfaces/compositing/overlay_strategy.mojom" +public_headers = [ "//components/viz/common/display/overlay_strategy.h" ] +traits_headers = + [ "//services/viz/privileged/cpp/overlay_strategy_struct_traits.h" ] +public_deps = [ + "//components/viz/common", + #"//services/viz/privileged/interfaces/compositing" +] + +type_mappings = [ "viz.mojom.OverlayStrategy=viz::OverlayStrategy" ]
diff --git a/services/viz/privileged/cpp/overlay_strategy_struct_traits.h b/services/viz/privileged/cpp/overlay_strategy_struct_traits.h new file mode 100644 index 0000000..a89e5be --- /dev/null +++ b/services/viz/privileged/cpp/overlay_strategy_struct_traits.h
@@ -0,0 +1,54 @@ +// Copyright 2016 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_VIZ_PRIVILEGED_CPP_OVERLAY_STRATEGY_STRUCT_TRAITS_H_ +#define SERVICES_VIZ_PRIVILEGED_CPP_OVERLAY_STRATEGY_STRUCT_TRAITS_H_ + +#include "components/viz/common/display/overlay_strategy.h" +#include "services/viz/privileged/interfaces/compositing/overlay_strategy.mojom.h" + +namespace mojo { + +template <> +struct EnumTraits<viz::mojom::OverlayStrategy, viz::OverlayStrategy> { + static viz::mojom::OverlayStrategy ToMojom(viz::OverlayStrategy reason) { + switch (reason) { + case viz::OverlayStrategy::kFullscreen: + return viz::mojom::OverlayStrategy::kFullscreen; + case viz::OverlayStrategy::kSingleOnTop: + return viz::mojom::OverlayStrategy::kSingleOnTop; + case viz::OverlayStrategy::kUnderlay: + return viz::mojom::OverlayStrategy::kUnderlay; + case viz::OverlayStrategy::kUnderlayCast: + return viz::mojom::OverlayStrategy::kUnderlayCast; + default: + break; + } + NOTREACHED(); + return viz::mojom::OverlayStrategy::kFullscreen; + } + + static bool FromMojom(viz::mojom::OverlayStrategy reason, + viz::OverlayStrategy* out) { + switch (reason) { + case viz::mojom::OverlayStrategy::kFullscreen: + *out = viz::OverlayStrategy::kFullscreen; + return true; + case viz::mojom::OverlayStrategy::kSingleOnTop: + *out = viz::OverlayStrategy::kSingleOnTop; + return true; + case viz::mojom::OverlayStrategy::kUnderlay: + *out = viz::OverlayStrategy::kUnderlay; + return true; + case viz::mojom::OverlayStrategy::kUnderlayCast: + *out = viz::OverlayStrategy::kUnderlayCast; + return true; + } + return false; + } +}; + +} // namespace mojo + +#endif // SERVICES_VIZ_PRIVILEGED_CPP_OVERLAY_STRATEGY_STRUCT_TRAITS_H_
diff --git a/services/viz/privileged/cpp/typemaps.gni b/services/viz/privileged/cpp/typemaps.gni index f838c08a6b..fed7dfa 100644 --- a/services/viz/privileged/cpp/typemaps.gni +++ b/services/viz/privileged/cpp/typemaps.gni
@@ -1 +1,4 @@ -typemaps = [ "//services/viz/privileged/cpp/context_lost_reason.typemap" ] +typemaps = [ + "//services/viz/privileged/cpp/context_lost_reason.typemap", + "//services/viz/privileged/cpp/overlay_strategy.typemap", +]
diff --git a/services/viz/privileged/interfaces/compositing/BUILD.gn b/services/viz/privileged/interfaces/compositing/BUILD.gn index e8b8c4f8..24852e6 100644 --- a/services/viz/privileged/interfaces/compositing/BUILD.gn +++ b/services/viz/privileged/interfaces/compositing/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//mojo/public/tools/bindings/mojom.gni") +import("//ui/ozone/ozone.gni") mojom("compositing") { sources = [ @@ -11,6 +12,7 @@ "frame_sink_manager.mojom", "frame_sink_video_capture.mojom", "layered_window_updater.mojom", + "overlay_strategy.mojom", "renderer_settings.mojom", ] @@ -25,4 +27,9 @@ "//ui/gfx/mojo", "//ui/latency/mojo:interfaces", ] + + enabled_features = [] + if (use_ozone) { + enabled_features += [ "use_ozone" ] + } }
diff --git a/services/viz/privileged/interfaces/compositing/display_private.mojom b/services/viz/privileged/interfaces/compositing/display_private.mojom index 5c0b20c..4c29f4e 100644 --- a/services/viz/privileged/interfaces/compositing/display_private.mojom +++ b/services/viz/privileged/interfaces/compositing/display_private.mojom
@@ -58,10 +58,6 @@ }; interface DisplayClient { - // Notifies that a swap has occured after some latency info with snapshot - // component reached the display. - DidSwapAfterSnapshotRequestReceived(array<ui.mojom.LatencyInfo> latency_info); - [EnableIf=is_mac] OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params);
diff --git a/services/viz/privileged/interfaces/compositing/overlay_strategy.mojom b/services/viz/privileged/interfaces/compositing/overlay_strategy.mojom new file mode 100644 index 0000000..a98cc61 --- /dev/null +++ b/services/viz/privileged/interfaces/compositing/overlay_strategy.mojom
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module viz.mojom; + +// Corresponds to viz::OverlayStrategy. Note that OverlayStrategy::kUnknown and +// OverlayStrategy::kNoStrategyUsed aren't defined for the mojo enum. These +// values don't correspond to usable strategies so they don't need to be sent +// over IPC. +enum OverlayStrategy { + kFullscreen, + kSingleOnTop, + kUnderlay, + kUnderlayCast, +};
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings.mojom b/services/viz/privileged/interfaces/compositing/renderer_settings.mojom index 60118bf..9b7ffd00 100644 --- a/services/viz/privileged/interfaces/compositing/renderer_settings.mojom +++ b/services/viz/privileged/interfaces/compositing/renderer_settings.mojom
@@ -4,6 +4,7 @@ module viz.mojom; +import "services/viz/privileged/interfaces/compositing/overlay_strategy.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; import "ui/gfx/mojo/color_space.mojom"; @@ -30,4 +31,7 @@ [EnableIf=is_android] gfx.mojom.ColorSpace color_space; + + [EnableIf=use_ozone] + array<OverlayStrategy> overlay_strategies; };
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc index 23c730b..4c56ff89 100644 --- a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc +++ b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h" + #include "services/viz/public/cpp/compositing/resource_settings_struct_traits.h" namespace mojo { @@ -11,8 +12,6 @@ bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>:: Read(viz::mojom::RendererSettingsDataView data, viz::RendererSettings* out) { - bool success = true; - out->allow_antialiasing = data.allow_antialiasing(); out->force_antialiasing = data.force_antialiasing(); out->force_blending_with_shaders = data.force_blending_with_shaders(); @@ -33,11 +32,19 @@ out->requires_alpha_channel = data.requires_alpha_channel(); #if defined(OS_ANDROID) - success = data.ReadInitialScreenSize(&out->initial_screen_size); - success = data.ReadColorSpace(&out->color_space); + if (!data.ReadInitialScreenSize(&out->initial_screen_size)) + return false; + + if (!data.ReadColorSpace(&out->color_space)) + return false; #endif - return success; +#if defined(USE_OZONE) + if (!data.ReadOverlayStrategies(&out->overlay_strategies)) + return false; +#endif + + return true; } } // namespace mojo
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h index f379f96..b040836 100644 --- a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h +++ b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h
@@ -4,13 +4,19 @@ #ifndef SERVICES_VIZ_PRIVILEGED_INTERFACES_COMPOSITING_RENDERER_SETTINGS_STRUCT_TRAITS_H_ #define SERVICES_VIZ_PRIVILEGED_INTERFACES_COMPOSITING_RENDERER_SETTINGS_STRUCT_TRAITS_H_ +#include <vector> + #include "build/build_config.h" #include "components/viz/common/display/renderer_settings.h" +#include "services/viz/privileged/cpp/overlay_strategy_struct_traits.h" #include "services/viz/privileged/interfaces/compositing/renderer_settings.mojom.h" -#include "services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h" #include "ui/gfx/geometry/mojo/geometry_struct_traits.h" #include "ui/gfx/ipc/color/gfx_param_traits.h" +#if defined(USE_OZONE) +#include "components/viz/common/display/overlay_strategy.h" +#endif + namespace mojo { template <> struct StructTraits<viz::mojom::RendererSettingsDataView, @@ -92,6 +98,13 @@ } #endif +#if defined(USE_OZONE) + static std::vector<viz::OverlayStrategy> overlay_strategies( + const viz::RendererSettings& input) { + return input.overlay_strategies; + } +#endif + static bool Read(viz::mojom::RendererSettingsDataView data, viz::RendererSettings* out); };
diff --git a/skia/tools/fuzzers/BUILD.gn b/skia/tools/fuzzers/BUILD.gn index 44bb98e17..b5ba615c 100644 --- a/skia/tools/fuzzers/BUILD.gn +++ b/skia/tools/fuzzers/BUILD.gn
@@ -48,9 +48,9 @@ static_library("skia_test_fonts") { sources = [ - "//third_party/skia/tools/fonts/SkTestFontMgr.cpp", - "//third_party/skia/tools/fonts/SkTestSVGTypeface.cpp", - "//third_party/skia/tools/fonts/SkTestTypeface.cpp", + "//third_party/skia/tools/fonts/TestFontMgr.cpp", + "//third_party/skia/tools/fonts/TestSVGTypeface.cpp", + "//third_party/skia/tools/fonts/TestTypeface.cpp", ] configs += [ "//skia:skia_library_config" ]
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 95012a7..5255820 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -5764,6 +5764,1156 @@ } ] }, + "mac-dummy-rel": { + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "accessibility_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "angle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "app_shell_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "blink_common_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "blink_fuzzer_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "blink_platform_unittests" + }, + { + "name": "webkit_unit_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "boringssl_crypto_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "boringssl_ssl_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "shards": 10 + }, + "test": "browser_tests" + }, + { + "args": [ + "--disable-features=WebUIPolymer2", + "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_browser_tests.filter" + ], + "name": "webui_polymer1_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "shards": 4 + }, + "test": "browser_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "cacheinvalidation_unittests" + }, + { + "args": [ + "--gtest_filter=-*UsingRealWebcam*" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "capture_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "cast_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "cc_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "chrome_app_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "chromedriver_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "components_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "components_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "shards": 6 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-perfetto", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "content_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "content_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "crashpad_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "cronet_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "cronet_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "crypto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "device_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "display_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "events_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "extensions_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "extensions_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "filesystem_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "gcm_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "gfx_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "gin_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "google_apis_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "gpu_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "headless_browsertests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "headless_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "shards": 3 + }, + "test": "interactive_ui_tests" + }, + { + "args": [ + "--disable-features=WebUIPolymer2", + "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer1_interactive_ui_tests.filter" + ], + "name": "webui_polymer1_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "interactive_ui_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "ipc_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "jingle_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "latency_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "leveldb_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "libjingle_xmpp_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "media_blink_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "media_service_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "media_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "message_center_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "midi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "mojo_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "nacl_loader_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "native_theme_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "net_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "pdf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "perfetto_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "ppapi_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "printing_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "remoting_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "sandbox_mac_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "service_manager_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "services_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "shell_dialogs_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "skia_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "snapshot_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "sql_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "storage_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "sync_integration_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "ui_base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "ui_touch_selection_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + }, + "test": "wtf_unittests" + } + ], + "isolated_scripts": [ + { + "isolate_name": "blink_python_tests", + "name": "blink_python_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "args": [ + "--test-type=integration" + ], + "isolate_name": "chromedriver_py_tests", + "name": "chromedriver_py_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "isolate_name": "chromedriver_replay_unittests", + "name": "chromedriver_replay_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "args": [ + "--gtest-benchmark-name=components_perftests" + ], + "isolate_name": "components_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "components_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "isolate_name": "content_shell_crash_test", + "name": "content_shell_crash_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "isolate_name": "flatbuffers_unittests", + "name": "flatbuffers_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "isolate_name": "metrics_python_tests", + "name": "metrics_python_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + }, + { + "isolate_name": "telemetry_gpu_unittests", + "name": "telemetry_gpu_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "idempotent": false + } + }, + { + "isolate_name": "telemetry_perf_unittests", + "name": "telemetry_perf_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "idempotent": false, + "shards": 12 + } + }, + { + "args": [ + "--jobs=1", + "--extra-browser-args=--disable-gpu" + ], + "isolate_name": "telemetry_unittests", + "name": "telemetry_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ], + "idempotent": false, + "shards": 4 + } + }, + { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], + "isolate_name": "views_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "views_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "none", + "os": "Mac-10.13" + } + ] + } + } + ], + "scripts": [ + { + "name": "check_static_initializers", + "script": "check_static_initializers.py", + "swarming": {} + }, + { + "name": "webkit_lint", + "script": "blink_lint_expectations.py", + "swarming": {} + } + ] + }, "mac-jumbo-rel": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 567882e..f48eca5 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -939,6 +939,8 @@ # chromium, due to https://crbug.com/878915 'win-dbg', 'win32-dbg', + # chromium.mac, see https://crbug.com/943804 + 'mac-dummy-rel', # Defined in internal configs. 'chromeos-amd64-generic-google-rel', ]
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 349581d..98b9c0df 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -2413,6 +2413,10 @@ "type": "additional_compile_target", }, "system_webview_shell_layout_test_apk": { + "args": [ + "--use-webview-provider", + "apks/SystemWebView.apk", + ], "label": "//android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk", "type": "console_test_launcher", }, @@ -2821,6 +2825,10 @@ "type": "console_test_launcher", }, "webview_ui_test_app_test_apk": { + "args": [ + "--use-webview-provider", + "apks/SystemWebView.apk", + ], "label": "//android_webview/tools/automated_ui_tests:webview_ui_test_app_test_apk", "type": "console_test_launcher", },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 6fe0718..51e626e 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1003,6 +1003,8 @@ 'non_network_service_webkit_layout_tests' : { 'remove_from': [ 'Linux Tests (dbg)(1)(32)', # 32-bit linux is unsupported + # chromium.mac. TODO(https://crbug.com/944117): Remove this. + 'mac-dummy-rel', ], 'modifications': { 'Linux Tests (dbg)(1)': { @@ -1056,6 +1058,8 @@ # TODO(dpranke): Should we be running this step on Linux Tests (dbg)(1)? 'Linux Tests (dbg)(1)', 'Linux Tests (dbg)(1)(32)', + # chromium.mac. TODO(https://crbug.com/944117): Remove this. + 'mac-dummy-rel', ], }, 'notification_helper_unittests': { @@ -1533,6 +1537,8 @@ # chromium.win 'Win 7 Tests x64 (1)', # 64-bit win is unsupported by the layout tests. 'Win10 Tests x64 (dbg)', + # chromium.mac. TODO(https://crbug.com/944117): Remove this. + 'mac-dummy-rel', ], 'modifications': { # chromium.android
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index b74dda2..54df8f7 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3221,6 +3221,18 @@ ], }, }, + # This builder doesn't run anywhere. It exists to let mac-rel mirror a bot. + 'mac-dummy-rel': { + 'mixins': [ + 'mac_10.13', + 'no_gpu', + ], + 'test_suites': { + 'gtest_tests': 'chromium_mac_gtests', + 'isolated_scripts': 'chromium_rel_isolated_scripts', + 'scripts': 'chromium_mac_scripts', + }, + }, 'mac-jumbo-rel': { 'additional_compile_targets': [ 'all'
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 26f69284..e08bf46 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3347,12 +3347,11 @@ ], "experiments": [ { - "name": "Intervention_R12_12%_Threshold", + "name": "Intervention_R9", "params": { "navigate_ads": "true", "pause_renderer": "true", - "purge_v8": "true", - "renderer_pmf_threshold_percentage": "12" + "renderer_workload_threshold_percentage": "16" }, "enable_features": [ "OomIntervention"
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index cb7e99f..412416a9 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -189,6 +189,34 @@ } # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. +android_aar_prebuilt("androidx_test_rules_java") { + aar_path = "libs/androidx_test_rules/rules-1.1.0.aar" + info_path = "libs/androidx_test_rules/androidx_test_rules.info" + testonly = true + deps = [ + ":androidx_test_runner_java", + ] + deps += [ + "//third_party/android_tools:android_test_base_java", + "//third_party/android_tools:android_test_mock_java", + "//third_party/android_tools:android_test_runner_java", + ] +} + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. +android_aar_prebuilt("androidx_test_runner_java") { + aar_path = "libs/androidx_test_runner/runner-1.1.0.aar" + info_path = "libs/androidx_test_runner/androidx_test_runner.info" + testonly = true + deps = [ + ":androidx_annotation_annotation_java", + ":androidx_test_monitor_java", + ":net_sf_kxml_kxml2_java", + "//third_party/junit:junit", + ] +} + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. android_aar_prebuilt("com_android_support_appcompat_v7_java") { aar_path = "libs/com_android_support_appcompat_v7/appcompat-v7-27.0.0.aar" info_path = "libs/com_android_support_appcompat_v7/com_android_support_appcompat_v7.info" @@ -918,6 +946,15 @@ } # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. +java_prebuilt("net_sf_kxml_kxml2_java") { + jar_path = "libs/net_sf_kxml_kxml2/kxml2-2.3.0.jar" + output_name = "net_sf_kxml_kxml2" + supports_android = true + visibility = [ ":*" ] + testonly = true +} + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. java_prebuilt("org_checkerframework_checker_compat_qual_java") { jar_path = "libs/org_checkerframework_checker_compat_qual/checker-compat-qual-2.3.0.jar" output_name = "org_checkerframework_checker_compat_qual"
diff --git a/third_party/android_deps/additional_readme_paths.json b/third_party/android_deps/additional_readme_paths.json index 7953c18..0f4b59a 100644 --- a/third_party/android_deps/additional_readme_paths.json +++ b/third_party/android_deps/additional_readme_paths.json
@@ -7,6 +7,8 @@ "libs/androidx_test_core", "libs/androidx_test_ext_junit", "libs/androidx_test_monitor", + "libs/androidx_test_rules", + "libs/androidx_test_runner", "libs/com_android_support_animated_vector_drawable", "libs/com_android_support_appcompat_v7", "libs/com_android_support_cardview_v7", @@ -65,6 +67,7 @@ "libs/com_squareup_javapoet", "libs/javax_annotation_jsr250_api", "libs/javax_inject_javax_inject", + "libs/net_sf_kxml_kxml2", "libs/org_checkerframework_checker_compat_qual", "libs/org_codehaus_mojo_animal_sniffer_annotations" ]
diff --git a/third_party/android_deps/libs/androidx_test_rules/LICENSE b/third_party/android_deps/libs/androidx_test_rules/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_rules/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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.
diff --git a/third_party/android_deps/libs/androidx_test_rules/OWNERS b/third_party/android_deps/libs/androidx_test_rules/OWNERS new file mode 100644 index 0000000..7b571d97 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_rules/OWNERS
@@ -0,0 +1 @@ +file://third_party/android_deps/OWNERS \ No newline at end of file
diff --git a/third_party/android_deps/libs/androidx_test_rules/README.chromium b/third_party/android_deps/libs/androidx_test_rules/README.chromium new file mode 100644 index 0000000..3613193 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_rules/README.chromium
@@ -0,0 +1,13 @@ +Name: AndroidX Test Library +Short Name: rules +URL: https://developer.android.com/testing +Version: 1.1.0 +License: Apache Version 2.0 +License File: NOT_SHIPPED +Security Critical: no + +Description: +The AndroidX Test Library provides an extensive framework for testing Android apps + +Local Modifications: +No modifications.
diff --git a/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info b/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info new file mode 100644 index 0000000..0dfcb237 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info
@@ -0,0 +1,13 @@ +# Generated by //build/android/gyp/aar.py +# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen". + +aidl = [ ] +assets = [ ] +has_classes_jar = true +has_native_libraries = false +has_proguard_flags = true +has_r_text_file = false +is_manifest_empty = true +resources = [ ] +subjar_tuples = [ ] +subjars = [ ]
diff --git a/third_party/android_deps/libs/androidx_test_rules/cipd.yaml b/third_party/android_deps/libs/androidx_test_rules/cipd.yaml new file mode 100644 index 0000000..e2c678a --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_rules/cipd.yaml
@@ -0,0 +1,10 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# To create CIPD package run the following command. +# cipd create --pkg-def cipd.yaml -tag version:1.1.0-cr0 +package: chromium/third_party/android_deps/libs/androidx_test_rules +description: "AndroidX Test Library" +data: +- file: rules-1.1.0.aar
diff --git a/third_party/android_deps/libs/androidx_test_runner/LICENSE b/third_party/android_deps/libs/androidx_test_runner/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_runner/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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.
diff --git a/third_party/android_deps/libs/androidx_test_runner/OWNERS b/third_party/android_deps/libs/androidx_test_runner/OWNERS new file mode 100644 index 0000000..7b571d97 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_runner/OWNERS
@@ -0,0 +1 @@ +file://third_party/android_deps/OWNERS \ No newline at end of file
diff --git a/third_party/android_deps/libs/androidx_test_runner/README.chromium b/third_party/android_deps/libs/androidx_test_runner/README.chromium new file mode 100644 index 0000000..385b0e8 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_runner/README.chromium
@@ -0,0 +1,13 @@ +Name: AndroidX Test Library +Short Name: runner +URL: https://developer.android.com/testing +Version: 1.1.0 +License: Apache Version 2.0 +License File: NOT_SHIPPED +Security Critical: no + +Description: +The AndroidX Test Library provides an extensive framework for testing Android apps + +Local Modifications: +No modifications.
diff --git a/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info b/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info new file mode 100644 index 0000000..0dfcb237 --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info
@@ -0,0 +1,13 @@ +# Generated by //build/android/gyp/aar.py +# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen". + +aidl = [ ] +assets = [ ] +has_classes_jar = true +has_native_libraries = false +has_proguard_flags = true +has_r_text_file = false +is_manifest_empty = true +resources = [ ] +subjar_tuples = [ ] +subjars = [ ]
diff --git a/third_party/android_deps/libs/androidx_test_runner/cipd.yaml b/third_party/android_deps/libs/androidx_test_runner/cipd.yaml new file mode 100644 index 0000000..69661ee --- /dev/null +++ b/third_party/android_deps/libs/androidx_test_runner/cipd.yaml
@@ -0,0 +1,10 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# To create CIPD package run the following command. +# cipd create --pkg-def cipd.yaml -tag version:1.1.0-cr0 +package: chromium/third_party/android_deps/libs/androidx_test_runner +description: "AndroidX Test Library" +data: +- file: runner-1.1.0.aar
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn index e25bd4b..a4bfc68 100644 --- a/third_party/blink/common/BUILD.gn +++ b/third_party/blink/common/BUILD.gn
@@ -42,6 +42,7 @@ "loader/url_loader_factory_bundle_mojom_traits.cc", "manifest/manifest.cc", "manifest/manifest_icon_selector.cc", + "manifest/manifest_util.cc", "mediastream/media_devices.cc", "mediastream/media_devices_mojom_traits.cc", "mediastream/media_stream_controls.cc", @@ -124,6 +125,7 @@ "frame/user_activation_state_unittest.cc", "indexeddb/indexeddb_key_unittest.cc", "manifest/manifest_icon_selector_unittest.cc", + "manifest/manifest_util_unittest.cc", "mediastream/media_devices_unittest.cc", "mime_util/mime_util_unittest.cc", "notifications/notification_struct_traits_unittest.cc",
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 0672baa..012f0c9 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -101,6 +101,21 @@ "PreviewsResourceLoadingHintsSpecificResourceTypes", base::FEATURE_DISABLED_BY_DEFAULT}; +// Perform a memory purge after a renderer is backgrounded. Formerly labelled as +// the "PurgeAndSuspend" experiment. +// +// TODO(adityakeerthi): Disabled by default on Mac and Android for historical +// reasons. Consider enabling by default if experiment results are positive. +// https://crbug.com/926186 +const base::Feature kPurgeRendererMemoryWhenBackgrounded { + "PurgeRendererMemoryWhenBackgrounded", +#if defined(OS_MACOSX) || defined(OS_ANDROID) + base::FEATURE_DISABLED_BY_DEFAULT +#else + base::FEATURE_ENABLED_BY_DEFAULT +#endif +}; + // Enable Implicit Root Scroller. https://crbug.com/903260. const base::Feature kImplicitRootScroller{"ImplicitRootScroller", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/manifest_util.cc b/third_party/blink/common/manifest/manifest_util.cc similarity index 73% rename from content/public/common/manifest_util.cc rename to third_party/blink/common/manifest/manifest_util.cc index d1684daa..63611e5 100644 --- a/content/public/common/manifest_util.cc +++ b/third_party/blink/common/manifest/manifest_util.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/common/manifest_util.h" +#include "third_party/blink/public/common/manifest/manifest_util.h" #include "base/strings/string_util.h" -namespace content { +namespace blink { std::string WebDisplayModeToString(blink::WebDisplayMode display) { switch (display) { @@ -27,11 +27,11 @@ blink::WebDisplayMode WebDisplayModeFromString(const std::string& display) { if (base::LowerCaseEqualsASCII(display, "browser")) return blink::kWebDisplayModeBrowser; - else if (base::LowerCaseEqualsASCII(display, "minimal-ui")) + if (base::LowerCaseEqualsASCII(display, "minimal-ui")) return blink::kWebDisplayModeMinimalUi; - else if (base::LowerCaseEqualsASCII(display, "standalone")) + if (base::LowerCaseEqualsASCII(display, "standalone")) return blink::kWebDisplayModeStandalone; - else if (base::LowerCaseEqualsASCII(display, "fullscreen")) + if (base::LowerCaseEqualsASCII(display, "fullscreen")) return blink::kWebDisplayModeFullscreen; return blink::kWebDisplayModeUndefined; } @@ -61,25 +61,25 @@ return ""; } -blink::WebScreenOrientationLockType -WebScreenOrientationLockTypeFromString(const std::string& orientation) { +blink::WebScreenOrientationLockType WebScreenOrientationLockTypeFromString( + const std::string& orientation) { if (base::LowerCaseEqualsASCII(orientation, "portrait-primary")) return blink::kWebScreenOrientationLockPortraitPrimary; - else if (base::LowerCaseEqualsASCII(orientation, "portrait-secondary")) + if (base::LowerCaseEqualsASCII(orientation, "portrait-secondary")) return blink::kWebScreenOrientationLockPortraitSecondary; - else if (base::LowerCaseEqualsASCII(orientation, "landscape-primary")) + if (base::LowerCaseEqualsASCII(orientation, "landscape-primary")) return blink::kWebScreenOrientationLockLandscapePrimary; - else if (base::LowerCaseEqualsASCII(orientation, "landscape-secondary")) + if (base::LowerCaseEqualsASCII(orientation, "landscape-secondary")) return blink::kWebScreenOrientationLockLandscapeSecondary; - else if (base::LowerCaseEqualsASCII(orientation, "any")) + if (base::LowerCaseEqualsASCII(orientation, "any")) return blink::kWebScreenOrientationLockAny; - else if (base::LowerCaseEqualsASCII(orientation, "landscape")) + if (base::LowerCaseEqualsASCII(orientation, "landscape")) return blink::kWebScreenOrientationLockLandscape; - else if (base::LowerCaseEqualsASCII(orientation, "portrait")) + if (base::LowerCaseEqualsASCII(orientation, "portrait")) return blink::kWebScreenOrientationLockPortrait; - else if (base::LowerCaseEqualsASCII(orientation, "natural")) + if (base::LowerCaseEqualsASCII(orientation, "natural")) return blink::kWebScreenOrientationLockNatural; return blink::kWebScreenOrientationLockDefault; } -} // namespace content +} // namespace blink
diff --git a/content/common/manifest_util_unittest.cc b/third_party/blink/common/manifest/manifest_util_unittest.cc similarity index 96% rename from content/common/manifest_util_unittest.cc rename to third_party/blink/common/manifest/manifest_util_unittest.cc index a8fca044..b37faa22 100644 --- a/content/common/manifest_util_unittest.cc +++ b/third_party/blink/common/manifest/manifest_util_unittest.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/public/common/manifest_util.h" +#include "third_party/blink/public/common/manifest/manifest_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -namespace content { +namespace blink { TEST(ManifestUtilTest, WebDisplayModeConversions) { struct ReversibleConversion { @@ -74,4 +74,4 @@ WebScreenOrientationLockTypeFromString("random")); } -} // namespace content +} // namespace blink
diff --git a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc index 07a1609..8dec0ad2 100644 --- a/third_party/blink/common/mediastream/media_stream_mojom_traits.cc +++ b/third_party/blink/common/mediastream/media_stream_mojom_traits.cc
@@ -214,8 +214,6 @@ if (!input.ReadInput(&out->input)) return false; out->session_id = input.session_id(); - if (!input.ReadCameraCalibration(&out->camera_calibration)) - return false; if (!input.ReadDisplayMediaInfo(&out->display_media_info)) return false; return true;
diff --git a/third_party/blink/common/mediastream/media_stream_request.cc b/third_party/blink/common/mediastream/media_stream_request.cc index d147103..4b0c692 100644 --- a/third_party/blink/common/mediastream/media_stream_request.cc +++ b/third_party/blink/common/mediastream/media_stream_request.cc
@@ -104,7 +104,6 @@ name = other.name; input = other.input; session_id = other.session_id; - camera_calibration = other.camera_calibration; if (other.display_media_info.has_value()) display_media_info = other.display_media_info->Clone(); } @@ -123,7 +122,6 @@ name = other.name; input = other.input; session_id = other.session_id; - camera_calibration = other.camera_calibration; if (other.display_media_info.has_value()) display_media_info = other.display_media_info->Clone(); return *this;
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index ce0a530..e9778e6 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -618,6 +618,7 @@ group("scaled_resources") { public_deps = [ ":image_resources", + "//third_party/blink/renderer/modules/media_controls:media_controls_non_touch_resources", "//third_party/blink/renderer/modules/media_controls:media_controls_resources", ] } @@ -626,6 +627,7 @@ output = "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak" sources = [ "$root_gen_dir/third_party/blink/public/resources/blink_image_resources_100_percent.pak", + "$root_gen_dir/third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.pak", "$root_gen_dir/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources_100_percent.pak", ] deps = [ @@ -637,6 +639,7 @@ output = "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_200_percent.pak" sources = [ "$root_gen_dir/third_party/blink/public/resources/blink_image_resources_200_percent.pak", + "$root_gen_dir/third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.pak", "$root_gen_dir/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources_200_percent.pak", ] deps = [ @@ -654,16 +657,10 @@ [ "//third_party/blink/renderer/platform:blink_platform_public_deps" ] sources = [ "platform/modules/bluetooth/web_bluetooth.mojom", - "platform/modules/idle/idle_manager.mojom", "platform/modules/notifications/notification_service.mojom", - "web/commit_result.mojom", - "web/devtools_frontend.mojom", - "web/selection_menu_behavior.mojom", - "web/window_features.mojom", ] public_deps = [ ":android_mojo_bindings", - ":authenticator_test_mojo_bindings", "//components/services/font/public/interfaces", "//device/bluetooth/public/mojom", "//mojo/public/mojom/base", @@ -697,14 +694,8 @@ } mojom("android_mojo_bindings") { - visibility = [ - ":mojo_bindings", - ":authenticator_test_mojo_bindings", - ] - visibility_blink = [ - ":mojo_bindings_blink", - ":authenticator_test_mojo_bindings_blink", - ] + visibility = [ ":mojo_bindings" ] + visibility_blink = [ ":mojo_bindings_blink" ] sources = [ "platform/modules/document_metadata/copyless_paste.mojom", "platform/modules/font_unique_name_lookup/font_unique_name_lookup.mojom", @@ -712,8 +703,6 @@ "platform/modules/installedapp/installed_app_provider.mojom", "platform/modules/installedapp/related_application.mojom", "platform/modules/mediasession/media_session.mojom", - "platform/modules/webauthn/authenticator.mojom", - "web/remote_objects.mojom", ] public_deps = [ "//mojo/public/mojom/base", @@ -731,9 +720,6 @@ export_class_attribute_blink = "BLINK_PLATFORM_EXPORT" export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" export_header_blink = "third_party/blink/public/platform/web_common.h" - - # Don't scramble message IDs so they are redistributable to external tests. - scramble_message_ids = false } # The embedded_frame_sink_mojo_bindings is separated from the rest of mojom @@ -806,18 +792,3 @@ ":mojo_bindings_headers", ] } - -# This is a separate target because it needs unscrambled message IDs. -mojom("authenticator_test_mojo_bindings") { - sources = [ - "platform/modules/webauthn/virtual_authenticator.mojom", - ] - - public_deps = [ - ":android_mojo_bindings", - "//url/mojom:url_mojom_gurl", - ] - - # Don't scramble message IDs so they are redistributable to external tests. - scramble_message_ids = false -}
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn index b9c3eba..24c4e4ab 100644 --- a/third_party/blink/public/common/BUILD.gn +++ b/third_party/blink/public/common/BUILD.gn
@@ -66,6 +66,7 @@ "loader/url_loader_factory_bundle_mojom_traits.h", "manifest/manifest.h", "manifest/manifest_icon_selector.h", + "manifest/manifest_util.h", "manifest/web_display_mode.h", "media/video_capture.h", "mediastream/media_devices.h",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index cb90f2d..5dd9985a 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -37,6 +37,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kPortals; BLINK_COMMON_EXPORT extern const base::Feature kPreviewsResourceLoadingHintsSpecificResourceTypes; +BLINK_COMMON_EXPORT extern const base::Feature + kPurgeRendererMemoryWhenBackgrounded; BLINK_COMMON_EXPORT extern const base::Feature kRTCGetDisplayMedia; BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault; BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed;
diff --git a/third_party/blink/public/common/frame/occlusion_state.h b/third_party/blink/public/common/frame/occlusion_state.h index b6ca000..1faa8d4 100644 --- a/third_party/blink/public/common/frame/occlusion_state.h +++ b/third_party/blink/public/common/frame/occlusion_state.h
@@ -11,14 +11,14 @@ // Indicates whether a child frame is occluded or visually altered by content // or styles in the parent frame. -enum FrameOcclusionState { +enum class FrameOcclusionState { // No occlusion determination was made. - kUnknownOcclusionState = 0, + kUnknown = 0, // The frame *may* be occluded or visually altered. kPossiblyOccluded = 1, // The frame is definitely not occluded or visually altered. kGuaranteedNotOccluded = 2, - kMaxOcclusionState = kGuaranteedNotOccluded + kMaxValue = kGuaranteedNotOccluded, }; } // namespace blink
diff --git a/content/public/common/manifest_util.h b/third_party/blink/public/common/manifest/manifest_util.h similarity index 73% rename from content/public/common/manifest_util.h rename to third_party/blink/public/common/manifest/manifest_util.h index f6c70ba..2a2bd8f 100644 --- a/content/public/common/manifest_util.h +++ b/third_party/blink/public/common/manifest/manifest_util.h
@@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_PUBLIC_COMMON_MANIFEST_UTIL_H_ -#define CONTENT_PUBLIC_COMMON_MANIFEST_UTIL_H_ +#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_UTIL_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_UTIL_H_ #include <string> -#include "content/common/content_export.h" +#include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/common/manifest/web_display_mode.h" #include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h" -namespace content { +namespace blink { // Converts a blink::WebDisplayMode to a string. Returns one of // https://www.w3.org/TR/appmanifest/#dfn-display-modes-values. Return values // are lowercase. Returns an empty string for blink::WebDisplayModeUndefined. -CONTENT_EXPORT std::string WebDisplayModeToString( +BLINK_COMMON_EXPORT std::string WebDisplayModeToString( blink::WebDisplayMode display); // Returns the blink::WebDisplayMode which matches |display|. @@ -24,14 +24,14 @@ // https://www.w3.org/TR/appmanifest/#dfn-display-modes-values. |display| is // case insensitive. Returns blink::WebDisplayModeUndefined if there is no // match. -CONTENT_EXPORT blink::WebDisplayMode WebDisplayModeFromString( +BLINK_COMMON_EXPORT blink::WebDisplayMode WebDisplayModeFromString( const std::string& display); // Converts a blink::WebScreenOrientationLockType to a string. Returns one of // https://www.w3.org/TR/screen-orientation/#orientationlocktype-enum. Return // values are lowercase. Returns an empty string for // blink::WebScreenOrientationLockDefault. -CONTENT_EXPORT std::string WebScreenOrientationLockTypeToString( +BLINK_COMMON_EXPORT std::string WebScreenOrientationLockTypeToString( blink::WebScreenOrientationLockType); // Returns the blink::WebScreenOrientationLockType which matches @@ -39,9 +39,9 @@ // https://www.w3.org/TR/screen-orientation/#orientationlocktype-enum. // |orientation| is case insensitive. Returns // blink::WebScreenOrientationLockDefault if there is no match. -CONTENT_EXPORT blink::WebScreenOrientationLockType +BLINK_COMMON_EXPORT blink::WebScreenOrientationLockType WebScreenOrientationLockTypeFromString(const std::string& orientation); -} // namespace content +} // namespace blink -#endif // CONTENT_PUBLIC_COMMON_MANIFEST_UTIL_H_ +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_UTIL_H_
diff --git a/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h b/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h index 044a808..f7a5c6b 100644 --- a/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h +++ b/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h
@@ -69,12 +69,6 @@ return device.session_id; } - static const base::Optional< - media::VideoCaptureDeviceDescriptor::CameraCalibration>& - camera_calibration(const blink::MediaStreamDevice& device) { - return device.camera_calibration; - } - static const base::Optional<media::mojom::DisplayMediaInformationPtr>& display_media_info(const blink::MediaStreamDevice& device) { return device.display_media_info;
diff --git a/third_party/blink/public/common/mediastream/media_stream_request.h b/third_party/blink/public/common/mediastream/media_stream_request.h index c00f038..c062c41 100644 --- a/third_party/blink/public/common/mediastream/media_stream_request.h +++ b/third_party/blink/public/common/mediastream/media_stream_request.h
@@ -79,9 +79,6 @@ NUM_MEDIA_REQUEST_RESULTS }; -using CameraCalibration = - media::VideoCaptureDeviceDescriptor::CameraCalibration; - // Convenience predicates to determine whether the given type represents some // audio or some video device. BLINK_COMMON_EXPORT bool IsAudioInputMediaType(MediaStreamType type); @@ -154,9 +151,6 @@ // Id for this capture session. Unique for all sessions of the same type. int session_id = kNoId; - // This field is optional and available only for some camera models. - base::Optional<CameraCalibration> camera_calibration; - // This field is optional and available only for display media devices. base::Optional<media::mojom::DisplayMediaInformationPtr> display_media_info; };
diff --git a/third_party/blink/public/common/messaging/transferable_message.h b/third_party/blink/public/common/messaging/transferable_message.h index 9d134b4..e532eadb 100644 --- a/third_party/blink/public/common/messaging/transferable_message.h +++ b/third_party/blink/public/common/messaging/transferable_message.h
@@ -12,7 +12,7 @@ #include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/common/messaging/cloneable_message.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" -#include "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom-forward.h" +#include "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom.h" #include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom.h" #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 95e17553..7862a04 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -29,6 +29,7 @@ "choosers/color_chooser.mojom", "choosers/file_chooser.mojom", "clipboard/clipboard.mojom", + "commit_result/commit_result.mojom", "contacts/contacts_manager.mojom", "cookie_store/cookie_store.mojom", "crash/crash_memory_metrics_reporter.mojom", @@ -36,6 +37,7 @@ "csp/content_security_policy.mojom", "devtools/console_message.mojom", "devtools/devtools_agent.mojom", + "devtools/devtools_frontend.mojom", "dom_storage/session_storage_namespace.mojom", "dom_storage/storage_area.mojom", "dom_storage/storage_partition_service.mojom", @@ -52,6 +54,7 @@ "frame/navigation_initiator.mojom", "geolocation/geolocation_service.mojom", "hyphenation/hyphenation.mojom", + "idle/idle_manager.mojom", "insecure_input/insecure_input_service.mojom", "keyboard_lock/keyboard_lock.mojom", "leak_detector/leak_detector.mojom", @@ -84,6 +87,7 @@ "renderer_preferences.mojom", "reporting/reporting.mojom", "script/script_type.mojom", + "selection_menu/selection_menu_behavior.mojom", "service_worker/dispatch_fetch_event_params.mojom", "service_worker/navigation_preload_state.mojom", "service_worker/service_worker_client.mojom", @@ -106,6 +110,7 @@ "wake_lock/wake_lock.mojom", "webaudio/audio_context_manager.mojom", "webdatabase/web_database.mojom", + "window_features/window_features.mojom", "worker/shared_worker.mojom", "worker/shared_worker_client.mojom", "worker/shared_worker_connector.mojom", @@ -126,6 +131,7 @@ public_deps = [ ":android_mojo_bindings", + ":authenticator_test_mojo_bindings", ":mojom_mhtml_load_result", ":speech_recognition_error_code", ":web_client_hints_types_mojo_bindings", @@ -168,17 +174,21 @@ # Kept separate from "mojom_platform" because the Java bindings are specifically # needed by Android's implementation of payments and webshare -# (in components/payments/content/android and chrome/android/) -# and input (in android_webview/ and content/browser/android/). +# (in components/payments/content/android and chrome/android/), +# input (in android_webview/ and content/browser/android/), remote objects +# (in content/public/android/) and webauthn (in chrome/android). mojom("android_mojo_bindings") { sources = [ "input/input_host.mojom", "input/input_messages.mojom", "payments/payment_request.mojom", + "remote_objects/remote_objects.mojom", + "webauthn/authenticator.mojom", "webshare/webshare.mojom", ] public_deps = [ "//components/payments/mojom", + "//mojo/public/mojom/base", "//url/mojom:url_mojom_gurl", "//url/mojom:url_mojom_origin", ] @@ -196,6 +206,9 @@ export_class_attribute_blink = "PLATFORM_EXPORT" export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" export_header_blink = "third_party/blink/renderer/platform/platform_export.h" + + # Don't scramble message IDs so they are redistributable to external tests. + scramble_message_ids = false } # Kept separate from "mojom_platform" because the Java bindings are needed by @@ -333,3 +346,26 @@ "web_client_hints/web_client_hints_types.mojom", ] } + +# This is a separate target because it needs unscrambled message IDs. +mojom("authenticator_test_mojo_bindings") { + sources = [ + "webauthn/virtual_authenticator.mojom", + ] + + public_deps = [ + ":android_mojo_bindings", + "//url/mojom:url_mojom_gurl", + ] + + export_class_attribute = "BLINK_COMMON_EXPORT" + export_define = "BLINK_COMMON_IMPLEMENTATION=1" + export_header = "third_party/blink/public/common/common_export.h" + + export_class_attribute_blink = "PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/renderer/platform/platform_export.h" + + # Don't scramble message IDs so they are redistributable to external tests. + scramble_message_ids = false +}
diff --git a/third_party/blink/public/mojom/commit_result/OWNERS b/third_party/blink/public/mojom/commit_result/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/commit_result/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/web/commit_result.mojom b/third_party/blink/public/mojom/commit_result/commit_result.mojom similarity index 100% rename from third_party/blink/public/web/commit_result.mojom rename to third_party/blink/public/mojom/commit_result/commit_result.mojom
diff --git a/third_party/blink/public/web/devtools_frontend.mojom b/third_party/blink/public/mojom/devtools/devtools_frontend.mojom similarity index 100% rename from third_party/blink/public/web/devtools_frontend.mojom rename to third_party/blink/public/mojom/devtools/devtools_frontend.mojom
diff --git a/third_party/blink/public/platform/modules/idle/OWNERS b/third_party/blink/public/mojom/idle/OWNERS similarity index 100% rename from third_party/blink/public/platform/modules/idle/OWNERS rename to third_party/blink/public/mojom/idle/OWNERS
diff --git a/third_party/blink/public/platform/modules/idle/idle_manager.mojom b/third_party/blink/public/mojom/idle/idle_manager.mojom similarity index 100% rename from third_party/blink/public/platform/modules/idle/idle_manager.mojom rename to third_party/blink/public/mojom/idle/idle_manager.mojom
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom index 8e617511..c4356b1 100644 --- a/third_party/blink/public/mojom/mediastream/media_stream.mojom +++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -52,7 +52,6 @@ string name; media.mojom.AudioParameters input; int32 session_id; - media.mojom.VideoCaptureDeviceDescriptorCameraCalibration? camera_calibration; media.mojom.DisplayMediaInformation? display_media_info; };
diff --git a/third_party/blink/public/mojom/remote_objects/OWNERS b/third_party/blink/public/mojom/remote_objects/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/remote_objects/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/web/remote_objects.mojom b/third_party/blink/public/mojom/remote_objects/remote_objects.mojom similarity index 100% rename from third_party/blink/public/web/remote_objects.mojom rename to third_party/blink/public/mojom/remote_objects/remote_objects.mojom
diff --git a/third_party/blink/public/mojom/selection_menu/OWNERS b/third_party/blink/public/mojom/selection_menu/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/selection_menu/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/web/selection_menu_behavior.mojom b/third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom similarity index 100% rename from third_party/blink/public/web/selection_menu_behavior.mojom rename to third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom
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 f68553e..343118e 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -1414,10 +1414,6 @@ kMediaStreamConstraintsGroupIdAudio = 1936, kMediaStreamConstraintsGroupIdVideo = 1937, kMediaStreamConstraintsVideoKind = 1938, - kMediaStreamConstraintsDepthNear = 1939, - kMediaStreamConstraintsDepthFar = 1940, - kMediaStreamConstraintsFocalLengthX = 1941, - kMediaStreamConstraintsFocalLengthY = 1942, kMediaStreamConstraintsMediaStreamSourceAudio = 1943, kMediaStreamConstraintsMediaStreamSourceVideo = 1944, kMediaStreamConstraintsRenderToAssociatedSink = 1945,
diff --git a/third_party/blink/public/platform/modules/webauthn/OWNERS b/third_party/blink/public/mojom/webauthn/OWNERS similarity index 100% rename from third_party/blink/public/platform/modules/webauthn/OWNERS rename to third_party/blink/public/mojom/webauthn/OWNERS
diff --git a/third_party/blink/public/platform/modules/webauthn/authenticator.mojom b/third_party/blink/public/mojom/webauthn/authenticator.mojom similarity index 100% rename from third_party/blink/public/platform/modules/webauthn/authenticator.mojom rename to third_party/blink/public/mojom/webauthn/authenticator.mojom
diff --git a/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom b/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom similarity index 95% rename from third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom rename to third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom index 95f8458..0792a3e 100644 --- a/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom +++ b/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom
@@ -5,7 +5,7 @@ module blink.test.mojom; import "url/mojom/url.mojom"; -import "third_party/blink/public/platform/modules/webauthn/authenticator.mojom"; +import "third_party/blink/public/mojom/webauthn/authenticator.mojom"; // Application protocol that the virtual authenticator should simulate. enum ClientToAuthenticatorProtocol {
diff --git a/third_party/blink/public/mojom/window_features/OWNERS b/third_party/blink/public/mojom/window_features/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/window_features/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/web/window_features.mojom b/third_party/blink/public/mojom/window_features/window_features.mojom similarity index 100% rename from third_party/blink/public/web/window_features.mojom rename to third_party/blink/public/mojom/window_features/window_features.mojom
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index ac297b2d..c6c49fc 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -712,6 +712,10 @@ return nullptr; } + // Renderer Memory Metrics ---------------------------------------------- + + virtual void RecordMetricsForBackgroundedRendererPurge() {} + // V8 Context Snapshot -------------------------------------------------- // This method returns true only when
diff --git a/third_party/blink/public/platform/web_media_constraints.h b/third_party/blink/public/platform/web_media_constraints.h index c46d181..b452f43 100644 --- a/third_party/blink/public/platform/web_media_constraints.h +++ b/third_party/blink/public/platform/web_media_constraints.h
@@ -243,10 +243,6 @@ StringConstraint group_id; // https://w3c.github.io/mediacapture-depth/#mediatrackconstraints StringConstraint video_kind; - DoubleConstraint depth_near; - DoubleConstraint depth_far; - DoubleConstraint focal_length_x; - DoubleConstraint focal_length_y; // Constraints not exposed in Blink at the moment, only through // the legacy name interface. StringConstraint media_stream_source; // tab, screen, desktop, system
diff --git a/third_party/blink/public/platform/web_media_stream_track.h b/third_party/blink/public/platform/web_media_stream_track.h index 8d134fa..5fa8699 100644 --- a/third_party/blink/public/platform/web_media_stream_track.h +++ b/third_party/blink/public/platform/web_media_stream_track.h
@@ -68,10 +68,6 @@ bool HasLatency() const { return latency >= 0; } bool HasVolume() const { return volume >= 0; } bool HasVideoKind() const { return !video_kind.IsNull(); } - bool HasFocalLengthX() const { return focal_length_x >= 0.0; } - bool HasFocalLengthY() const { return focal_length_y >= 0.0; } - bool HasDepthNear() const { return depth_near >= 0.0; } - bool HasDepthFar() const { return depth_far >= 0.0; } // The variables are read from // MediaStreamTrack::GetSettings only. double frame_rate = -1.0; @@ -94,10 +90,6 @@ // Media Capture Depth Stream Extensions. WebString video_kind; - double focal_length_x = -1.0; - double focal_length_y = -1.0; - double depth_near = -1.0; - double depth_far = -1.0; // Screen Capture extensions base::Optional<DisplayCaptureSurfaceType> display_surface;
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h index 382ae48a..8addc01 100644 --- a/third_party/blink/public/platform/web_url_request.h +++ b/third_party/blink/public/platform/web_url_request.h
@@ -159,7 +159,7 @@ network::mojom::ReferrerPolicy); BLINK_PLATFORM_EXPORT void AddHTTPHeaderField(const WebString& name, const WebString& value); - BLINK_PLATFORM_EXPORT void ClearHTTPHeaderField(const WebString& name); + BLINK_PLATFORM_EXPORT void ClearHttpHeaderField(const WebString& name); BLINK_PLATFORM_EXPORT void VisitHTTPHeaderFields(WebHTTPHeaderVisitor*) const; BLINK_PLATFORM_EXPORT WebHTTPBody HttpBody() const; @@ -181,9 +181,6 @@ BLINK_PLATFORM_EXPORT mojom::RequestContextType GetRequestContext() const; BLINK_PLATFORM_EXPORT void SetRequestContext(mojom::RequestContextType); - BLINK_PLATFORM_EXPORT network::mojom::RequestContextFrameType GetFrameType() - const; - BLINK_PLATFORM_EXPORT network::mojom::ReferrerPolicy GetReferrerPolicy() const;
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h index 00f6bc1..9128a2b 100644 --- a/third_party/blink/public/platform/web_url_response.h +++ b/third_party/blink/public/platform/web_url_response.h
@@ -199,7 +199,7 @@ const WebString& value); BLINK_PLATFORM_EXPORT void AddHTTPHeaderField(const WebString& name, const WebString& value); - BLINK_PLATFORM_EXPORT void ClearHTTPHeaderField(const WebString& name); + BLINK_PLATFORM_EXPORT void ClearHttpHeaderField(const WebString& name); BLINK_PLATFORM_EXPORT void VisitHTTPHeaderFields(WebHTTPHeaderVisitor*) const; BLINK_PLATFORM_EXPORT int64_t AppCacheID() const;
diff --git a/third_party/blink/public/web/web_ax_object.h b/third_party/blink/public/web/web_ax_object.h index 7dee9992..a8b14c915 100644 --- a/third_party/blink/public/web/web_ax_object.h +++ b/third_party/blink/public/web/web_ax_object.h
@@ -99,10 +99,10 @@ // tree. BLINK_EXPORT int GenerateAXID() const; - // Update layout on the underlying tree, and return true if this object is - // still valid (not detached). Note that calling this method - // can cause other WebAXObjects to become invalid, too, - // so always call isDetached if any other WebCore code has run. + // Update layout if necessary on the underlying tree, and return true if this + // object is still valid (not detached). Note that calling this method can + // cause other WebAXObjects to become invalid, too, so always call isDetached + // if any other blink/renderer/core code has run. BLINK_EXPORT bool UpdateLayoutAndCheckValidity(); BLINK_EXPORT unsigned ChildCount() const; @@ -203,6 +203,11 @@ // present and if it wasn't already exposed by one of the two functions above. BLINK_EXPORT WebString Placeholder(ax::mojom::NameFrom) const; + // Takes the result of nameFrom and retrieves the HTML Title of the object, + // if present and if it wasn't already exposed by |GetName| above. + // HTML Title is typically used as a tooltip. + BLINK_EXPORT WebString Title(ax::mojom::NameFrom) const; + // The following selection functions get or set the global document // selection and can be called on any object in the tree. BLINK_EXPORT void Selection(WebAXObject& anchor_object,
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index cfca63b..611a2f64 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -13,15 +13,15 @@ #include "third_party/blink/public/common/feature_policy/feature_policy.h" #include "third_party/blink/public/common/frame/sandbox_flags.h" #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-shared.h" +#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-shared.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h" #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h" +#include "third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom-shared.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_focus_type.h" #include "third_party/blink/public/platform/web_size.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/web/commit_result.mojom-shared.h" -#include "third_party/blink/public/web/selection_menu_behavior.mojom-shared.h" #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_frame.h" #include "third_party/blink/public/web/web_frame_load_type.h"
diff --git a/third_party/blink/renderer/bindings/core/DEPS b/third_party/blink/renderer/bindings/core/DEPS index f83e6ef..5ed1eb0 100644 --- a/third_party/blink/renderer/bindings/core/DEPS +++ b/third_party/blink/renderer/bindings/core/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+gin/public", + "+mojo/public", "+services/metrics/public/cpp", "+third_party/blink/public/platform", "+third_party/blink/public/web/web_serialized_script_value_version.h", @@ -12,3 +13,9 @@ "-web", "+web/tests", ] + +specific_include_rules = { + "script_streamer.cc": [ + "+base/threading", + ] +} \ No newline at end of file
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc index fa21f0f4..7cf42cf 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -8,6 +8,9 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/threading/scoped_blocking_call.h" +#include "base/threading/thread_restrictions.h" +#include "mojo/public/cpp/system/wait.h" #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" @@ -20,6 +23,7 @@ #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h" #include "third_party/blink/renderer/platform/loader/fetch/resource.h" +#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" @@ -30,133 +34,129 @@ namespace blink { -// For passing data between the main thread (producer) and the streamer thread -// (consumer). The main thread prepares the data (copies it from Resource) and -// the streamer thread feeds it to V8. -class SourceStreamDataQueue { - public: - SourceStreamDataQueue() : finished_(false), have_data_(mutex_) {} - ~SourceStreamDataQueue() { DiscardQueuedData(); } - - void Clear() { - MutexLocker locker(mutex_); - finished_ = false; - DiscardQueuedData(); - } - - void Produce(const uint8_t* data, size_t length) { - TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("v8.compile"), - "v8.streamingCompile.sendData", this, - TRACE_EVENT_FLAG_FLOW_OUT, "length", length); - MutexLocker locker(mutex_); - DCHECK(!finished_); - data_.push_back(std::make_pair(data, length)); - have_data_.Signal(); - } - - void Finish() { - TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), - "v8.streamingCompile.finishData", this, - TRACE_EVENT_FLAG_FLOW_OUT); - MutexLocker locker(mutex_); - finished_ = true; - have_data_.Signal(); - } - - void Consume(const uint8_t** data, size_t* length) { - MutexLocker locker(mutex_); - while (!TryGetData(data, length)) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), - "v8.streamingCompile.waitForData"); - have_data_.Wait(); - TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("v8.compile"), - "v8.streamingCompile.receivedData", this, - TRACE_EVENT_FLAG_FLOW_IN, "length", *length); - } - } - - private: - bool TryGetData(const uint8_t** data, size_t* length) - EXCLUSIVE_LOCKS_REQUIRED(mutex_) { - mutex_.AssertAcquired(); - if (!data_.IsEmpty()) { - std::pair<const uint8_t*, size_t> next_data = data_.TakeFirst(); - *data = next_data.first; - *length = next_data.second; - return true; - } - if (finished_) { - *length = 0; - return true; - } - return false; - } - - void DiscardQueuedData() EXCLUSIVE_LOCKS_REQUIRED(mutex_) { - while (!data_.IsEmpty()) { - std::pair<const uint8_t*, size_t> next_data = data_.TakeFirst(); - delete[] next_data.first; - } - } - - Deque<std::pair<const uint8_t*, size_t>> data_ GUARDED_BY(mutex_); - bool finished_ GUARDED_BY(mutex_); - Mutex mutex_; - ThreadCondition have_data_ GUARDED_BY(mutex_); - - DISALLOW_COPY_AND_ASSIGN(SourceStreamDataQueue); -}; - // SourceStream implements the streaming interface towards V8. The main // functionality is preparing the data to give to V8 on main thread, and // actually giving the data (via GetMoreData which is called on a background // thread). class SourceStream : public v8::ScriptCompiler::ExternalSourceStream { public: - SourceStream() - : v8::ScriptCompiler::ExternalSourceStream(), - cancelled_(false), -#if DCHECK_IS_ON() - finished_(false), -#endif // DCHECK_IS_ON() - queue_lead_position_(0), - queue_tail_position_(0) { - } - + SourceStream() = default; ~SourceStream() override = default; // Called by V8 on a background thread. Should block until we can return // some data. size_t GetMoreData(const uint8_t** src) override { DCHECK(!IsMainThread()); - { - MutexLocker locker(mutex_); - if (cancelled_) - return 0; + CHECK(ready_to_run_.IsSet()); + + if (finished_) { + return 0; } - size_t length = 0; - // This will wait until there is data. - data_queue_.Consume(src, &length); - { - MutexLocker locker(mutex_); - if (cancelled_) - return 0; + + if (cancelled_.IsSet()) { + SendLoadingFinishedCallback( + &ResponseBodyLoaderClient::DidCancelLoadingBody); + return 0; } - queue_lead_position_ += length; - return length; + + if (initial_data_) { + CHECK_GT(initial_data_len_, 0u); + *src = initial_data_.release(); + size_t len = initial_data_len_; + initial_data_len_ = 0; + return len; + } + + CHECK(!initial_data_); + CHECK_EQ(initial_data_len_, 0u); + CHECK(data_pipe_.is_valid()); + + // Start a new two-phase read, blocking until data is available. + while (true) { + const void* buffer; + uint32_t num_bytes; + MojoResult result = data_pipe_->BeginReadData(&buffer, &num_bytes, + MOJO_READ_DATA_FLAG_NONE); + + switch (result) { + case MOJO_RESULT_OK: { + // num_bytes could only be 0 if the handle was being read elsewhere. + CHECK_GT(num_bytes, 0u); + + auto copy_for_script_stream = std::make_unique<uint8_t[]>(num_bytes); + memcpy(copy_for_script_stream.get(), buffer, num_bytes); + + // TODO(leszeks): It would be nice to get rid of this second copy, and + // either share ownership of the chunks, or only give chunks back to + // the client once the streaming completes. + auto copy_for_resource = std::make_unique<char[]>(num_bytes); + memcpy(copy_for_resource.get(), buffer, num_bytes); + PostCrossThreadTask( + *loading_task_runner_, FROM_HERE, + CrossThreadBind( + NotifyClientDidReceiveData, response_body_loader_client_, + WTF::Passed(std::move(copy_for_resource)), num_bytes)); + + result = data_pipe_->EndReadData(num_bytes); + CHECK_EQ(result, MOJO_RESULT_OK); + + *src = copy_for_script_stream.release(); + return num_bytes; + } + + case MOJO_RESULT_SHOULD_WAIT: { + { + base::ScopedAllowBaseSyncPrimitives + scoped_allow_base_sync_primitives; + base::ScopedBlockingCall scoped_blocking_call( + FROM_HERE, base::BlockingType::WILL_BLOCK); + result = mojo::Wait(data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE); + } + + if (result != MOJO_RESULT_OK) { + // If the producer handle was closed, then treat as EOF. + CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); + SendLoadingFinishedCallback( + &ResponseBodyLoaderClient::DidFinishLoadingBody); + return 0; + } + + // We were blocked, so check for cancelation again. + if (cancelled_.IsSet()) { + SendLoadingFinishedCallback( + &ResponseBodyLoaderClient::DidCancelLoadingBody); + return 0; + } + + // Loop to read the data. + continue; + } + + case MOJO_RESULT_FAILED_PRECONDITION: + // If the producer handle was closed, then treat as EOF. + SendLoadingFinishedCallback( + &ResponseBodyLoaderClient::DidFinishLoadingBody); + return 0; + + default: + // Some other error occurred. + SendLoadingFinishedCallback( + &ResponseBodyLoaderClient::DidFailLoadingBody); + return 0; + } + } } - void DidFinishLoading() { - DCHECK(IsMainThread()); -#if DCHECK_IS_ON() - finished_ = true; -#endif // DCHECK_IS_ON() - data_queue_.Finish(); - } - - void DidReceiveData(ScriptResource* resource, ScriptStreamer* streamer) { - DCHECK(IsMainThread()); - PrepareDataOnMainThread(resource, streamer); + void DrainRemainingDataWithoutStreaming() { + DCHECK(!IsMainThread()); + if (!finished_) { + // Keep reading data until we finish (returning 0). It won't be streaming + // compiled any more, but it will continue being forwarded to the client. + const uint8_t* ignored_data; + while (GetMoreData(&ignored_data) != 0) { + } + } + CHECK(finished_); } void Cancel() { @@ -164,101 +164,88 @@ // The script is no longer needed by the upper layers. Stop streaming // it. The next time GetMoreData is called (or woken up), it will return // 0, which will be interpreted as EOS by V8 and the parsing will - // fail. ScriptStreamer::streamingComplete will be called, and at that + // fail. ScriptStreamer::StreamingComplete will be called, and at that // point we will release the references to SourceStream. - { - MutexLocker locker(mutex_); - cancelled_ = true; - } - data_queue_.Finish(); + cancelled_.Set(); } - private: - void PrepareDataOnMainThread(ScriptResource* resource, - ScriptStreamer* streamer) { + void TakeDataAndPipeOnMainThread( + ScriptResource* resource, + ScriptStreamer* streamer, + mojo::ScopedDataPipeConsumerHandle data_pipe, + ResponseBodyLoaderClient* response_body_loader_client, + scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner) { DCHECK(IsMainThread()); - - bool was_canceled; - { - MutexLocker locker(mutex_); - was_canceled = cancelled_; - } - if (was_canceled) { - data_queue_.Finish(); - return; - } + CHECK(data_pipe); + CHECK(!ready_to_run_.IsSet()); + CHECK(!cancelled_.IsSet()); // The Resource must still be alive; otherwise we should've cancelled // the streaming (if we have cancelled, the background thread is not // waiting). DCHECK(resource); - if (V8CodeCache::HasCodeCache(resource->CacheHandler())) { - // The resource has a code cache entry, so it's unnecessary to stream - // and parse the code. Cancel the streaming and resume the non-streaming - // code path which will consume the code cache. - streamer->SuppressStreaming(ScriptStreamer::kHasCodeCache); - Cancel(); - return; + const SharedBuffer* resource_buffer = resource->ResourceBuffer().get(); + + CHECK(!initial_data_); + CHECK_EQ(initial_data_len_, 0u); + + // Get the data that is already in the ResourceBuffer. + const size_t length = resource_buffer->size(); + + if (length > 0) { + initial_data_.reset(new uint8_t[length]); + + bool success = resource_buffer->GetBytes( + reinterpret_cast<void*>(initial_data_.get()), length); + CHECK(success); + + initial_data_len_ = length; } - if (!resource_buffer_) { - // We don't have a buffer yet. Try to get it from the resource. - resource_buffer_ = resource->ResourceBuffer(); - } + data_pipe_ = std::move(data_pipe); + response_body_loader_client_ = response_body_loader_client; + loading_task_runner_ = loading_task_runner; - FetchDataFromResourceBuffer(); + CHECK(data_pipe_); + ready_to_run_.Set(); } - void FetchDataFromResourceBuffer() { - DCHECK(IsMainThread()); - MutexLocker locker(mutex_); - -#if DCHECK_IS_ON() - DCHECK(!finished_); -#endif // DCHECK_IS_ON() - - if (cancelled_) { - data_queue_.Finish(); - return; - } - - // Get as much data from the ResourceBuffer as we can in one chunk. - const size_t length = resource_buffer_->size() - queue_tail_position_; - - uint8_t* const copied_data = new uint8_t[length]; - size_t pos = 0; - - for (auto it = resource_buffer_->GetIteratorAt(queue_tail_position_); - it != resource_buffer_->end(); ++it) { - memcpy(copied_data + pos, it->data(), it->size()); - pos += it->size(); - } - DCHECK_EQ(pos, length); - queue_tail_position_ = resource_buffer_->size(); - data_queue_.Produce(copied_data, length); + private: + static void NotifyClientDidReceiveData( + ResponseBodyLoaderClient* response_body_loader_client, + std::unique_ptr<char[]> data, + uint32_t data_size) { + response_body_loader_client->DidReceiveData( + base::make_span(data.get(), data_size)); } - // For coordinating between the main thread and background thread tasks. - Mutex mutex_; + void SendLoadingFinishedCallback( + void (ResponseBodyLoaderClient::*callback)()) { + DCHECK(!IsMainThread()); + CHECK(!finished_); + PostCrossThreadTask( + *loading_task_runner_, FROM_HERE, + CrossThreadBind(callback, response_body_loader_client_)); + finished_ = true; + } - bool cancelled_ GUARDED_BY(mutex_); // Used by both threads. + // TODO(leszeks): Make this a DCHECK-only flag. + base::AtomicFlag ready_to_run_; + base::AtomicFlag cancelled_; -#if DCHECK_IS_ON() - bool finished_; // Only used by the main thread. -#endif // DCHECK_IS_ON() + // Only used by background thread + bool finished_ = false; - // The shared buffer containing the resource data + state variables. - scoped_refptr<const SharedBuffer> - resource_buffer_; // Only used by the main thread. + // The initial data that was already on the Resource, rather than being read + // directly from the data pipe. + std::unique_ptr<uint8_t[]> initial_data_; + size_t initial_data_len_ = 0; - // The queue contains the data to be passed to the V8 thread. - // queueLeadPosition: data we have handed off to the V8 thread. - // queueTailPosition: end of data we have enqued in the queue. - // bookmarkPosition: position of the bookmark. - SourceStreamDataQueue data_queue_; // Thread safe. - size_t queue_lead_position_; // Only used by v8 thread. - size_t queue_tail_position_ GUARDED_BY(mutex_); // Used by both threads. + mojo::ScopedDataPipeConsumerHandle data_pipe_; + CrossThreadWeakPersistent<ResponseBodyLoaderClient> + response_body_loader_client_; + scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_; DISALLOW_COPY_AND_ASSIGN(SourceStream); }; @@ -306,10 +293,9 @@ CrossThreadBind(&ScriptStreamer::StreamingComplete, WrapCrossThreadPersistent(this))); - // The task might delete ScriptStreamer, so it's not safe to do anything - // after posting it. Note that there's no way to guarantee that this - // function has returned before the task is ran - however, we should not - // access the "this" object after posting the task. + // The task might be the only remaining reference to the ScriptStreamer, and + // there's no way to guarantee that this function has returned before the task + // is ran, so we should not access the "this" object after posting the task. } void ScriptStreamer::Cancel() { @@ -338,7 +324,8 @@ void RunScriptStreamingTask( std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task, - ScriptStreamer* streamer) { + ScriptStreamer* streamer, + SourceStream* stream) { TRACE_EVENT_WITH_FLOW1( "v8,devtools.timeline," TRACE_DISABLED_BY_DEFAULT("v8.compile"), "v8.parseOnBackground", streamer, @@ -348,6 +335,12 @@ // Running the task can and will block: SourceStream::GetSomeData will get // called and it will block and wait for data from the network. task->Run(); + + // V8 may have exited early due to a parsing error, so make sure we finish + // draining the datapipe to the client. + // TODO(leszeks): This could be done asynchronously, using a mojo watcher. + stream->DrainRemainingDataWithoutStreaming(); + streamer->StreamingCompleteOnBackgroundThread(); } @@ -358,90 +351,126 @@ return resource_buffer_size >= small_script_threshold_; } -void ScriptStreamer::NotifyAppendData() { +// Try to start streaming the script from the given datapipe, taking ownership +// of the datapipe and weak ownership of the client. Returns true if streaming +// succeeded and false otherwise. +// +// Streaming may fail to start because: +// +// * The encoding is invalid (not UTF-8 or one-byte data) +// * The script is too small (see HasEnoughDataForStreaming) +// * There is a code cache for this script already +// * V8 failed to create a script streamer +// +// If this method returns true, the datapipe handle will be cleared and the +// streamer becomes responsible for draining the datapipe and forwarding data +// to the client. Otherwise, the caller should continue as if this were a no-op. +bool ScriptStreamer::TryStartStreaming( + mojo::ScopedDataPipeConsumerHandle* data_pipe, + ResponseBodyLoaderClient* response_body_loader_client) { DCHECK(IsMainThread()); if (streaming_suppressed_) - return; - if (!have_enough_data_for_streaming_) { - // Even if the first data chunk is small, the script can still be big - // enough - wait until the next data chunk comes before deciding whether - // to start the streaming. - DCHECK(script_resource_->ResourceBuffer()); - if (!HasEnoughDataForStreaming(script_resource_->ResourceBuffer()->size())) - return; - have_enough_data_for_streaming_ = true; - - { - // Check for BOM (byte order marks), because that might change our - // understanding of the data encoding. - char maybe_bom[kMaximumLengthOfBOM] = {}; - if (!script_resource_->ResourceBuffer()->GetBytes(maybe_bom, - kMaximumLengthOfBOM)) { - NOTREACHED(); - return; - } - - std::unique_ptr<TextResourceDecoder> decoder( - std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions( - TextResourceDecoderOptions::kPlainTextContent, - WTF::TextEncoding(script_resource_->Encoding())))); - decoder->CheckForBOM(maybe_bom, kMaximumLengthOfBOM); - - // The encoding may change when we see the BOM. Check for BOM now - // and update the encoding from the decoder when necessary. Supress - // streaming if the encoding is unsupported. - // - // Also note that have at least s_smallScriptThreshold worth of - // data, which is more than enough for detecting a BOM. - if (!ConvertEncoding(decoder->Encoding().GetName(), &encoding_)) { - SuppressStreaming(kEncodingNotSupported); - return; - } - } - - DCHECK(!stream_); - DCHECK(!source_); - stream_ = new SourceStream; - // |source_| takes ownership of |stream_|. - source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(stream_, - encoding_); - - std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> - script_streaming_task( - base::WrapUnique(v8::ScriptCompiler::StartStreamingScript( - V8PerIsolateData::MainThreadIsolate(), source_.get(), - compile_options_))); - if (!script_streaming_task) { - // V8 cannot stream the script. - SuppressStreaming(kV8CannotStream); - stream_ = nullptr; - source_.reset(); - return; - } - - TRACE_EVENT_WITH_FLOW1( - TRACE_DISABLED_BY_DEFAULT("v8.compile"), "v8.streamingCompile.start", - this, TRACE_EVENT_FLAG_FLOW_OUT, "data", - inspector_parse_script_event::Data(this->ScriptResourceIdentifier(), - this->ScriptURLString())); - - // Script streaming tasks are high priority, as they can block the parser, - // and they can (and probably will) block during their own execution as - // they wait for more input. - // - // TODO(leszeks): Decrease the priority of these tasks where possible. - worker_pool::PostTaskWithTraits( - FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()}, - CrossThreadBind(RunScriptStreamingTask, - WTF::Passed(std::move(script_streaming_task)), - WrapCrossThreadPersistent(this))); - } + return false; if (stream_) - stream_->DidReceiveData(script_resource_, this); + return false; + + DCHECK(!have_enough_data_for_streaming_); + + // Even if the first data chunk is small, the script can still be big + // enough - wait until the next data chunk comes before deciding whether + // to start the streaming. + DCHECK(script_resource_->ResourceBuffer()); + if (!HasEnoughDataForStreaming(script_resource_->ResourceBuffer()->size())) + return false; + have_enough_data_for_streaming_ = true; + + { + // Check for BOM (byte order marks), because that might change our + // understanding of the data encoding. + char maybe_bom[kMaximumLengthOfBOM] = {}; + if (!script_resource_->ResourceBuffer()->GetBytes(maybe_bom, + kMaximumLengthOfBOM)) { + NOTREACHED(); + return false; + } + + std::unique_ptr<TextResourceDecoder> decoder( + std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions( + TextResourceDecoderOptions::kPlainTextContent, + WTF::TextEncoding(script_resource_->Encoding())))); + decoder->CheckForBOM(maybe_bom, kMaximumLengthOfBOM); + + // The encoding may change when we see the BOM. Check for BOM now + // and update the encoding from the decoder when necessary. Suppress + // streaming if the encoding is unsupported. + // + // Also note that have at least s_smallScriptThreshold worth of + // data, which is more than enough for detecting a BOM. + if (!ConvertEncoding(decoder->Encoding().GetName(), &encoding_)) { + SuppressStreaming(kEncodingNotSupported); + return false; + } + } + + if (V8CodeCache::HasCodeCache(script_resource_->CacheHandler())) { + // The resource has a code cache entry, so it's unnecessary to stream + // and parse the code. + // TODO(leszeks): Can we even reach this code path with data pipes? + SuppressStreaming(ScriptStreamer::kHasCodeCache); + stream_ = nullptr; + source_.reset(); + return false; + } + + DCHECK(!stream_); + DCHECK(!source_); + stream_ = new SourceStream; + // |source_| takes ownership of |stream_|, and will keep |stream_| alive until + // |source_| is destructed. + source_ = + std::make_unique<v8::ScriptCompiler::StreamedSource>(stream_, encoding_); + + std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> + script_streaming_task( + base::WrapUnique(v8::ScriptCompiler::StartStreamingScript( + V8PerIsolateData::MainThreadIsolate(), source_.get(), + compile_options_))); + if (!script_streaming_task) { + // V8 cannot stream the script. + SuppressStreaming(kV8CannotStream); + stream_ = nullptr; + source_.reset(); + return false; + } + + TRACE_EVENT_WITH_FLOW1( + TRACE_DISABLED_BY_DEFAULT("v8.compile"), "v8.streamingCompile.start", + this, TRACE_EVENT_FLAG_FLOW_OUT, "data", + inspector_parse_script_event::Data(this->ScriptResourceIdentifier(), + this->ScriptURLString())); + + stream_->TakeDataAndPipeOnMainThread( + script_resource_, this, std::move(*data_pipe), + response_body_loader_client, loading_task_runner_); + + // Script streaming tasks are high priority, as they can block the parser, + // and they can (and probably will) block during their own execution as + // they wait for more input. + // + // TODO(leszeks): Decrease the priority of these tasks where possible. + worker_pool::PostTaskWithTraits( + FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()}, + CrossThreadBind(RunScriptStreamingTask, + WTF::Passed(std::move(script_streaming_task)), + WrapCrossThreadPersistent(this), + WTF::CrossThreadUnretained(stream_))); + + return true; } void ScriptStreamer::NotifyFinished() { DCHECK(IsMainThread()); + // A special case: empty and small scripts. We didn't receive enough data to // start the streaming before this notification. In that case, there won't // be a "parsing complete" notification either, and we should not wait for @@ -450,9 +479,6 @@ SuppressStreaming(kScriptTooSmall); } - if (stream_) { - stream_->DidFinishLoading(); - } loading_finished_ = true; NotifyFinishedToClient();
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/third_party/blink/renderer/bindings/core/v8/script_streamer.h index 07b81d4..43f3998a 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.h +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/single_thread_task_runner.h" +#include "mojo/public/cpp/system/data_pipe.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -18,6 +19,7 @@ class ScriptResource; class SourceStream; +class ResponseBodyLoaderClient; // ScriptStreamer streams incomplete script data to V8 so that it can be parsed // while it's loaded. ScriptResource holds a reference to ScriptStreamer. @@ -103,7 +105,9 @@ } // Called by ScriptResource when data arrives from the network. - void NotifyAppendData(); + bool TryStartStreaming(mojo::ScopedDataPipeConsumerHandle* data_pipe, + ResponseBodyLoaderClient* response_body_loader_client); + // Called by ScriptResource when loading has completed. // // Should not be called synchronously, as it can trigger script resource
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc index 3a6f3ba..14a24af 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -5,11 +5,13 @@ #include "third_party/blink/renderer/bindings/core/v8/script_streamer.h" #include <memory> +#include <utility> #include "base/single_thread_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_url_loader.h" #include "third_party/blink/public/platform/web_url_loader_mock_factory.h" #include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h" #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h" @@ -25,8 +27,12 @@ #include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/loader/fetch/cross_origin_attribute_value.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h" +#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h" #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h" +#include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h" +#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -37,63 +43,118 @@ namespace { +class TestResourceClient final + : public GarbageCollectedFinalized<TestResourceClient>, + public ResourceClient { + USING_GARBAGE_COLLECTED_MIXIN(TestResourceClient); + + public: + TestResourceClient() : finished_(false) {} + bool Finished() const { return finished_; } + + void DataReceived(Resource*, + const char* /* data */, + size_t /* length */) override {} + void NotifyFinished(Resource*) override { finished_ = true; } + + // Name for debugging, e.g. shown in memory-infra. + String DebugName() const override { return "TestResourceClient"; } + + private: + bool finished_; +}; + +// TODO(leszeks): This class has a similar class in resource_loader_test.cc, +// the two should probably share the same class. +class NoopLoaderFactory final : public ResourceFetcher::LoaderFactory { + std::unique_ptr<WebURLLoader> CreateURLLoader( + const ResourceRequest& request, + const ResourceLoaderOptions& options, + scoped_refptr<base::SingleThreadTaskRunner>) override { + return std::make_unique<NoopWebURLLoader>(); + } + std::unique_ptr<CodeCacheLoader> CreateCodeCacheLoader() override { + return Platform::Current()->CreateCodeCacheLoader(); + } + + class NoopWebURLLoader final : public WebURLLoader { + public: + ~NoopWebURLLoader() override = default; + void LoadSynchronously(const WebURLRequest&, + WebURLLoaderClient*, + WebURLResponse&, + base::Optional<WebURLError>&, + WebData&, + int64_t& encoded_data_length, + int64_t& encoded_body_length, + WebBlobInfo& downloaded_blob) override { + NOTREACHED(); + } + void LoadAsynchronously(const WebURLRequest&, + WebURLLoaderClient*) override {} + + void Cancel() override {} + void SetDefersLoading(bool) override {} + void DidChangePriority(WebURLRequest::Priority, int) override { + NOTREACHED(); + } + }; +}; + class ScriptStreamingTest : public testing::Test { public: ScriptStreamingTest() - : loading_task_runner_(platform_->test_task_runner()), - dummy_page_holder_(DummyPageHolder::Create(IntSize(800, 600))) { - dummy_page_holder_->GetPage().GetSettings().SetScriptEnabled(true); - MockScriptElementBase* element = MockScriptElementBase::Create(); - // Basically we are not interested in ScriptElementBase* calls, just making - // the method(s) to return default values. - EXPECT_CALL(*element, IntegrityAttributeValue()) - .WillRepeatedly(testing::Return(String())); - EXPECT_CALL(*element, GetDocument()) - .WillRepeatedly(testing::ReturnRef(dummy_page_holder_->GetDocument())); - EXPECT_CALL(*element, Loader()).WillRepeatedly(testing::Return(nullptr)); + : url_("http://www.streaming-test.com/"), + loading_task_runner_(platform_->test_task_runner()) { + auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); + FetchContext* context = MakeGarbageCollected<MockFetchContext>(); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>( + ResourceFetcherInit(*properties, context, loading_task_runner_, + MakeGarbageCollected<NoopLoaderFactory>())); - KURL url("http://www.streaming-test.com/"); - Platform::Current()->GetURLLoaderMockFactory()->RegisterURL( - url, WrappedResourceResponse(ResourceResponse()), ""); - pending_script_ = ClassicPendingScript::Fetch( - url, dummy_page_holder_->GetDocument(), ScriptFetchOptions(), - kCrossOriginAttributeNotSet, UTF8Encoding(), element, - FetchParameters::kNoDefer); - pending_script_->SetSchedulingType(ScriptSchedulingType::kParserBlocking); + ResourceRequest request(url_); + request.SetRequestContext(mojom::RequestContextType::SCRIPT); + + resource_client_ = MakeGarbageCollected<TestResourceClient>(); + FetchParameters params(request); + resource_ = ScriptResource::Fetch(params, fetcher, resource_client_, + ScriptResource::kAllowStreaming); + resource_->AddClient(resource_client_, loading_task_runner_.get()); + ScriptStreamer::SetSmallScriptThresholdForTesting(0); - Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(url); - ResourceResponse response(url); + ResourceResponse response(url_); response.SetHttpStatusCode(200); - GetResource()->SetResponse(response); - } + resource_->SetResponse(response); - ~ScriptStreamingTest() override { - if (pending_script_) - pending_script_->Dispose(); - } - - ClassicPendingScript* GetPendingScript() const { - return pending_script_.Get(); + resource_->Loader()->DidReceiveResponse(WrappedResourceResponse(response)); + resource_->Loader()->DidStartLoadingResponseBody( + std::move(data_pipe_.consumer_handle)); } ScriptSourceCode GetScriptSourceCode() const { - ClassicScript* classic_script = GetPendingScript()->GetSource(NullURL()); - DCHECK(classic_script); - return classic_script->GetScriptSourceCode(); + ScriptStreamer* streamer = resource_->TakeStreamer(); + if (streamer) { + if (streamer->StreamingSuppressed()) { + return ScriptSourceCode(nullptr, resource_, + streamer->StreamingSuppressedReason()); + } + return ScriptSourceCode(streamer, resource_, ScriptStreamer::kInvalid); + } + return ScriptSourceCode(nullptr, resource_, resource_->NoStreamerReason()); } Settings* GetSettings() const { return &dummy_page_holder_->GetPage().GetSettings(); } - ScriptResource* GetResource() const { - return ToScriptResource(pending_script_->GetResource()); - } - protected: - void AppendData(ScriptResource* resource, const char* data) { - resource->AppendData(data, strlen(data)); + void AppendData(const char* data) { + uint32_t data_len = strlen(data); + MojoResult result = data_pipe_.producer_handle->WriteData( + data, &data_len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); + EXPECT_EQ(result, MOJO_RESULT_OK); + // Yield control to the background thread, so that V8 gets a chance to // process the data before the main thread adds more. Note that we // cannot fully control in what kind of chunks the data is passed to V8 @@ -102,24 +163,20 @@ test::YieldCurrentThread(); } - void AppendData(const char* data) { AppendData(GetResource(), data); } - - void AppendPadding(ScriptResource* resource) { + void AppendPadding() { for (int i = 0; i < 10; ++i) { - AppendData(resource, - " /* this is padding to make the script long enough, so " - "that V8's buffer gets filled and it starts processing " - "the data */ "); + AppendData( + " /* this is padding to make the script long enough, so " + "that V8's buffer gets filled and it starts processing " + "the data */ "); } } - void AppendPadding() { AppendPadding(GetResource()); } - void Finish() { - GetResource()->Loader()->DidFinishLoading( - TimeTicks(), 0, 0, 0, false, - std::vector<network::cors::PreflightTimingInfo>()); - GetResource()->SetStatus(ResourceStatus::kCached); + resource_->Loader()->DidFinishLoading(base::TimeTicks(), 0, 0, 0, false, + {}); + data_pipe_.producer_handle.reset(); + resource_->SetStatus(ResourceStatus::kCached); } void ProcessTasksUntilStreamingComplete() { platform_->RunUntilIdle(); } @@ -127,29 +184,16 @@ ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> platform_; + KURL url_; scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_; - // The PendingScript where we stream from. These don't really - // fetch any data outside the test; the test controls the data by calling - // ScriptResource::AppendData. - Persistent<ClassicPendingScript> pending_script_; + + Persistent<TestResourceClient> resource_client_; + Persistent<ScriptResource> resource_; + mojo::DataPipe data_pipe_; std::unique_ptr<DummyPageHolder> dummy_page_holder_; }; -class TestPendingScriptClient final - : public GarbageCollectedFinalized<TestPendingScriptClient>, - public PendingScriptClient { - USING_GARBAGE_COLLECTED_MIXIN(TestPendingScriptClient); - - public: - TestPendingScriptClient() : finished_(false) {} - void PendingScriptFinished(PendingScript*) override { finished_ = true; } - bool Finished() const { return finished_; } - - private: - bool finished_; -}; - // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being // currently unable to block and wait for the script streaming thread. TEST_F(ScriptStreamingTest, DISABLED_CompilingStreamedScript) { @@ -157,23 +201,21 @@ // Test that we can successfully compile a streamed script. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); AppendData("function foo() {"); AppendPadding(); AppendData("return 5; }"); AppendPadding(); AppendData("foo();"); - EXPECT_FALSE(client->Finished()); + EXPECT_FALSE(resource_client_->Finished()); Finish(); // Process tasks on the main thread until the streaming background thread // has completed its tasks. ProcessTasksUntilStreamingComplete(); - EXPECT_TRUE(client->Finished()); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_TRUE(source_code.Streamer()); v8::TryCatch try_catch(scope.GetIsolate()); @@ -195,28 +237,23 @@ // currently unable to block and wait for the script streaming thread. TEST_F(ScriptStreamingTest, DISABLED_CompilingStreamedScriptWithParseError) { // Test that scripts with parse errors are handled properly. In those cases, - // the V8 side typically finished before loading finishes: make sure we - // handle it gracefully. + // V8 stops reading the network stream: make sure we handle it gracefully. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); AppendData("function foo() {"); AppendData("this is the part which will be a parse error"); // V8 won't realize the parse error until it actually starts parsing the // script, and this happens only when its buffer is filled. AppendPadding(); - EXPECT_FALSE(client->Finished()); - - // Force the V8 side to finish before the loading. - ProcessTasksUntilStreamingComplete(); - EXPECT_FALSE(client->Finished()); - + EXPECT_FALSE(resource_client_->Finished()); Finish(); - EXPECT_TRUE(client->Finished()); + // Process tasks on the main thread until the streaming background thread + // has completed its tasks. + ProcessTasksUntilStreamingComplete(); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_TRUE(source_code.Streamer()); v8::TryCatch try_catch(scope.GetIsolate()); @@ -240,10 +277,8 @@ // Test that the upper layers (PendingScript and up) can be ramped down // while streaming is ongoing, and ScriptStreamer handles it gracefully. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); AppendData("function foo() {"); // In general, we cannot control what the background thread is doing @@ -252,14 +287,13 @@ // Simulate cancelling the network load (e.g., because the user navigated // away). - EXPECT_FALSE(client->Finished()); - GetPendingScript()->Dispose(); - pending_script_ = nullptr; // This will destroy m_resource. + EXPECT_FALSE(resource_client_->Finished()); + resource_ = nullptr; // The V8 side will complete too. This should not crash. We don't receive // any results from the streaming and the client doesn't get notified. ProcessTasksUntilStreamingComplete(); - EXPECT_FALSE(client->Finished()); + EXPECT_FALSE(resource_client_->Finished()); } // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being @@ -268,62 +302,55 @@ // Test that the upper layers (PendingScript and up) can be ramped down // before streaming is started, and ScriptStreamer handles it gracefully. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); // In general, we cannot control what the background thread is doing // (whether it's parsing or waiting for more data). In this test, we have // given it so little data that it's surely waiting for more. - EXPECT_FALSE(client->Finished()); + EXPECT_FALSE(resource_client_->Finished()); // Keep the resource alive - Persistent<ScriptResource> resource = GetResource(); + Persistent<ScriptResource> resource = resource_; // Simulate cancelling the network load (e.g., because the user navigated // away). - GetPendingScript()->Dispose(); - pending_script_ = nullptr; // This would destroy m_resource, but we are still - // holding on to it here. + resource_ = nullptr; // Make sure the streaming starts. - AppendData(resource, "function foo() {"); - AppendPadding(resource); + AppendData("function foo() {"); + AppendPadding(); resource.Clear(); // The V8 side will complete too. This should not crash. We don't receive // any results from the streaming and the client doesn't get notified. ProcessTasksUntilStreamingComplete(); - EXPECT_FALSE(client->Finished()); + EXPECT_FALSE(resource_client_->Finished()); } // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being // currently unable to block and wait for the script streaming thread. TEST_F(ScriptStreamingTest, DISABLED_SuppressingStreaming) { - // If we notice during streaming that there is a code cache, streaming + // If we notice before streaming that there is a code cache, streaming // is suppressed (V8 doesn't parse while the script is loading), and the // upper layer (ScriptResourceClient) should get a notification when the // script is loaded. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); - AppendData("function foo() {"); - AppendPadding(); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); - SingleCachedMetadataHandler* cache_handler = GetResource()->CacheHandler(); + SingleCachedMetadataHandler* cache_handler = resource_->CacheHandler(); EXPECT_TRUE(cache_handler); cache_handler->SetCachedMetadata(V8CodeCache::TagForCodeCache(cache_handler), reinterpret_cast<const uint8_t*>("X"), 1, CachedMetadataHandler::kCacheLocally); + AppendData("function foo() {"); AppendPadding(); Finish(); ProcessTasksUntilStreamingComplete(); - EXPECT_TRUE(client->Finished()); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); // ScriptSourceCode doesn't refer to the streamer, since we have suppressed @@ -339,16 +366,13 @@ // (ScriptResourceClient) should be notified when an empty script has been // loaded. V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); // Finish the script without sending any data. Finish(); - // The finished notification should arrive immediately and not be cycled - // through a background thread. - EXPECT_TRUE(client->Finished()); + ProcessTasksUntilStreamingComplete(); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_FALSE(source_code.Streamer()); @@ -361,18 +385,14 @@ V8TestingScope scope; ScriptStreamer::SetSmallScriptThresholdForTesting(100); - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); AppendData("function foo() { }"); Finish(); - - // The finished notification should arrive immediately and not be cycled - // through a background thread. - EXPECT_TRUE(client->Finished()); + ProcessTasksUntilStreamingComplete(); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_FALSE(source_code.Streamer()); @@ -386,10 +406,8 @@ V8TestingScope scope; ScriptStreamer::SetSmallScriptThresholdForTesting(100); - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); // This is the first data chunk which is small. AppendData("function foo() { }"); @@ -400,7 +418,7 @@ Finish(); ProcessTasksUntilStreamingComplete(); - EXPECT_TRUE(client->Finished()); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_TRUE(source_code.Streamer()); v8::TryCatch try_catch(scope.GetIsolate()); @@ -424,14 +442,12 @@ // It's possible that the encoding of the Resource changes after we start // loading it. V8TestingScope scope; - GetResource()->SetEncodingForTest("windows-1252"); + resource_->SetEncodingForTest("windows-1252"); - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); - GetResource()->SetEncodingForTest("UTF-8"); + resource_->SetEncodingForTest("UTF-8"); // \xec\x92\x81 are the raw bytes for \uc481. AppendData( "function foo() { var foob\xec\x92\x81r = 13; return foob\xec\x92\x81r; " @@ -440,7 +456,7 @@ Finish(); ProcessTasksUntilStreamingComplete(); - EXPECT_TRUE(client->Finished()); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_TRUE(source_code.Streamer()); v8::TryCatch try_catch(scope.GetIsolate()); @@ -466,12 +482,10 @@ V8TestingScope scope; // This encoding is wrong on purpose. - GetResource()->SetEncodingForTest("windows-1252"); + resource_->SetEncodingForTest("windows-1252"); - GetResource()->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->StartStreaming(loading_task_runner_); + resource_->SetClientIsWaitingForFinished(); // \xef\xbb\xbf is the UTF-8 byte order mark. \xec\x92\x81 are the raw bytes // for \uc481. @@ -481,7 +495,7 @@ Finish(); ProcessTasksUntilStreamingComplete(); - EXPECT_TRUE(client->Finished()); + EXPECT_TRUE(resource_client_->Finished()); ScriptSourceCode source_code = GetScriptSourceCode(); EXPECT_TRUE(source_code.Streamer()); v8::TryCatch try_catch(scope.GetIsolate()); @@ -504,14 +518,12 @@ // A test for crbug.com/711703. Should not crash. TEST_F(ScriptStreamingTest, DISABLED_GarbageCollectDuringStreaming) { V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); + resource_->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); - EXPECT_FALSE(client->Finished()); + resource_->SetClientIsWaitingForFinished(); + EXPECT_FALSE(resource_client_->Finished()); - pending_script_ = nullptr; + resource_ = nullptr; ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); @@ -521,11 +533,9 @@ // currently unable to block and wait for the script streaming thread. TEST_F(ScriptStreamingTest, DISABLED_ResourceSetRevalidatingRequest) { V8TestingScope scope; - GetResource()->StartStreaming(loading_task_runner_); + resource_->StartStreaming(loading_task_runner_); - TestPendingScriptClient* client = - MakeGarbageCollected<TestPendingScriptClient>(); - GetPendingScript()->WatchForLoad(client); + resource_->SetClientIsWaitingForFinished(); // Kick the streaming off. AppendData("function foo() {"); @@ -535,17 +545,17 @@ ProcessTasksUntilStreamingComplete(); // Second start streaming should fail. - GetResource()->StartStreaming(loading_task_runner_); - EXPECT_FALSE(GetResource()->HasRunningStreamer()); + resource_->StartStreaming(loading_task_runner_); + EXPECT_FALSE(resource_->HasRunningStreamer()); - ResourceRequest request(GetResource()->Url()); - GetResource()->SetRevalidatingRequest(request); + ResourceRequest request(resource_->Url()); + resource_->SetRevalidatingRequest(request); // The next streaming should still fail, but the reason should be // "kRevalidate". - GetResource()->StartStreaming(loading_task_runner_); - EXPECT_FALSE(GetResource()->HasRunningStreamer()); - EXPECT_EQ(GetResource()->NoStreamerReason(), ScriptStreamer::kRevalidate); + resource_->StartStreaming(loading_task_runner_); + EXPECT_FALSE(resource_->HasRunningStreamer()); + EXPECT_EQ(resource_->NoStreamerReason(), ScriptStreamer::kRevalidate); } } // namespace
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index f27b98774..0fdf8ba 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -696,6 +696,7 @@ v8::Isolate* isolate = V8PerIsolateData::Initialize(scheduler->V8TaskRunner(), v8_context_snapshot_mode); + scheduler->SetV8Isolate(isolate); // ThreadState::isolate_ needs to be set before setting the EmbedderHeapTracer // as setting the tracer indicates that a V8 garbage collection should trace
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc index 4805cbc..0c926d7 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -187,8 +187,7 @@ DISALLOW_COPY_AND_ASSIGN(ExceptionToAbortStreamingScope); }; -SingleCachedMetadataHandler* GetCachedMetadataHandler(ScriptState* script_state, - const KURL& url) { +RawResource* GetRawResource(ScriptState* script_state, const KURL& url) { if (!RuntimeEnabledFeatures::WasmCodeCacheEnabled()) return nullptr; ExecutionContext* execution_context = ExecutionContext::From(script_state); @@ -205,8 +204,7 @@ // Wasm modules should be fetched as raw resources. DCHECK_EQ(ResourceType::kRaw, resource->GetType()); - RawResource* raw_resource = ToRawResource(resource); - return raw_resource->ScriptCacheHandler(); + return ToRawResource(resource); } class WasmStreamingClient : public v8::WasmStreaming::Client { @@ -217,7 +215,6 @@ v8::Local<v8::Context> context) : response_url_(response_url), response_time_(response_time), - isolate_(isolate), context_(isolate, context) { context_.SetWeak(); } @@ -246,32 +243,26 @@ "v8.wasm.cachedModule", TRACE_EVENT_SCOPE_THREAD, "producedCacheSize", serialized_module.size); - v8::HandleScope handle_scope(isolate_); - auto context = context_.Get(isolate_); - ScriptState* script_state = ScriptState::From(context); - SingleCachedMetadataHandler* cache_handler = - GetCachedMetadataHandler(script_state, response_url_); - if (cache_handler) { - cache_handler->SetCachedMetadata( - kWasmModuleTag, - reinterpret_cast<const uint8_t*>(serialized_module.buffer.get()), - serialized_module.size); - return; - } - // The resources needed for caching have been GC'ed, but we should still // save the compiled module. Use the platform API directly. - Platform::Current()->CacheMetadata( - blink::mojom::CodeCacheType::kWebAssembly, response_url_, - response_time_, + scoped_refptr<CachedMetadata> cached_metadata = CachedMetadata::Create( + kWasmModuleTag, reinterpret_cast<const uint8_t*>(serialized_module.buffer.get()), serialized_module.size); + + const Vector<uint8_t>& serialized_data = cached_metadata->SerializedData(); + // Make sure the data could be copied. + if (serialized_data.size() < serialized_module.size) + return; + + Platform::Current()->CacheMetadata( + blink::mojom::CodeCacheType::kWebAssembly, response_url_, + response_time_, serialized_data.data(), serialized_data.size()); } private: KURL response_url_; base::Time response_time_; - v8::Isolate* isolate_; v8::Global<v8::Context> context_; DISALLOW_COPY_AND_ASSIGN(WasmStreamingClient); @@ -338,28 +329,31 @@ } KURL url(response->url()); - SingleCachedMetadataHandler* cache_handler = - GetCachedMetadataHandler(script_state, url); - if (cache_handler) { - streaming->SetClient(std::make_shared<WasmStreamingClient>( - url, response->GetResponse()->ResponseTime(), args.GetIsolate(), - script_state->GetContext())); - scoped_refptr<CachedMetadata> cached_module = - cache_handler->GetCachedMetadata(kWasmModuleTag); - if (cached_module) { - TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), - "v8.wasm.moduleCacheHit", TRACE_EVENT_SCOPE_THREAD, - "url", url.GetString().Utf8(), "consumedCacheSize", - cached_module->size()); - bool is_valid = streaming->SetCompiledModuleBytes( - reinterpret_cast<const uint8_t*>(cached_module->Data()), - cached_module->size()); - if (!is_valid) { - TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), - "v8.wasm.moduleCacheInvalid", - TRACE_EVENT_SCOPE_THREAD); - cache_handler->ClearCachedMetadata( - CachedMetadataHandler::kSendToPlatform); + RawResource* raw_resource = GetRawResource(script_state, url); + if (raw_resource) { + SingleCachedMetadataHandler* cache_handler = + raw_resource->ScriptCacheHandler(); + if (cache_handler) { + streaming->SetClient(std::make_shared<WasmStreamingClient>( + url, raw_resource->GetResponse().ResponseTime(), args.GetIsolate(), + script_state->GetContext())); + scoped_refptr<CachedMetadata> cached_module = + cache_handler->GetCachedMetadata(kWasmModuleTag); + if (cached_module) { + TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.moduleCacheHit", TRACE_EVENT_SCOPE_THREAD, + "url", url.GetString().Utf8(), "consumedCacheSize", + cached_module->size()); + bool is_valid = streaming->SetCompiledModuleBytes( + reinterpret_cast<const uint8_t*>(cached_module->Data()), + cached_module->size()); + if (!is_valid) { + TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), + "v8.wasm.moduleCacheInvalid", + TRACE_EVENT_SCOPE_THREAD); + cache_handler->ClearCachedMetadata( + CachedMetadataHandler::kSendToPlatform); + } } } }
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py index 2746b75d..c0dddb4 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py
@@ -71,7 +71,7 @@ css_name_and_enum_pairs = [ (property_['name'].original, - 'static_cast<int>(' + property_['property_id'] + ')') + 'static_cast<int>(CSSPropertyID::' + property_['enum_key'] + ')') for property_ in self._css_properties.properties_including_aliases] return {
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py b/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py index 361fb6f..3a18d15 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py
@@ -30,7 +30,7 @@ from core.css import css_properties from collections import defaultdict import json5_generator -from name_utilities import id_for_css_property +from name_utilities import enum_key_for_css_property, id_for_css_property import template_expander @@ -53,10 +53,12 @@ self._longhand_dictionary = defaultdict(list) for property_ in json5_properties.shorthands: + property_['longhand_enum_keys'] = map( + enum_key_for_css_property, property_['longhands']) property_['longhand_property_ids'] = map( id_for_css_property, property_['longhands']) - for longhand in property_['longhand_property_ids']: - self._longhand_dictionary[longhand].append(property_) + for longhand_enum_key in property_['longhand_enum_keys']: + self._longhand_dictionary[longhand_enum_key].append(property_) for longhands in self._longhand_dictionary.values(): # Sort first by number of longhands in decreasing order, then
diff --git a/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl index 225ca7969..fdceebe 100644 --- a/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl
@@ -85,7 +85,7 @@ switch (id) { {% for descriptor in descriptors %} case AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}}: - return CSSProperty{{descriptor.name.to_upper_camel_case()}}; + return CSSPropertyID::{{descriptor.name.to_enum_value()}}; {% endfor %} default: NOTREACHED(); @@ -96,7 +96,7 @@ AtRuleDescriptorID CSSPropertyIDAsAtRuleDescriptor(CSSPropertyID id) { switch (id) { {% for descriptor in descriptors %} - case CSSProperty{{descriptor.name.to_upper_camel_case()}}: + case CSSPropertyID::{{descriptor.name.to_enum_value()}}: return AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}}; {% endfor %} default:
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py index dc570b7..3a50b89 100755 --- a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py +++ b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py
@@ -11,7 +11,7 @@ class PropertyClassData( - namedtuple('PropertyClassData', 'enum_value,property_id,classname,namespace_group,filename')): + namedtuple('PropertyClassData', 'enum_key,enum_value,property_id,classname,namespace_group,filename')): pass @@ -73,6 +73,7 @@ """ namespace_group = 'Shorthand' if property_['longhands'] else 'Longhand' return PropertyClassData( + enum_key=property_['enum_key'], enum_value=property_['enum_value'], property_id=property_['property_id'], classname=property_['name'].to_upper_camel_case(),
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl index 19f5351..9701c2c7 100644 --- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl
@@ -21,10 +21,10 @@ namespace blink { namespace { -{% for _, property_id, classname, namespace_group, _ in property_classes_by_property_id %} +{% for _, _, property_id, classname, namespace_group, _ in property_classes_by_property_id %} static constexpr css_{{namespace_group.lower()}}::{{classname}} property_{{property_id.lower()}}; {% endfor %} -{% for _, property_id, classname, namespace_group, _ in alias_classes_by_property_id %} +{% for _, _, property_id, classname, namespace_group, _ in alias_classes_by_property_id %} static constexpr css_{{namespace_group.lower()}}::{{classname}} property_{{property_id.lower()}}; {% endfor %} @@ -41,7 +41,7 @@ DCHECK_LE(id, lastUnresolvedCSSProperty); // last unresolved property id switch (id) { {% for property_class_data in alias_classes_by_property_id %} - case {{property_class_data.property_id}}: + case CSSPropertyID::{{property_class_data.enum_key}}: return &property_{{property_class_data.property_id.lower()}}; {% endfor %} default:
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl index 94e9ee3..1e4079f1 100644 --- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl
@@ -47,7 +47,7 @@ return "{{property_classname[0].lower() + property_classname[1:]}}"; } {% if property.alias_for == None %} - CSSPropertyID PropertyID() const override { return {{property.property_id}}; } + CSSPropertyID PropertyID() const override { return CSSPropertyID::{{property.enum_key}}; } {%if property.layout_dependent %} bool IsLayoutDependentProperty() const override { return true; } bool IsLayoutDependent(const ComputedStyle*, LayoutObject*) const override;
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl index 56fe6df..0fdcccf 100644 --- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl
@@ -28,7 +28,7 @@ switch (id) { {% for property in properties if property.keywordIDs and 'Keyword' in property.typedom_types %} - case {{property.property_id}}: { + case CSSPropertyID::{{property.enum_key}}: { switch (valueID) { {% for keywordValueID in property.keywordIDs %} case {{keywordValueID}}:
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl index 3b83fd39..1e9ebf9 100644 --- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
@@ -83,7 +83,7 @@ switch (id) { case CSSPropertyVariable: {% for property in properties if property.typedom_types %} - case {{property.property_id}}: + case CSSPropertyID::{{property.enum_key}}: {% endfor %} return true; default: @@ -124,7 +124,7 @@ return value.GetType() == CSSStyleValue::kUnparsedType; {% for property in properties if property.typedom_types %} {% if property.typedom_types != ['Keyword'] %} - case {{property.property_id}}: + case CSSPropertyID::{{property.enum_key}}: return ( {% for type in property.typedom_types if type != 'Keyword' %} {{ "|| " if not loop.first }}CSSOMTypes::IsCSSStyleValue{{type}}(value)
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl index 6456a79..bb9c2205b 100644 --- a/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl
@@ -40,7 +40,7 @@ }; static StylePropertyShorthand {{property.name.to_lower_camel_case()}}Longhands( - {{property.property_id}}, + CSSPropertyID::{{property.enum_key}}, {{property.name.to_lower_camel_case()}}Properties, base::size({{property.name.to_lower_camel_case()}}Properties)); return {{property.name.to_lower_camel_case()}}Longhands; @@ -68,7 +68,7 @@ return offsetShorthandWithoutPositionAnchor(); switch (propertyID) { {% for property in properties %} - case {{property.property_id}}: + case CSSPropertyID::{{property.enum_key}}: return {{property.name.to_lower_camel_case()}}Shorthand(); {% endfor %} default: { @@ -81,10 +81,10 @@ CSSPropertyID propertyID, Vector<StylePropertyShorthand, 4>* result) { DCHECK(!result->size()); switch (propertyID) { - {% for longhand_id, shorthands in longhands_dictionary.items() %} - case {{longhand_id}}: { + {% for longhand_enum_key, shorthands in longhands_dictionary.items() %} + case CSSPropertyID::{{longhand_enum_key}}: { {% for shorthand in shorthands %} - if (CSSProperty::Get({{shorthand.property_id}}).IsEnabled()) + if (CSSProperty::Get(CSSPropertyID::{{shorthand.enum_key}}).IsEnabled()) result->UncheckedAppend({{shorthand.name.to_lower_camel_case()}}Shorthand()); {% endfor %} break;
diff --git a/third_party/blink/renderer/controller/dev_tools_frontend_impl.h b/third_party/blink/renderer/controller/dev_tools_frontend_impl.h index b5777f2..ec54e126 100644 --- a/third_party/blink/renderer/controller/dev_tools_frontend_impl.h +++ b/third_party/blink/renderer/controller/dev_tools_frontend_impl.h
@@ -33,7 +33,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/blink/public/web/devtools_frontend.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_frontend.mojom-blink.h" #include "third_party/blink/renderer/core/inspector/inspector_frontend_client.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index f54cad1..e1ab9cd 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1706,8 +1706,6 @@ jumbo_source_set("unit_tests") { testonly = true sources = [ - "clipboard/data_object_test.cc", - "clipboard/data_transfer_test.cc", "content_capture/content_capture_test.cc", "css/active_style_sheets_test.cc", "css/affected_by_pseudo_test.cc", @@ -1974,6 +1972,7 @@ "html/track/vtt/vtt_scanner_test.cc", "imagebitmap/image_bitmap_test.cc", "input/event_handler_test.cc", + "input/fallback_cursor_event_manager_test.cc", "input/ime_on_focus_test.cc", "input/overscroll_behavior_test.cc", "input/pointer_event_manager_test.cc", @@ -2244,6 +2243,7 @@ "//testing/gtest", "//third_party/blink/renderer/core/accessibility:unit_tests", "//third_party/blink/renderer/core/animation:unit_tests", + "//third_party/blink/renderer/core/clipboard:unit_tests", "//third_party/blink/renderer/core/editing:unit_tests", "//third_party/blink/renderer/core/fileapi:unit_tests", ]
diff --git a/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc b/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc index 06e8ccf..8166679d 100644 --- a/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc +++ b/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
@@ -58,6 +58,9 @@ bool ShouldApplyDarkModeFilterToPage(DarkModePagePolicy policy, const LayoutObject& root_layout_object) { + if (root_layout_object.StyleRef().DarkColorScheme()) + return false; + switch (policy) { case DarkModePagePolicy::kFilterAll: return true;
diff --git a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc index 7b0dc674..962980b 100644 --- a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc +++ b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc
@@ -74,5 +74,23 @@ GetLayoutView())); } +TEST_F(ApplyDarkModeCheckTest, SupportedColorSchemesDark) { + RuntimeEnabledFeatures::SetMetaSupportedColorSchemesEnabled(true); + GetDocument().GetSettings()->SetForceDarkModeEnabled(true); + GetDocument().GetSettings()->SetPreferredColorScheme( + PreferredColorScheme::kDark); + ColorSchemeSet schemes; + schemes.Set(ColorScheme::kDark); + GetDocument().GetStyleEngine().SetSupportedColorSchemes(schemes); + UpdateAllLifecyclePhasesForTest(); + + // Opting out of forced darkening when dark is among the supported color + // schemes for the page. + EXPECT_FALSE(ShouldApplyDarkModeFilterToPage( + DarkModePagePolicy::kFilterByBackground, GetLayoutView())); + EXPECT_FALSE(ShouldApplyDarkModeFilterToPage(DarkModePagePolicy::kFilterAll, + GetLayoutView())); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/accessibility/ax_object_cache.h b/third_party/blink/renderer/core/accessibility/ax_object_cache.h index 02f4f86..721bb00 100644 --- a/third_party/blink/renderer/core/accessibility/ax_object_cache.h +++ b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -58,6 +58,10 @@ virtual void Dispose() = 0; + // Register/remove popups + virtual void InitializePopup(Document* document) = 0; + virtual void DisposePopup(Document* document) = 0; + virtual void SelectionChanged(Node*) = 0; virtual void ChildrenChanged(Node*) = 0; virtual void ChildrenChanged(LayoutObject*) = 0; @@ -86,7 +90,8 @@ virtual void UpdateCacheAfterNodeIsAttached(Node*) = 0; virtual void DidInsertChildrenOfNode(Node*) = 0; - virtual void HandleAttributeChanged(const QualifiedName& attr_name, + // Returns true if the AXObjectCache cares about this attribute + virtual bool HandleAttributeChanged(const QualifiedName& attr_name, Element*) = 0; virtual void HandleFocusedUIElementChanged(Node* old_focused_node, Node* new_focused_node) = 0;
diff --git a/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc b/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc index 13257433..7c03edf6 100644 --- a/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc +++ b/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
@@ -171,7 +171,7 @@ case FilterOperation::SATURATE: case FilterOperation::SEPIA: result.interpolable_value = std::make_unique<InterpolableNumber>( - ToBasicColorMatrixFilterOperation(filter).Amount()); + To<BasicColorMatrixFilterOperation>(filter).Amount()); break; case FilterOperation::BRIGHTNESS: @@ -179,7 +179,7 @@ case FilterOperation::INVERT: case FilterOperation::OPACITY: result.interpolable_value = std::make_unique<InterpolableNumber>( - ToBasicComponentTransferFilterOperation(filter).Amount()); + To<BasicComponentTransferFilterOperation>(filter).Amount()); break; case FilterOperation::BLUR:
diff --git a/third_party/blink/renderer/core/aom/accessible_node.cc b/third_party/blink/renderer/core/aom/accessible_node.cc index d940a04..b3c5b361 100644 --- a/third_party/blink/renderer/core/aom/accessible_node.cc +++ b/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -8,7 +8,9 @@ #include "third_party/blink/renderer/core/aom/accessible_node_list.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/qualified_name.h" +#include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform//weborigin/security_origin.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -1170,12 +1172,30 @@ const blink::QualifiedName& attribute) { // TODO(dmazzoni): Make a cleaner API for this rather than pretending // the DOM attribute changed. - if (AXObjectCache* cache = GetAXObjectCache()) { - if (element_) - cache->HandleAttributeChanged(attribute, element_); - else - cache->HandleAttributeChanged(attribute, this); + AXObjectCache* cache = GetAXObjectCache(); + if (!cache) + return; + + if (!element_) { + cache->HandleAttributeChanged(attribute, this); + return; } + + // By definition, any attribute on an AccessibleNode is interesting to + // AXObjectCache, so no need to check return value. + cache->HandleAttributeChanged(attribute, element_); + + auto* page = GetDocument()->GetPage(); + auto* view = GetDocument()->View(); + if (!page || !view) + return; + + // TODO(aboxhall): add a lifecycle phase for accessibility updates. + if (!view->CanThrottleRendering()) + page->Animator().ScheduleVisualUpdate(GetDocument()->GetFrame()); + + GetDocument()->Lifecycle().EnsureStateAtMost( + DocumentLifecycle::kVisualUpdatePending); } AXObjectCache* AccessibleNode::GetAXObjectCache() {
diff --git a/third_party/blink/renderer/core/clipboard/BUILD.gn b/third_party/blink/renderer/core/clipboard/BUILD.gn index e5e8a6a..7c0e8dd 100644 --- a/third_party/blink/renderer/core/clipboard/BUILD.gn +++ b/third_party/blink/renderer/core/clipboard/BUILD.gn
@@ -36,3 +36,10 @@ "//ui/gfx/codec", ] } + +blink_core_tests("unit_tests") { + sources = [ + "data_object_test.cc", + "data_transfer_test.cc", + ] +}
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.cc b/third_party/blink/renderer/core/css/css_gradient_value.cc index d7851466..bff2a43f 100644 --- a/third_party/blink/renderer/core/css/css_gradient_value.cc +++ b/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -292,7 +292,7 @@ const ComputedStyle& style) { return document.GetTextLinkColors().ColorFromCSSValue( stop_color, style.VisitedDependentColor(GetCSSPropertyColor()), - document.GetColorScheme()); + style.GetColorScheme()); } void CSSGradientValue::AddDeprecatedStops(GradientDesc& desc,
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc index ac511a03..18dc90d 100644 --- a/third_party/blink/renderer/core/css/media_values.cc +++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -180,9 +180,8 @@ LocalFrame* frame) { DCHECK(frame); DCHECK(frame->GetSettings()); - if (frame->GetSettings()->ForceDarkModeEnabled()) - return PreferredColorScheme::kNoPreference; - return frame->GetSettings()->GetPreferredColorScheme(); + DCHECK(frame->GetDocument()); + return frame->GetDocument()->GetStyleEngine().GetPreferredColorScheme(); } bool MediaValues::CalculatePrefersReducedMotion(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index ee0a5dac8..bc4cff1 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -1965,49 +1965,53 @@ case FilterOperation::GRAYSCALE: filter_value = CSSFunctionValue::Create(CSSValueGrayscale); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount(), + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::SEPIA: filter_value = CSSFunctionValue::Create(CSSValueSepia); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount(), + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::SATURATE: filter_value = CSSFunctionValue::Create(CSSValueSaturate); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount(), + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::HUE_ROTATE: filter_value = CSSFunctionValue::Create(CSSValueHueRotate); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount(), + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount(), CSSPrimitiveValue::UnitType::kDegrees)); break; case FilterOperation::INVERT: filter_value = CSSFunctionValue::Create(CSSValueInvert); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicComponentTransferFilterOperation(filter_operation)->Amount(), + To<BasicComponentTransferFilterOperation>(filter_operation) + ->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::OPACITY: filter_value = CSSFunctionValue::Create(CSSValueOpacity); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicComponentTransferFilterOperation(filter_operation)->Amount(), + To<BasicComponentTransferFilterOperation>(filter_operation) + ->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::BRIGHTNESS: filter_value = CSSFunctionValue::Create(CSSValueBrightness); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicComponentTransferFilterOperation(filter_operation)->Amount(), + To<BasicComponentTransferFilterOperation>(filter_operation) + ->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::CONTRAST: filter_value = CSSFunctionValue::Create(CSSValueContrast); filter_value->Append(*CSSPrimitiveValue::Create( - ToBasicComponentTransferFilterOperation(filter_operation)->Amount(), + To<BasicComponentTransferFilterOperation>(filter_operation) + ->Amount(), CSSPrimitiveValue::UnitType::kNumber)); break; case FilterOperation::BLUR:
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc index e2a880b..5b3cb0b 100644 --- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc +++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -216,7 +216,7 @@ } } StyleImage* new_image = - LoadPendingImage(style, ToStylePendingImage(background_image), + LoadPendingImage(style, To<StylePendingImage>(background_image), image_request_optimization); if (new_image && new_image->IsLazyloadPossiblyDeferred()) LazyLoadImageObserver::StartMonitoring(element_); @@ -234,7 +234,7 @@ if (image->IsPendingImage()) { ToImageContentData(content_data) ->SetImage( - LoadPendingImage(style, ToStylePendingImage(image), + LoadPendingImage(style, To<StylePendingImage>(image), FetchParameters::kAllowPlaceholder)); } } @@ -248,8 +248,9 @@ if (StyleImage* image = current_cursor.GetImage()) { if (image->IsPendingImage()) { // cursor images shouldn't be replaced with placeholders - current_cursor.SetImage(LoadPendingImage( - style, ToStylePendingImage(image), FetchParameters::kNone)); + current_cursor.SetImage( + LoadPendingImage(style, To<StylePendingImage>(image), + FetchParameters::kNone)); } } } @@ -261,7 +262,7 @@ style->ListStyleImage()->IsPendingImage()) { // List style images shouldn't be replaced with placeholders style->SetListStyleImage(LoadPendingImage( - style, ToStylePendingImage(style->ListStyleImage()), + style, To<StylePendingImage>(style->ListStyleImage()), FetchParameters::kNone)); } break; @@ -271,7 +272,7 @@ style->BorderImageSource()->IsPendingImage()) { // Border images shouldn't be replaced with placeholders style->SetBorderImageSource(LoadPendingImage( - style, ToStylePendingImage(style->BorderImageSource()), + style, To<StylePendingImage>(style->BorderImageSource()), FetchParameters::kNone)); } break; @@ -282,7 +283,7 @@ if (mask_image.GetImage() && mask_image.GetImage()->IsPendingImage()) { StyleImage* loaded_image = LoadPendingImage( - style, ToStylePendingImage(mask_image.GetImage()), + style, To<StylePendingImage>(mask_image.GetImage()), FetchParameters::kAllowPlaceholder); reflection->SetMask(NinePieceImage( loaded_image, mask_image.ImageSlices(), mask_image.Fill(), @@ -296,7 +297,7 @@ if (style->MaskBoxImageSource() && style->MaskBoxImageSource()->IsPendingImage()) { style->SetMaskBoxImageSource(LoadPendingImage( - style, ToStylePendingImage(style->MaskBoxImageSource()), + style, To<StylePendingImage>(style->MaskBoxImageSource()), FetchParameters::kAllowPlaceholder)); } break; @@ -307,7 +308,7 @@ if (mask_layer->GetImage() && mask_layer->GetImage()->IsPendingImage()) { mask_layer->SetImage(LoadPendingImage( - style, ToStylePendingImage(mask_layer->GetImage()), + style, To<StylePendingImage>(mask_layer->GetImage()), FetchParameters::kAllowPlaceholder)); } } @@ -317,7 +318,7 @@ if (style->ShapeOutside() && style->ShapeOutside()->GetImage() && style->ShapeOutside()->GetImage()->IsPendingImage()) { style->ShapeOutside()->SetImage(LoadPendingImage( - style, ToStylePendingImage(style->ShapeOutside()->GetImage()), + style, To<StylePendingImage>(style->ShapeOutside()->GetImage()), FetchParameters::kAllowPlaceholder, kCrossOriginAttributeAnonymous)); }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index 6d9f923a..8c9f003f 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -50,6 +50,7 @@ #include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/css/resolver/transform_builder.h" +#include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -112,7 +113,7 @@ const CSSValue& value, bool for_visited_link) { return state.GetDocument().GetTextLinkColors().ColorFromCSSValue( - value, state.Style()->GetColor(), state.GetDocument().GetColorScheme(), + value, state.Style()->GetColor(), state.Style()->GetColorScheme(), for_visited_link); } @@ -1346,7 +1347,7 @@ identifier_value->GetValueID() == CSSValueCurrentcolor) return StyleColor::CurrentColor(); return state.GetDocument().GetTextLinkColors().ColorFromCSSValue( - value, Color(), state.GetDocument().GetColorScheme(), for_visited_link); + value, Color(), state.Style()->GetColorScheme(), for_visited_link); } StyleAutoColor StyleBuilderConverter::ConvertStyleAutoColor( @@ -1360,7 +1361,7 @@ return StyleAutoColor::AutoColor(); } return state.GetDocument().GetTextLinkColors().ColorFromCSSValue( - value, Color(), state.GetDocument().GetColorScheme(), for_visited_link); + value, Color(), state.Style()->GetColorScheme(), for_visited_link); } SVGPaint StyleBuilderConverter::ConvertSVGPaint(StyleResolverState& state, @@ -1636,6 +1637,7 @@ static const CSSValue& ComputeRegisteredPropertyValue( const Document& document, + const StyleResolverState* state, const CSSToLengthConversionData& css_to_length_conversion_data, const CSSValue& value) { // TODO(timloh): Images values can also contain lengths. @@ -1644,7 +1646,7 @@ CSSFunctionValue::Create(function_value->FunctionType()); for (const CSSValue* inner_value : To<CSSValueList>(value)) { new_function->Append(ComputeRegisteredPropertyValue( - document, css_to_length_conversion_data, *inner_value)); + document, state, css_to_length_conversion_data, *inner_value)); } return *new_function; } @@ -1653,7 +1655,7 @@ CSSValueList* new_list = CSSValueList::CreateWithSeparatorFrom(*old_list); for (const CSSValue* inner_value : *old_list) { new_list->Append(ComputeRegisteredPropertyValue( - document, css_to_length_conversion_data, *inner_value)); + document, state, css_to_length_conversion_data, *inner_value)); } return *new_list; } @@ -1709,8 +1711,10 @@ if (value_id == CSSValueCurrentcolor) return value; if (StyleColor::IsColorKeyword(value_id)) { + ColorScheme scheme = + state ? state->Style()->GetColorScheme() : ColorScheme::kLight; Color color = document.GetTextLinkColors().ColorFromCSSValue( - value, Color(), document.GetColorScheme(), false); + value, Color(), scheme, false); return *CSSColorValue::Create(color.Rgb()); } } @@ -1721,15 +1725,15 @@ const CSSValue& StyleBuilderConverter::ConvertRegisteredPropertyInitialValue( const Document& document, const CSSValue& value) { - return ComputeRegisteredPropertyValue(document, CSSToLengthConversionData(), - value); + return ComputeRegisteredPropertyValue(document, nullptr /* state */, + CSSToLengthConversionData(), value); } const CSSValue& StyleBuilderConverter::ConvertRegisteredPropertyValue( const StyleResolverState& state, const CSSValue& value) { return ComputeRegisteredPropertyValue( - state.GetDocument(), state.CssToLengthConversionData(), value); + state.GetDocument(), &state, state.CssToLengthConversionData(), value); } // Registered properties need to substitute as absolute values. This means
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 356a75e..00371fe 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1029,6 +1029,9 @@ : 1); initial_style->SetEffectiveZoom(initial_style->Zoom()); + if (document.GetStyleEngine().GetColorScheme() == ColorScheme::kDark) + initial_style->SetDarkColorScheme(); + FontDescription document_font_description = initial_style->GetFontDescription(); document_font_description.SetLocale(
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 260c645..c809c88 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -245,6 +245,7 @@ } void StyleEngine::SetNeedsActiveStyleUpdate(TreeScope& tree_scope) { + DCHECK(tree_scope.RootNode().isConnected()); if (GetDocument().IsActive() || !IsMaster()) MarkTreeScopeDirty(tree_scope); } @@ -318,6 +319,9 @@ new_sheets[i]->AddedAdoptedToTreeScope(tree_scope); } + if (!tree_scope.RootNode().isConnected()) + return; + if (new_sheets_count) { EnsureStyleSheetCollectionFor(tree_scope); if (tree_scope != document_) @@ -1780,6 +1784,43 @@ layout_tree_rebuild_root_.Update(ancestor, dirty_node); } +void StyleEngine::UpdateColorScheme() { + auto* settings = GetDocument().GetSettings(); + DCHECK(settings); + PreferredColorScheme old_preferred_scheme = preferred_color_scheme_; + ColorScheme old_color_scheme = color_scheme_; + + preferred_color_scheme_ = settings->GetPreferredColorScheme(); + color_scheme_ = ColorScheme::kLight; + + if (preferred_color_scheme_ == PreferredColorScheme::kDark) { + if (supported_color_schemes_.Contains(ColorScheme::kDark)) { + color_scheme_ = ColorScheme::kDark; + } else if (settings->ForceDarkModeEnabled()) { + // Make sure we don't match (prefers-color-scheme: dark) when forced + // darkening is enabled. + preferred_color_scheme_ = PreferredColorScheme::kNoPreference; + } + } + + if (color_scheme_ != old_color_scheme) { + PlatformColorsChanged(); + if (LocalFrameView* view = GetDocument().View()) { + if (color_scheme_ == ColorScheme::kDark) { + view->SetBaseBackgroundColor(color_scheme_ == ColorScheme::kDark + ? Color::kBlack + : Color::kWhite); + } + } + } + if (preferred_color_scheme_ != old_preferred_scheme) + MediaQueryAffectingValueChanged(); +} + +void StyleEngine::ColorSchemeChanged() { + UpdateColorScheme(); +} + void StyleEngine::Trace(blink::Visitor* visitor) { visitor->Trace(document_); visitor->Trace(injected_user_style_sheets_);
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 73e4431..29040a1 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -33,6 +33,7 @@ #include <memory> #include <utility> #include "base/auto_reset.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/active_style_sheets.h" @@ -133,6 +134,7 @@ void MediaQueriesChangedInScope(TreeScope&); void WatchedSelectorsChanged(); void InitialStyleChanged(); + void ColorSchemeChanged(); void InitialViewportChanged(); void ViewportRulesChanged(); void HtmlImportAddedOrRemoved(); @@ -348,10 +350,15 @@ void SetSupportedColorSchemes(const ColorSchemeSet& supported_color_schemes) { supported_color_schemes_ = supported_color_schemes; + UpdateColorScheme(); } const ColorSchemeSet& GetSupportedColorSchemes() const { return supported_color_schemes_; } + PreferredColorScheme GetPreferredColorScheme() const { + return preferred_color_scheme_; + } + ColorScheme GetColorScheme() const { return color_scheme_; } void Trace(blink::Visitor*) override; const char* NameInHeapSnapshot() const override { return "StyleEngine"; } @@ -445,6 +452,8 @@ void AddUserKeyframeRules(const RuleSet&); void AddUserKeyframeStyle(StyleRuleKeyframes*); + void UpdateColorScheme(); + Member<Document> document_; bool is_master_; @@ -534,6 +543,15 @@ // supported schemes are used to opt-out of forced darkening. ColorSchemeSet supported_color_schemes_; + // The preferred color scheme is set in settings, but may be overridden by the + // ForceDarkMode setting where the preferred_color_scheme_ will be set no + // kNoPreference to avoid dark styling to be applied before auto darkening. + PreferredColorScheme preferred_color_scheme_; + + // The resolved color scheme to use based on the supported color schemes, the + // preferred color scheme, and the ForceDarkMode setting. + ColorScheme color_scheme_ = ColorScheme::kLight; + friend class StyleEngineTest; };
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index c879ab7..01d83f5 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -631,12 +631,12 @@ } } -void DisplayLockContext::WillStartLifecycleUpdate() { +void DisplayLockContext::WillStartLifecycleUpdate(const LocalFrameView& view) { if (state_ == kUpdating) update_budget_->WillStartLifecycleUpdate(); } -void DisplayLockContext::DidFinishLifecycleUpdate() { +void DisplayLockContext::DidFinishLifecycleUpdate(const LocalFrameView& view) { if (state_ == kPendingAcquire) { if (!ElementSupportsDisplayLocking()) { FinishAcquireResolver(kReject, rejection_names::kContainmentNotSatisfied);
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index aee69443..a5fcc96 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -163,8 +163,8 @@ void AddToWhitespaceReattachSet(Element& element); // LifecycleNotificationObserver overrides. - void WillStartLifecycleUpdate() override; - void DidFinishLifecycleUpdate() override; + void WillStartLifecycleUpdate(const LocalFrameView&) override; + void DidFinishLifecycleUpdate(const LocalFrameView&) override; private: friend class DisplayLockContextTest;
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index a7372bf..4da7c1b 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -2474,9 +2474,6 @@ if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean) Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean); - if (AXObjectCache* cache = ExistingAXObjectCache()) - cache->ProcessUpdatesAfterLayout(*this); - if (LocalFrameView* frame_view_anchored = View()) frame_view_anchored->PerformScrollAnchoringAdjustments(); @@ -7723,9 +7720,9 @@ FeaturePolicyViolationReportBody* body = MakeGarbageCollected<FeaturePolicyViolationReportBody>( feature_name, "Feature policy violation", - (disposition == mojom::FeaturePolicyDisposition::kReport ? "report" - : "enforce"), - SourceLocation::Capture()); + (disposition == mojom::FeaturePolicyDisposition::kReport + ? "report" + : "enforce")); Report* report = MakeGarbageCollected<Report>("feature-policy-violation", Url().GetString(), body); ReportingContext::From(this)->QueueReport(report); @@ -7872,19 +7869,6 @@ return false; } -void Document::SetColorScheme(ColorScheme color_scheme) { - if (color_scheme_ == color_scheme) - return; - color_scheme_ = color_scheme; - PlatformColorsChanged(); - if (LocalFrameView* view = View()) { - if (color_scheme == ColorScheme::kDark) - view->SetBaseBackgroundColor(Color::kBlack); - else - view->SetBaseBackgroundColor(Color::kWhite); - } -} - ComputedAccessibleNode* Document::GetOrCreateComputedAccessibleNode( AXID ax_id, WebComputedAXTree* tree) {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 101b288..7604940 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -66,7 +66,6 @@ #include "third_party/blink/renderer/core/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" -#include "third_party/blink/renderer/platform/graphics/color_scheme.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h" #include "third_party/blink/renderer/platform/timer.h" @@ -1513,9 +1512,6 @@ // associated Web App Manifest, it will return false. bool IsInWebAppScope() const; - ColorScheme GetColorScheme() const { return color_scheme_; } - void SetColorScheme(ColorScheme); - ComputedAccessibleNode* GetOrCreateComputedAccessibleNode( AXID ax_id, WebComputedAXTree* tree); @@ -1755,7 +1751,6 @@ TextLinkColors text_link_colors_; const Member<VisitedLinkState> visited_link_state_; - ColorScheme color_scheme_ = ColorScheme::kLight; bool visually_ordered_;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 40e3e44..a416238 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1690,8 +1690,22 @@ if (isConnected()) { if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) { - if (params.old_value != params.new_value) - cache->HandleAttributeChanged(name, this); + if (params.old_value != params.new_value) { + auto* page = GetDocument().GetPage(); + auto* view = GetDocument().View(); + // If this attribute is interesting for accessibility (e.g. `role` or + // `alt`), but doesn't trigger a lifecycle update on its own + // (e.g. because it doesn't make layout dirty), make sure we run + // lifecycle phases to update the computed accessibility tree. + if (cache->HandleAttributeChanged(name, this) && page && view) { + if (!view->CanThrottleRendering()) + page->Animator().ScheduleVisualUpdate(GetDocument().GetFrame()); + + // TODO(aboxhall): add a lifecycle phase for accessibility updates. + GetDocument().Lifecycle().EnsureStateAtMost( + DocumentLifecycle::kVisualUpdatePending); + } + } } } @@ -2063,7 +2077,7 @@ DCHECK(GetDocument().InStyleRecalc()); ComputedStyle* style = MutableComputedStyle(); - if ((!style || style->Display() == EDisplay::kNone) && + if ((!style || style->IsEnsuredInDisplayNone()) && !ChildNeedsReattachLayoutTree()) { Node::AttachLayoutTree(context); return;
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc index 865bb5e..b73a7b9 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc +++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -62,6 +62,8 @@ return nullptr; } + void SetV8Isolate(v8::Isolate* isolate) override {} + private: DISALLOW_COPY_AND_ASSIGN(MockIdleDeadlineScheduler); };
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc index 7ea93e71..0b02bd2 100644 --- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc +++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -69,6 +69,8 @@ return nullptr; } + void SetV8Isolate(v8::Isolate* isolate) override {} + void RunIdleTask() { std::move(idle_task_).Run(TimeTicks()); } bool HasIdleTask() const { return !!idle_task_; }
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc index a5bf081..77253a8 100644 --- a/third_party/blink/renderer/core/events/mouse_event.cc +++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -34,6 +34,8 @@ #include "third_party/blink/renderer/core/input/input_device_capabilities.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/page/pointer_lock_controller.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/svg/svg_element.h" @@ -220,17 +222,26 @@ const LocalDOMWindow* dom_window, MouseEventInit* initializer) { FloatPoint client_point; + FloatPoint screen_point = web_pointer_properties.PositionInScreen(); float scale_factor = 1.0f; if (dom_window && dom_window->GetFrame() && dom_window->GetFrame()->View()) { LocalFrame* frame = dom_window->GetFrame(); - FloatPoint page_point = frame->View()->ConvertFromRootFrame( - web_pointer_properties.PositionInWidget()); + FloatPoint root_frame_point = web_pointer_properties.PositionInWidget(); + if (Page* p = frame->GetPage()) { + if (p->GetPointerLockController().GetElement() && + !p->GetPointerLockController().LockPending()) { + p->GetPointerLockController().GetPointerLockPosition(&root_frame_point, + &screen_point); + } + } + FloatPoint frame_point = + frame->View()->ConvertFromRootFrame(root_frame_point); scale_factor = 1.0f / frame->PageZoomFactor(); - client_point = page_point.ScaledBy(scale_factor); + client_point = frame_point.ScaledBy(scale_factor); } - initializer->setScreenX(web_pointer_properties.PositionInScreen().x); - initializer->setScreenY(web_pointer_properties.PositionInScreen().y); + initializer->setScreenX(screen_point.X()); + initializer->setScreenY(screen_point.Y()); initializer->setClientX(client_point.X()); initializer->setClientY(client_point.Y());
diff --git a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc index 5308387..a377e0b9 100644 --- a/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc +++ b/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
@@ -231,7 +231,7 @@ // If there are blocked headers, copy the response so we can remove them. WebURLResponse validated_response = WrappedResourceResponse(response); for (const auto& header : blocked_headers) - validated_response.ClearHTTPHeaderField(WebString::FromASCII(header)); + validated_response.ClearHttpHeaderField(WebString::FromASCII(header)); client_->DidReceiveResponse(validated_response); }
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index 750b55f..b716b5bb 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -298,14 +298,15 @@ frame->Init(); frame->View()->SetParentVisible(true); frame->View()->SetSelfVisible(true); - if (AXObjectCache* cache = - popup_client_->OwnerElement().GetDocument().ExistingAXObjectCache()) - cache->ChildrenChanged(&popup_client_->OwnerElement()); DCHECK(frame->DomWindow()); PagePopupSupplement::Install(*frame, *this, popup_client_); DCHECK_EQ(popup_client_->OwnerElement().GetDocument().ExistingAXObjectCache(), frame->GetDocument()->ExistingAXObjectCache()); + if (AXObjectCache* cache = frame->GetDocument()->ExistingAXObjectCache()) { + cache->InitializePopup(frame->GetDocument()); + cache->ChildrenChanged(&popup_client_->OwnerElement()); + } page_->LayerTreeViewInitialized(*layer_tree_view_, *animation_host_, nullptr); @@ -558,6 +559,9 @@ closing_ = true; + if (AXObjectCache* cache = MainFrame().GetDocument()->ExistingAXObjectCache()) + cache->DisposePopup(MainFrame().GetDocument()); + { // This function can be called in EventDispatchForbiddenScope for the main // document, and the following operations dispatch some events. It's safe
diff --git a/third_party/blink/renderer/core/frame/BUILD.gn b/third_party/blink/renderer/core/frame/BUILD.gn index 92712039..da228b7 100644 --- a/third_party/blink/renderer/core/frame/BUILD.gn +++ b/third_party/blink/renderer/core/frame/BUILD.gn
@@ -94,6 +94,7 @@ "local_frame_view.h", "location.cc", "location.h", + "location_report_body.h", "message_report_body.h", "navigation_rate_limiter.cc", "navigation_rate_limiter.h",
diff --git a/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h b/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h index d3c753a..f693ab2 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h +++ b/third_party/blink/renderer/core/frame/csp/csp_violation_report_body.h
@@ -7,11 +7,11 @@ #include "third_party/blink/renderer/bindings/core/v8/source_location.h" #include "third_party/blink/renderer/core/events/security_policy_violation_event_init.h" -#include "third_party/blink/renderer/core/frame/report_body.h" +#include "third_party/blink/renderer/core/frame/location_report_body.h" namespace blink { -class CORE_EXPORT CSPViolationReportBody : public ReportBody { +class CORE_EXPORT CSPViolationReportBody : public LocationReportBody { DEFINE_WRAPPERTYPEINFO(); public: @@ -21,17 +21,17 @@ } CSPViolationReportBody(const SecurityPolicyViolationEventInit& violation_data) - : document_url_(violation_data.documentURI()), + : LocationReportBody(violation_data.sourceFile(), + violation_data.lineNumber(), + violation_data.columnNumber()), + document_url_(violation_data.documentURI()), referrer_(violation_data.referrer()), blocked_url_(violation_data.blockedURI()), effective_directive_(violation_data.effectiveDirective()), original_policy_(violation_data.originalPolicy()), - source_file_(violation_data.sourceFile()), sample_(violation_data.sample()), disposition_(violation_data.disposition()), - status_code_(violation_data.statusCode()), - line_number_(source_file_ ? violation_data.lineNumber() : 0), - column_number_(source_file_ ? violation_data.columnNumber() : 0) {} + status_code_(violation_data.statusCode()) {} ~CSPViolationReportBody() override = default; @@ -40,33 +40,19 @@ String blockedURL() const { return blocked_url_; } String effectiveDirective() const { return effective_directive_; } String originalPolicy() const { return original_policy_; } - String sourceFile() const { return source_file_; } String sample() const { return sample_; } String disposition() const { return disposition_; } uint16_t statusCode() const { return status_code_; } - uint32_t lineNumber(bool& is_null) const { - is_null = !source_file_; - return line_number_; - } - - uint32_t columnNumber(bool& is_null) const { - is_null = !source_file_; - return column_number_; - } - private: const String document_url_; const String referrer_; const String blocked_url_; const String effective_directive_; const String original_policy_; - const String source_file_; const String sample_; const String disposition_; const uint16_t status_code_; - const uint32_t line_number_; - const uint32_t column_number_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index 4fbeb716..4cbba2930 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -759,7 +759,7 @@ // Construct the deprecation report. double removal_date = MilestoneDate(info.anticipated_removal); DeprecationReportBody* body = MakeGarbageCollected<DeprecationReportBody>( - info.id, removal_date, info.message, SourceLocation::Capture()); + info.id, removal_date, info.message); Report* report = MakeGarbageCollected<Report>( "deprecation", document->Url().GetString(), body);
diff --git a/third_party/blink/renderer/core/frame/deprecation_report_body.h b/third_party/blink/renderer/core/frame/deprecation_report_body.h index 5b24d16..176a8e5 100644 --- a/third_party/blink/renderer/core/frame/deprecation_report_body.h +++ b/third_party/blink/renderer/core/frame/deprecation_report_body.h
@@ -16,9 +16,8 @@ public: DeprecationReportBody(const String& id, double anticipatedRemoval, - const String& message, - std::unique_ptr<SourceLocation> location) - : MessageReportBody(message, std::move(location)), + const String& message) + : MessageReportBody(message), id_(id), anticipatedRemoval_(anticipatedRemoval) {}
diff --git a/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h b/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h index d7b1b76..d9880de4 100644 --- a/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h +++ b/third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h
@@ -16,9 +16,8 @@ public: FeaturePolicyViolationReportBody(const String& feature_id, const String& message, - const String& disposition, - std::unique_ptr<SourceLocation> location) - : MessageReportBody(message, std::move(location)), + const String& disposition) + : MessageReportBody(message), feature_id_(feature_id), disposition_(disposition) {}
diff --git a/third_party/blink/renderer/core/frame/intervention.cc b/third_party/blink/renderer/core/frame/intervention.cc index f3f654e..1247dd4d 100644 --- a/third_party/blink/renderer/core/frame/intervention.cc +++ b/third_party/blink/renderer/core/frame/intervention.cc
@@ -33,8 +33,8 @@ return; // Construct the intervention report. - InterventionReportBody* body = MakeGarbageCollected<InterventionReportBody>( - id, message, SourceLocation::Capture()); + InterventionReportBody* body = + MakeGarbageCollected<InterventionReportBody>(id, message); Report* report = MakeGarbageCollected<Report>( "intervention", document->Url().GetString(), body);
diff --git a/third_party/blink/renderer/core/frame/intervention_report_body.h b/third_party/blink/renderer/core/frame/intervention_report_body.h index 058f948..0414005 100644 --- a/third_party/blink/renderer/core/frame/intervention_report_body.h +++ b/third_party/blink/renderer/core/frame/intervention_report_body.h
@@ -14,10 +14,8 @@ DEFINE_WRAPPERTYPEINFO(); public: - InterventionReportBody(const String& id, - const String& message, - std::unique_ptr<SourceLocation> location) - : MessageReportBody(message, std::move(location)), id_(id) {} + InterventionReportBody(const String& id, const String& message) + : MessageReportBody(message), id_(id) {} ~InterventionReportBody() override = default;
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index f13e058..7bb3906 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1440,8 +1440,9 @@ } FrameOcclusionState LocalFrame::GetOcclusionState() const { + // TODO(dcheng): Get rid of this branch for the main frame. if (IsMainFrame()) - return kGuaranteedNotOccluded; + return FrameOcclusionState::kGuaranteedNotOccluded; if (IsLocalRoot()) return occlusion_state_; return LocalFrameRoot().GetOcclusionState();
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 1f21df0..e77b504 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -552,7 +552,7 @@ mutable mojom::blink::ReportingServiceProxyPtr reporting_service_; IntRect remote_viewport_intersection_; - FrameOcclusionState occlusion_state_ = kUnknownOcclusionState; + FrameOcclusionState occlusion_state_ = FrameOcclusionState::kUnknown; std::unique_ptr<FrameResourceCoordinator> frame_resource_coordinator_; // Per-frame URLLoader factory.
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 4b35f36..264d2b4 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2215,7 +2215,7 @@ ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { for (auto& observer : frame_view.lifecycle_observers_) - observer->WillStartLifecycleUpdate(); + observer->WillStartLifecycleUpdate(frame_view); }); // If we're in PrintBrowser mode, setup a print context. @@ -2231,7 +2231,7 @@ ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { for (auto& observer : frame_view.lifecycle_observers_) - observer->DidFinishLifecycleUpdate(); + observer->DidFinishLifecycleUpdate(frame_view); }); return Lifecycle().GetState() == target_state;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 867a0a7..49fa8c1 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -117,8 +117,8 @@ : public GarbageCollectedMixin { public: // These are called when the lifecycle updates start/finish. - virtual void WillStartLifecycleUpdate() = 0; - virtual void DidFinishLifecycleUpdate() = 0; + virtual void WillStartLifecycleUpdate(const LocalFrameView&) = 0; + virtual void DidFinishLifecycleUpdate(const LocalFrameView&) = 0; }; static LocalFrameView* Create(LocalFrame&);
diff --git a/third_party/blink/renderer/core/frame/location_report_body.h b/third_party/blink/renderer/core/frame/location_report_body.h new file mode 100644 index 0000000..9a730a55 --- /dev/null +++ b/third_party/blink/renderer/core/frame/location_report_body.h
@@ -0,0 +1,49 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_REPORT_BODY_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_REPORT_BODY_H_ + +#include <memory> +#include <utility> + +#include "third_party/blink/renderer/bindings/core/v8/source_location.h" +#include "third_party/blink/renderer/core/frame/report_body.h" + +namespace blink { + +class LocationReportBody : public ReportBody { + public: + explicit LocationReportBody(std::unique_ptr<SourceLocation> location) + : location_(std::move(location)) {} + + LocationReportBody() : LocationReportBody(SourceLocation::Capture()) {} + + LocationReportBody(const String& source_file, + unsigned line_number, + unsigned column_number) + : LocationReportBody( + SourceLocation::Capture(source_file, line_number, column_number)) {} + + ~LocationReportBody() override = default; + + String sourceFile() const { return location_->Url(); } + + uint32_t lineNumber(bool& is_null) const { + is_null = location_->IsUnknown(); + return location_->LineNumber(); + } + + uint32_t columnNumber(bool& is_null) const { + is_null = location_->IsUnknown(); + return location_->ColumnNumber(); + } + + protected: + std::unique_ptr<SourceLocation> location_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_REPORT_BODY_H_
diff --git a/third_party/blink/renderer/core/frame/message_report_body.h b/third_party/blink/renderer/core/frame/message_report_body.h index 3c44e32e0..a2398bc 100644 --- a/third_party/blink/renderer/core/frame/message_report_body.h +++ b/third_party/blink/renderer/core/frame/message_report_body.h
@@ -6,35 +6,21 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_BODY_H_ #include "third_party/blink/renderer/bindings/core/v8/source_location.h" -#include "third_party/blink/renderer/core/frame/report_body.h" +#include "third_party/blink/renderer/core/frame/location_report_body.h" namespace blink { -class MessageReportBody : public ReportBody { +class MessageReportBody : public LocationReportBody { public: - MessageReportBody(const String& message, - std::unique_ptr<SourceLocation> location) - : message_(message), location_(std::move(location)) {} + MessageReportBody(const String& message) + : LocationReportBody(), message_(message) {} ~MessageReportBody() override = default; String message() const { return message_; } - String sourceFile() const { return location_->Url(); } - - uint32_t lineNumber(bool& is_null) const { - is_null = location_->IsUnknown(); - return location_->LineNumber(); - } - - uint32_t columnNumber(bool& is_null) const { - is_null = location_->IsUnknown(); - return location_->ColumnNumber(); - } - protected: const String message_; - std::unique_ptr<SourceLocation> location_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame_view.cc b/third_party/blink/renderer/core/frame/remote_frame_view.cc index ea41020..6325110 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_view.cc +++ b/third_party/blink/renderer/core/frame/remote_frame_view.cc
@@ -101,7 +101,8 @@ FrameOcclusionState occlusion_state = owner_element->GetDocument().GetFrame()->GetOcclusionState(); bool should_compute_occlusion = - needs_occlusion_tracking_ && occlusion_state == kGuaranteedNotOccluded && + needs_occlusion_tracking_ && + occlusion_state == FrameOcclusionState::kGuaranteedNotOccluded && parent_lifecycle_state >= DocumentLifecycle::kPrePaintClean && RuntimeEnabledFeatures::IntersectionObserverV2Enabled(); @@ -134,9 +135,9 @@ viewport_intersection = EnclosingIntRect(intersection_rect); } if (should_compute_occlusion && !geometry.IsVisible()) - occlusion_state = kPossiblyOccluded; - } else if (occlusion_state == kGuaranteedNotOccluded) { - occlusion_state = kUnknownOcclusionState; + occlusion_state = FrameOcclusionState::kPossiblyOccluded; + } else if (occlusion_state == FrameOcclusionState::kGuaranteedNotOccluded) { + occlusion_state = FrameOcclusionState::kUnknown; } // TODO(szager): There are some redundant IPC's here; clean them up.
diff --git a/third_party/blink/renderer/core/frame/remote_frame_view.h b/third_party/blink/renderer/core/frame/remote_frame_view.h index a246b3b..93721f7 100644 --- a/third_party/blink/renderer/core/frame/remote_frame_view.h +++ b/third_party/blink/renderer/core/frame/remote_frame_view.h
@@ -100,7 +100,7 @@ Member<RemoteFrame> remote_frame_; bool is_attached_; IntRect last_viewport_intersection_; - FrameOcclusionState last_occlusion_state_ = kUnknownOcclusionState; + FrameOcclusionState last_occlusion_state_ = FrameOcclusionState::kUnknown; IntRect frame_rect_; bool self_visible_; bool parent_visible_;
diff --git a/third_party/blink/renderer/core/frame/settings.cc b/third_party/blink/renderer/core/frame/settings.cc index d91bf99..ac117465 100644 --- a/third_party/blink/renderer/core/frame/settings.cc +++ b/third_party/blink/renderer/core/frame/settings.cc
@@ -114,6 +114,7 @@ } else { SetDarkMode(DarkMode::kOff); } + Invalidate(SettingsDelegate::kColorSchemeChange); } } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index a30d822..a5bc0df1 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -1007,7 +1007,7 @@ { name: "preferredColorScheme", initial: "PreferredColorScheme::kNoPreference", - invalidate: "MediaQuery", + invalidate: "ColorScheme", type: "PreferredColorScheme", },
diff --git a/third_party/blink/renderer/core/frame/settings_delegate.h b/third_party/blink/renderer/core/frame/settings_delegate.h index deceb0a..4e64deeb5 100644 --- a/third_party/blink/renderer/core/frame/settings_delegate.h +++ b/third_party/blink/renderer/core/frame/settings_delegate.h
@@ -69,6 +69,7 @@ kHighlightAdsChange, kPaintChange, kScrollbarLayoutChange, + kColorSchemeChange, }; virtual void SettingsChanged(ChangeType) = 0;
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 2b6b90e5..76d81ef 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1142,6 +1142,23 @@ if (value_changed) NotifyFormStateChanged(); + + if (isConnected()) { + if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) { + auto* page = GetDocument().GetPage(); + auto* view = GetDocument().View(); + // Run the document lifecycle to ensure AX notifications fire, + // even if the value didn't change. + if (page && view) { + // TODO(aboxhall): add a lifecycle phase for accessibility updates. + if (!view->CanThrottleRendering()) + page->Animator().ScheduleVisualUpdate(GetDocument().GetFrame()); + + GetDocument().Lifecycle().EnsureStateAtMost( + DocumentLifecycle::kVisualUpdatePending); + } + } + } } void HTMLInputElement::SetNonAttributeValue(const String& sanitized_value) {
diff --git a/third_party/blink/renderer/core/html/html_meta_element.cc b/third_party/blink/renderer/core/html/html_meta_element.cc index c5b25dc..b7f430e1 100644 --- a/third_party/blink/renderer/core/html/html_meta_element.cc +++ b/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -478,6 +478,9 @@ void HTMLMetaElement::ProcessSupportedColorSchemes( const AtomicString& content) { + if (!RuntimeEnabledFeatures::MetaSupportedColorSchemesEnabled()) + return; + SpaceSplitString supported_schemes_strings(content.LowerASCII()); size_t count = supported_schemes_strings.size(); ColorSchemeSet supported_schemes;
diff --git a/third_party/blink/renderer/core/html/html_meta_element_test.cc b/third_party/blink/renderer/core/html/html_meta_element_test.cc index 1d30c475..e179eb1 100644 --- a/third_party/blink/renderer/core/html/html_meta_element_test.cc +++ b/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -5,6 +5,8 @@ #include "third_party/blink/renderer/core/html/html_meta_element.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/media_query_list.h" +#include "third_party/blink/renderer/core/css/media_query_matcher.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/settings.h" @@ -21,6 +23,8 @@ PageTestBase::SetUp(); RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(true); + RuntimeEnabledFeatures::SetMetaSupportedColorSchemesEnabled(true); + RuntimeEnabledFeatures::SetMediaQueryPrefersColorSchemeEnabled(true); GetDocument().GetSettings()->SetViewportMetaEnabled(true); } @@ -185,4 +189,24 @@ EXPECT_TRUE(SupportsColorScheme(ColorScheme::kDark)); } +TEST_F(HTMLMetaElementTest, SupportedColorSchemesForcedDarkeningAndMQ) { + GetDocument().GetSettings()->SetPreferredColorScheme( + PreferredColorScheme::kDark); + + auto* media_query = GetDocument().GetMediaQueryMatcher().MatchMedia( + "(prefers-color-scheme: dark)"); + EXPECT_TRUE(media_query->matches()); + GetDocument().GetSettings()->SetForceDarkModeEnabled(true); + EXPECT_FALSE(media_query->matches()); + + SetSupportedColorSchemes("light"); + EXPECT_FALSE(media_query->matches()); + + SetSupportedColorSchemes("dark"); + EXPECT_TRUE(media_query->matches()); + + SetSupportedColorSchemes("light dark"); + EXPECT_TRUE(media_query->matches()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index 8a2a3140..3645f06c 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -689,7 +689,6 @@ return (!mime_type.IsEmpty() && url.IsEmpty()) || !MixedContentChecker::ShouldBlockFetch( frame, mojom::RequestContextType::OBJECT, - network::mojom::RequestContextFrameType::kNone, ResourceRequest::RedirectStatus::kNoRedirect, url); }
diff --git a/third_party/blink/renderer/core/input/BUILD.gn b/third_party/blink/renderer/core/input/BUILD.gn index ab9d456..c301db4d 100644 --- a/third_party/blink/renderer/core/input/BUILD.gn +++ b/third_party/blink/renderer/core/input/BUILD.gn
@@ -14,6 +14,8 @@ "event_handler.h", "event_handling_util.cc", "event_handling_util.h", + "fallback_cursor_event_manager.cc", + "fallback_cursor_event_manager.h", "gesture_manager.cc", "gesture_manager.h", "input_device_capabilities.cc",
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 30f83e0a..5016dc3 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -178,7 +178,13 @@ *selection_controller_)), active_interval_timer_(frame.GetTaskRunner(TaskType::kUserInteraction), this, - &EventHandler::ActiveIntervalTimerFired) {} + &EventHandler::ActiveIntervalTimerFired) { + if (RuntimeEnabledFeatures::FallbackCursorModeEnabled() && + frame.IsLocalRoot()) { + fallback_cursor_event_manager_ = + MakeGarbageCollected<FallbackCursorEventManager>(frame); + } +} void EventHandler::Trace(blink::Visitor* visitor) { visitor->Trace(frame_); @@ -196,6 +202,7 @@ visitor->Trace(keyboard_event_manager_); visitor->Trace(pointer_event_manager_); visitor->Trace(gesture_manager_); + visitor->Trace(fallback_cursor_event_manager_); visitor->Trace(last_deferred_tap_element_); } @@ -235,7 +242,7 @@ return; controller->StartMiddleClickAutoscroll( layout_object->GetFrame(), LastKnownMousePositionInRootFrame(), - mouse_event_manager_->LastKnownMousePositionGlobal()); + mouse_event_manager_->LastKnownMouseScreenPosition()); mouse_event_manager_->InvalidateClick(); } @@ -331,6 +338,10 @@ mouse_event_manager_->LastKnownMousePositionInViewport()); } +FloatPoint EventHandler::LastKnownMouseScreenPosition() const { + return mouse_event_manager_->LastKnownMouseScreenPosition(); +} + IntPoint EventHandler::DragDataTransferLocationForTesting() { if (mouse_event_manager_->GetDragState().drag_data_transfer_) return mouse_event_manager_->GetDragState() @@ -650,6 +661,12 @@ frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint( mev.InnerNode()); + if (RuntimeEnabledFeatures::FallbackCursorModeEnabled()) { + frame_->LocalFrameRoot() + .GetEventHandler() + .fallback_cursor_event_manager_->HandleMousePressEvent(mouse_event); + } + LocalFrame* subframe = event_handling_util::GetTargetSubframe(mev); if (subframe) { WebInputEventResult result = PassMousePressEventToSubframe(mev, subframe); @@ -772,6 +789,7 @@ result.SetToShadowHostIfInRestrictedShadowRoot(); frame_->GetChromeClient().OnMouseDown(*result.InnerNode()); } + return event_result; } @@ -801,6 +819,12 @@ page->GetChromeClient().MouseDidMoveOverElement(*frame_, location, hovered_node_result); + if (RuntimeEnabledFeatures::FallbackCursorModeEnabled()) { + frame_->LocalFrameRoot() + .GetEventHandler() + .fallback_cursor_event_manager_->HandleMouseMoveEvent(event); + } + return result; } @@ -853,7 +877,7 @@ page->GetAutoscrollController().StopMiddleClickAutoscroll(frame_); } else { page->GetAutoscrollController().HandleMouseMoveForMiddleClickAutoscroll( - frame_, mouse_event_manager_->LastKnownMousePositionGlobal(), + frame_, mouse_event_manager_->LastKnownMouseScreenPosition(), mouse_event.button == WebPointerProperties::Button::kMiddle); } }
diff --git a/third_party/blink/renderer/core/input/event_handler.h b/third_party/blink/renderer/core/input/event_handler.h index 130c343..b923b44 100644 --- a/third_party/blink/renderer/core/input/event_handler.h +++ b/third_party/blink/renderer/core/input/event_handler.h
@@ -35,6 +35,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" #include "third_party/blink/renderer/core/events/text_event_input_type.h" +#include "third_party/blink/renderer/core/input/fallback_cursor_event_manager.h" #include "third_party/blink/renderer/core/input/gesture_manager.h" #include "third_party/blink/renderer/core/input/keyboard_event_manager.h" #include "third_party/blink/renderer/core/input/mouse_event_manager.h" @@ -134,6 +135,7 @@ void ResizeScrollableAreaDestroyed(); FloatPoint LastKnownMousePositionInRootFrame() const; + FloatPoint LastKnownMouseScreenPosition() const; IntPoint DragDataTransferLocationForTesting(); @@ -448,6 +450,7 @@ Member<KeyboardEventManager> keyboard_event_manager_; Member<PointerEventManager> pointer_event_manager_; Member<GestureManager> gesture_manager_; + Member<FallbackCursorEventManager> fallback_cursor_event_manager_; double max_mouse_moved_duration_; @@ -496,6 +499,11 @@ FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ReadOnlyInputDoesNotInheritUserSelect); + FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, + MouseMoveCursorLockOnDiv); + FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, + MouseMoveCursorLockOnIFrame); + DISALLOW_COPY_AND_ASSIGN(EventHandler); };
diff --git a/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc b/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc new file mode 100644 index 0000000..e136641f --- /dev/null +++ b/third_party/blink/renderer/core/input/fallback_cursor_event_manager.cc
@@ -0,0 +1,337 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/input/fallback_cursor_event_manager.h" + +#include "third_party/blink/public/platform/web_keyboard_event.h" +#include "third_party/blink/public/platform/web_mouse_event.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/editing/editing_utilities.h" +#include "third_party/blink/renderer/core/events/web_input_event_conversion.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_client.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/html/html_frame_owner_element.h" +#include "third_party/blink/renderer/core/input/event_handler.h" +#include "third_party/blink/renderer/core/input/scroll_manager.h" +#include "third_party/blink/renderer/core/layout/hit_test_location.h" +#include "third_party/blink/renderer/core/layout/hit_test_request.h" +#include "third_party/blink/renderer/core/layout/hit_test_result.h" +#include "third_party/blink/renderer/core/layout/layout_box.h" +#include "third_party/blink/renderer/core/layout/layout_object.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" +#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" +#include "third_party/blink/renderer/platform/geometry/int_point.h" +#include "third_party/blink/renderer/platform/geometry/int_size.h" +#include "third_party/blink/renderer/platform/keyboard_codes.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" + +namespace blink { + +namespace { + +const float kScrollAreaRatio = 0.3f; + +LocalFrame* FrameOfNode(const Node& node) { + return node.GetDocument().GetFrame(); +} + +Node* ParentNode(const Node& node) { + if (node.IsDocumentNode()) { + FrameOwner* frame_owner = FrameOfNode(node)->Owner(); + DCHECK(frame_owner->IsLocal()); + return DynamicTo<HTMLFrameOwnerElement>(frame_owner); + } + + return node.parentNode(); +} + +HitTestResult HitTest(LayoutView* layout_view, const IntPoint& point_in_root) { + HitTestRequest request(HitTestRequest::kReadOnly | + HitTestRequest::kAllowChildFrameContent); + HitTestLocation location(point_in_root); + HitTestResult result(request, location); + layout_view->HitTest(location, result); + + return result; +} + +bool CanScrollAnyDirection(const ScrollableArea& scrollable) { + IntSize scroll_dimensions = + scrollable.MaximumScrollOffsetInt() - scrollable.MinimumScrollOffsetInt(); + return !scroll_dimensions.IsZero(); +} + +IntSize ScrollableAreaClipSizeInViewport(const ScrollableArea& scrollable) { + LayoutBox* box = scrollable.GetLayoutBox(); + DCHECK(box); + LocalFrameView* view = box->GetFrameView(); + DCHECK(view); + + LayoutRect layout_rect = + LayoutRect(scrollable.VisibleContentRect(blink::kIncludeScrollbars)); + layout_rect = view->DocumentToFrame(layout_rect); + IntRect rect = view->FrameToViewport(EnclosedIntRect(layout_rect)); + return rect.Size(); +} + +IntPoint RootFrameLocationToScrollable(const IntPoint& location_in_root_frame, + const ScrollableArea& scrollable) { + LayoutBox* box = scrollable.GetLayoutBox(); + DCHECK(box); + LocalFrameView* view = box->GetFrameView(); + + DCHECK(view); + + IntPoint location_in_frame = + view->ConvertFromRootFrame(location_in_root_frame); + + if (&scrollable == view->GetScrollableArea()) + return location_in_frame; + + DCHECK(scrollable.IsPaintLayerScrollableArea()); + + IntPoint location_in_box = + view->ConvertToLayoutObject(*box, location_in_frame); + location_in_box.Move(-box->BorderLeft().ToInt(), -box->BorderTop().ToInt()); + return location_in_box; +} + +} // namespace + +FallbackCursorEventManager::FallbackCursorEventManager(LocalFrame& root_frame) + : root_frame_(root_frame) { + DCHECK(root_frame.IsMainFrame()); + ResetCurrentScrollable(); +} + +void FallbackCursorEventManager::Trace(blink::Visitor* visitor) { + visitor->Trace(root_frame_); + visitor->Trace(current_node_); +} + +void FallbackCursorEventManager::ResetCurrentScrollable() { + current_node_.Clear(); +} + +// Check if current scrolling ScrollableArea is still valid and reset it if not. +void FallbackCursorEventManager::InvalidateCurrentScrollableIfNeeded() { + if (!current_node_) + return; + + if (!current_node_->isConnected() || + !current_node_->GetDocument().GetFrame()) { + ResetCurrentScrollable(); + } + ScrollableArea* current_scrollable = CurrentScrollingScrollableArea(); + if (!current_scrollable || !CanScrollAnyDirection(*current_scrollable)) + ResetCurrentScrollable(); +} + +ScrollableArea* FallbackCursorEventManager::CurrentScrollingScrollableArea() { + LocalFrame* current_frame = CurrentScrollingFrame(); + Node* current_node = CurrentScrollingNode(); + + if (current_node->IsDocumentNode()) + return current_frame->View()->GetScrollableArea(); + + auto* layout_object = current_node->GetLayoutObject(); + if (!layout_object || !layout_object->IsBox()) + return nullptr; + + return ToLayoutBox(current_node->GetLayoutObject())->GetScrollableArea(); +} + +Node* FallbackCursorEventManager::CurrentScrollingNode() { + if (!current_node_) + return root_frame_->GetDocument(); + + return current_node_.Get(); +} + +LocalFrame* FallbackCursorEventManager::CurrentScrollingFrame() { + if (!current_node_) + return root_frame_; + + return FrameOfNode(*current_node_.Get()); +} + +bool FallbackCursorEventManager::ShouldLock( + Direction d, + const ScrollableArea& scrollable, + const IntSize& node_size, + const IntPoint& cursor_location_in_node) { + // Check can scroll in direction, if not should not lock this direction. + IntSize current_offset = scrollable.ScrollOffsetInt(); + IntSize min_offset = scrollable.MinimumScrollOffsetInt(); + IntSize max_offset = scrollable.MaximumScrollOffsetInt(); + + switch (d) { + case Direction::kLeft: + if (current_offset.Width() <= min_offset.Width()) + return false; + break; + case Direction::kRight: + if (current_offset.Width() >= max_offset.Width()) + return false; + break; + case Direction::kUp: + if (current_offset.Height() <= min_offset.Height()) + return false; + break; + case Direction::kDown: + if (current_offset.Height() >= max_offset.Height()) + return false; + break; + default: + NOTREACHED(); + } + + // Check if cursor located in scroll area. + switch (d) { + case Direction::kLeft: + if (cursor_location_in_node.X() < node_size.Width() * kScrollAreaRatio) { + return true; + } + break; + case Direction::kRight: + if (cursor_location_in_node.X() > + node_size.Width() * (1 - kScrollAreaRatio)) { + return true; + } + break; + case Direction::kUp: + if (cursor_location_in_node.Y() < node_size.Height() * kScrollAreaRatio) { + return true; + } + break; + case Direction::kDown: + if (cursor_location_in_node.Y() > + node_size.Height() * (1 - kScrollAreaRatio)) { + return true; + } + break; + default: + NOTREACHED(); + } + + return false; +} + +void FallbackCursorEventManager::LockCursor(bool left, + bool right, + bool up, + bool down) { + root_frame_->GetChromeClient().FallbackCursorModeLockCursor( + root_frame_.Get(), left, right, up, down); +} + +void FallbackCursorEventManager::SetCursorVisibility(bool visible) { + root_frame_->GetChromeClient().FallbackCursorModeSetCursorVisibility( + root_frame_.Get(), visible); +} + +void FallbackCursorEventManager::ComputeLockCursor( + const IntPoint& location_in_root_frame) { + ScrollableArea* scrollable = CurrentScrollingScrollableArea(); + + DCHECK(scrollable); + IntSize scrollable_clip_size_in_viewport = + ScrollableAreaClipSizeInViewport(*scrollable); + IntPoint location_in_scrollable = + RootFrameLocationToScrollable(location_in_root_frame, *scrollable); + + bool left = + ShouldLock(Direction::kLeft, *scrollable, + scrollable_clip_size_in_viewport, location_in_scrollable); + bool right = + ShouldLock(Direction::kRight, *scrollable, + scrollable_clip_size_in_viewport, location_in_scrollable); + bool up = + ShouldLock(Direction::kUp, *scrollable, scrollable_clip_size_in_viewport, + location_in_scrollable); + bool down = + ShouldLock(Direction::kDown, *scrollable, + scrollable_clip_size_in_viewport, location_in_scrollable); + + LockCursor(left, right, up, down); +} + +void FallbackCursorEventManager::HandleMouseMoveEvent(const WebMouseEvent& e) { + DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled()); + + InvalidateCurrentScrollableIfNeeded(); + ScrollableArea* scrollable = CurrentScrollingScrollableArea(); + + DCHECK(scrollable); + + IntPoint location_in_root_frame{e.PositionInWidget().x, + e.PositionInWidget().y}; + + IntSize scrollable_clip_size_in_viewport = + ScrollableAreaClipSizeInViewport(*scrollable); + IntPoint location_in_scrollable = + RootFrameLocationToScrollable(location_in_root_frame, *scrollable); + + // Check if mouse out of current node. + IntRect rect = IntRect(IntPoint(), scrollable_clip_size_in_viewport); + if (!rect.Contains(location_in_scrollable)) + ResetCurrentScrollable(); + + ComputeLockCursor(location_in_root_frame); +} + +void FallbackCursorEventManager::HandleMousePressEvent(const WebMouseEvent& e) { + DCHECK(RuntimeEnabledFeatures::FallbackCursorModeEnabled()); + + ResetCurrentScrollable(); + + // Re hit test since we need a hit test with child frame. + IntPoint location{e.PositionInRootFrame().x, e.PositionInRootFrame().y}; + HitTestResult hit_test_result = + HitTest(root_frame_->GetDocument()->GetLayoutView(), location); + Node* node = hit_test_result.InnerNode(); + + // Click on input boxes or media node should hide the cursor. + if (HasEditableStyle(*node) || node->IsMediaElement()) { + SetCursorVisibility(false); + return; + } + + for (; node; node = ParentNode(*node)) { + ScrollableArea* scrollable = nullptr; + if (node->IsDocumentNode()) { + LocalFrame* current_frame = FrameOfNode(*node); + DCHECK(current_frame); + scrollable = current_frame->View()->GetScrollableArea(); + } else { + auto* layout_object = node->GetLayoutObject(); + if (!layout_object || !layout_object->IsBox()) { + continue; + } + + LayoutBox* box = ToLayoutBox(layout_object); + if (!box->CanBeScrolledAndHasScrollableArea()) { + continue; + } + scrollable = box->GetScrollableArea(); + } + + DCHECK(scrollable); + if (!CanScrollAnyDirection(*scrollable)) + continue; + + // Found scrollable + break; + } + + current_node_ = node; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h b/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h new file mode 100644 index 0000000..b5a56fc --- /dev/null +++ b/third_party/blink/renderer/core/input/fallback_cursor_event_manager.h
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_ + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/heap/visitor.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" + +namespace blink { + +class Node; +class IntPoint; +class IntSize; +class LocalFrame; +class ScrollableArea; +class WebMouseEvent; + +class CORE_EXPORT FallbackCursorEventManager + : public GarbageCollected<FallbackCursorEventManager> { + public: + FallbackCursorEventManager(LocalFrame&); + void Trace(blink::Visitor*); + + void HandleMouseMoveEvent(const WebMouseEvent&); + void HandleMousePressEvent(const WebMouseEvent&); + + private: + FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, + MouseMoveCursorLockOnDiv); + FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, + MouseMoveCursorLockOnIFrame); + + enum class Direction { + kLeft, + kRight, + kUp, + kDown, + }; + + void ResetCurrentScrollable(); + void InvalidateCurrentScrollableIfNeeded(); + LocalFrame* CurrentScrollingFrame(); + Node* CurrentScrollingNode(); + ScrollableArea* CurrentScrollingScrollableArea(); + + bool ShouldLock(Direction d, + const ScrollableArea& scrollable, + const IntSize& node_size, + const IntPoint& cursor_location_in_node); + void ComputeLockCursor(const IntPoint& location_in_root_frame); + void LockCursor(bool left, bool right, bool up, bool down); + void SetCursorVisibility(bool visible); + + const Member<LocalFrame> root_frame_; + Member<Node> current_node_; + + DISALLOW_COPY_AND_ASSIGN(FallbackCursorEventManager); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_FALLBACK_CURSOR_EVENT_MANAGER_H_
diff --git a/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc new file mode 100644 index 0000000..90a0ec63 --- /dev/null +++ b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
@@ -0,0 +1,261 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/input/fallback_cursor_event_manager.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/web_mouse_event.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/input/event_handler.h" +#include "third_party/blink/renderer/core/loader/empty_clients.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" + +namespace blink { + +class FallbackCursorChromeClient : public EmptyChromeClient { + public: + FallbackCursorChromeClient() {} + + void FallbackCursorModeLockCursor(LocalFrame* frame, + bool left, + bool right, + bool up, + bool down) override { + cursor_lock_[0] = left; + cursor_lock_[1] = right; + cursor_lock_[2] = up; + cursor_lock_[3] = down; + } + + void FallbackCursorModeSetCursorVisibility(LocalFrame* frame, + bool visible) override { + cursor_visible_ = visible; + } + + bool cursor_lock_[4] = {0}; + bool cursor_visible_ = true; + + private: + DISALLOW_COPY_AND_ASSIGN(FallbackCursorChromeClient); +}; + +class FallbackCursorEventManagerTest : public RenderingTest { + protected: + FallbackCursorEventManagerTest() + : RenderingTest(SingleChildLocalFrameClient::Create()), + chrome_client_(MakeGarbageCollected<FallbackCursorChromeClient>()) { + RuntimeEnabledFeatures::SetFallbackCursorModeEnabled(true); + } + + ~FallbackCursorEventManagerTest() override {} + + ChromeClient& GetChromeClient() const override { return *chrome_client_; } + + FallbackCursorChromeClient& GetFallbackCursorChromeClient() const { + return *chrome_client_; + } + + void MouseMove(int x, int y) { + WebMouseEvent event(WebInputEvent::kMouseMove, WebFloatPoint(x, y), + WebFloatPoint(x, y), + WebPointerProperties::Button::kNoButton, 0, + WebInputEvent::kNoModifiers, CurrentTimeTicks()); + event.SetFrameScale(1); + GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent( + event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>()); + } + + void MouseDown(int x, int y) { + WebMouseEvent event( + WebInputEvent::kMouseDown, WebFloatPoint(x, y), WebFloatPoint(x, y), + WebPointerProperties::Button::kLeft, 0, + WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks()); + event.SetFrameScale(1); + GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event); + } + + void ExpectLock(bool l, bool r, bool u, bool d) { + EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[0], l); + EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[1], r); + EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[2], u); + EXPECT_EQ(GetFallbackCursorChromeClient().cursor_lock_[3], d); + } + + private: + Persistent<FallbackCursorChromeClient> chrome_client_; + + DISALLOW_COPY_AND_ASSIGN(FallbackCursorEventManagerTest); +}; + +TEST_F(FallbackCursorEventManagerTest, RootFrameNotScrollable) { + SetBodyInnerHTML("A"); + + // Mouse move to edge. + MouseMove(0, 0); + ExpectLock(false, false, false, false); + + MouseMove(0, 600); + ExpectLock(false, false, false, false); + + MouseMove(800, 0); + ExpectLock(false, false, false, false); + + MouseMove(800, 600); + ExpectLock(false, false, false, false); +} + +TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnRootFrame) { + SetBodyInnerHTML(R"HTML( + <style> + html, body { + margin: 0px; + } + .big { + height: 10000px; + width: 10000px; + } + </style> + <div class='big'></div> + )HTML"); + + // Move below the scroll down line. + MouseMove(100, 500); + ExpectLock(false, false, false, true); + + // Move above the scroll down line. + MouseMove(100, 400); + ExpectLock(false, false, false, false); + + // Move to the right of scroll right line. + MouseMove(600, 400); + ExpectLock(false, true, false, false); +} + +TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnDiv) { + SetBodyInnerHTML(R"HTML( + <style> + html, body { + margin: 0px; + } + .big { + height: 10000px; + width: 10000px; + } + #d1 { + height: 100px; + width: 100px; + overflow: auto; + } + </style> + <div id='d1'> + <div class='big'></div> + </div> + )HTML"); + + // Move below the scroll down line but before mouse down. + MouseMove(50, 80); + ExpectLock(false, false, false, false); + EXPECT_FALSE(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_); + + // Mouse down and move lock on down. + MouseDown(50, 80); + Element* d1 = GetDocument().getElementById("d1"); + EXPECT_EQ(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_.Get(), + d1); + MouseMove(50, 80); + ExpectLock(false, false, false, true); + + // Mouse move out of div. + MouseMove(200, 200); + ExpectLock(false, false, false, false); + EXPECT_FALSE(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_); +} + +TEST_F(FallbackCursorEventManagerTest, MouseMoveCursorLockOnIFrame) { + SetBodyInnerHTML(R"HTML( + <style> + html, body { + margin: 0px; + } + #ifr { + height: 100px; + width: 100px; + } + </style> + <iframe id='ifr'></iframe> + )HTML"); + + SetChildFrameHTML(R"HTML( + <style> + html, body { + margin: 0px; + } + .big { + height: 10000px; + width: 10000px; + } + </style> + <div class='big'></div> + )HTML"); + + // Move below the scroll down line but before mouse down. + MouseMove(50, 80); + ExpectLock(false, false, false, false); + EXPECT_FALSE(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_); + + // Mouse down and move lock on down. + MouseDown(50, 80); + MouseMove(50, 80); + ExpectLock(false, false, false, true); + Node* child_frame_doc = ChildFrame().GetDocument(); + EXPECT_EQ(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_.Get(), + child_frame_doc); + + // Mouse move out of iframe. + MouseMove(200, 200); + ExpectLock(false, false, false, false); + EXPECT_FALSE(GetDocument() + .GetFrame() + ->GetEventHandler() + .fallback_cursor_event_manager_->current_node_); +} + +TEST_F(FallbackCursorEventManagerTest, MouseDownOnEditor) { + SetBodyInnerHTML(R"HTML( + <style> + html, body { + margin: 0px; + } + .big { + height: 10000px; + width: 10000px; + } + </style> + <div class='big' contenteditable='true'> + </div> + )HTML"); + + MouseMove(50, 80); + MouseDown(50, 80); + + EXPECT_EQ(GetFallbackCursorChromeClient().cursor_visible_, false); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc index 7e3448e..4626cf37 100644 --- a/third_party/blink/renderer/core/input/mouse_event_manager.cc +++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -126,7 +126,7 @@ captures_dragging_ = false; is_mouse_position_unknown_ = true; last_known_mouse_position_ = FloatPoint(); - last_known_mouse_global_position_ = FloatPoint(); + last_known_mouse_screen_position_ = FloatPoint(); mouse_pressed_ = false; click_count_ = 0; click_element_ = nullptr; @@ -402,7 +402,7 @@ } WebMouseEvent fake_mouse_move_event(WebInputEvent::kMouseMove, last_known_mouse_position_, - last_known_mouse_global_position_, button, + last_known_mouse_screen_position_, button, 0, modifiers, CurrentTimeTicks()); Vector<WebMouseEvent> coalesced_events, predicted_events; frame_->GetEventHandler().HandleMouseMoveEvent( @@ -625,14 +625,14 @@ return last_known_mouse_position_; } -FloatPoint MouseEventManager::LastKnownMousePositionGlobal() { - return last_known_mouse_global_position_; +FloatPoint MouseEventManager::LastKnownMouseScreenPosition() { + return last_known_mouse_screen_position_; } void MouseEventManager::SetLastKnownMousePosition(const WebMouseEvent& event) { is_mouse_position_unknown_ = event.GetType() == WebInputEvent::kMouseLeave; last_known_mouse_position_ = event.PositionInWidget(); - last_known_mouse_global_position_ = event.PositionInScreen(); + last_known_mouse_screen_position_ = event.PositionInScreen(); } void MouseEventManager::SetLastMousePositionAsUnknown() {
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.h b/third_party/blink/renderer/core/input/mouse_event_manager.h index 225f885..a011f5e 100644 --- a/third_party/blink/renderer/core/input/mouse_event_manager.h +++ b/third_party/blink/renderer/core/input/mouse_event_manager.h
@@ -133,7 +133,7 @@ Element* GetElementUnderMouse(); bool IsMousePositionUnknown(); FloatPoint LastKnownMousePositionInViewport(); - FloatPoint LastKnownMousePositionGlobal(); + FloatPoint LastKnownMouseScreenPosition(); bool MousePressed(); void ReleaseMousePress(); @@ -226,7 +226,7 @@ // The last mouse movement position this frame has seen in viewport // coordinates. FloatPoint last_known_mouse_position_; - FloatPoint last_known_mouse_global_position_; + FloatPoint last_known_mouse_screen_position_; unsigned is_mouse_position_unknown_ : 1; // Current button-press state for mouse/mouse-like-stylus.
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index 0d1a189..6e5fc93b 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -225,7 +225,7 @@ return; } - StyleGeneratedImage* gen_image = ToStyleGeneratedImage(style_image); + StyleGeneratedImage* gen_image = To<StyleGeneratedImage>(style_image); CSSValue* image_css = gen_image->CssValue(); if (auto* gradient = DynamicTo<cssvalue::CSSGradientValue>(image_css)) { BlendWithColorsFromGradient(gradient, colors, found_non_transparent_color,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 11af29ec..6682b45 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -745,12 +745,9 @@ uint64_t identifier, LocalFrame* frame, const ResourceRequest& request) { - String request_id = IdentifiersFactory::RequestId(loader, identifier); - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - auto value = std::make_unique<TracedValue>(); - value->SetString("requestId", request_id); + value->SetString("requestId", + IdentifiersFactory::RequestId(loader, identifier)); value->SetString("frame", IdentifiersFactory::FrameId(frame)); value->SetString("url", request.Url().GetString()); value->SetString("requestMethod", request.HttpMethod());
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc index 86d4bc7f..4783c5d 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -66,7 +66,7 @@ bool ComputeIsVisible(LayoutObject* target, const LayoutRect& rect) { DCHECK(RuntimeEnabledFeatures::IntersectionObserverV2Enabled()); if (target->GetDocument().GetFrame()->LocalFrameRoot().GetOcclusionState() != - kGuaranteedNotOccluded) { + FrameOcclusionState::kGuaranteedNotOccluded) { return false; } if (target->HasDistortingVisualEffects())
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index 029a4af2..a82d786c 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -56,7 +56,7 @@ // If we're tracking visibility, and we don't have occlusion information // from our parent frame, then postpone computing intersections until a // later lifecycle when the occlusion information is known. - if (occlusion_state == kUnknownOcclusionState) + if (occlusion_state == FrameOcclusionState::kUnknown) return; } last_run_time_ = timestamp;
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc index 9d633fe..77873f5 100644 --- a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
@@ -47,7 +47,7 @@ LayoutImageResource::Initialize(layout_object); if (style_image_->IsImageResource()) - cached_image_ = ToStyleFetchedImage(style_image_)->CachedImage(); + cached_image_ = To<StyleFetchedImage>(style_image_.Get())->CachedImage(); style_image_->AddClient(layout_object_); }
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index f9e1b70..7af7b06 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1352,7 +1352,7 @@ LayoutRect LayoutInline::LinesVisualOverflowBoundingBox() const { if (IsInLayoutNGInlineFormattingContext()) { NGPhysicalOffsetRect result; - NGPaintFragment::InlineFragemntsIncludingCulledFor( + NGPaintFragment::InlineFragmentsIncludingCulledFor( *this, [](NGPaintFragment* fragment, void* context) { NGPhysicalOffsetRect* result =
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index bf071c3..06db154 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -185,8 +185,7 @@ } LayoutTableSection* Header() const { - // TODO(mstensho): We should ideally DCHECK(!needsSectionRecalc()) here, but - // we currently cannot, due to crbug.com/693212 + DCHECK(!NeedsSectionRecalc()); return head_; } LayoutTableSection* Footer() const {
diff --git a/third_party/blink/renderer/core/layout/layout_theme_test.cc b/third_party/blink/renderer/core/layout/layout_theme_test.cc index 81adfc6..88cb960 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_test.cc +++ b/third_party/blink/renderer/core/layout/layout_theme_test.cc
@@ -6,9 +6,11 @@ #include <memory> #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/style_engine.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/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/page/page.h" @@ -88,7 +90,8 @@ Element* initial = GetDocument().getElementById("initial"); ASSERT_TRUE(initial); - EXPECT_EQ(ColorScheme::kLight, GetDocument().GetColorScheme()); + EXPECT_EQ(ColorScheme::kLight, + GetDocument().GetStyleEngine().GetColorScheme()); ASSERT_TRUE(GetDocument().documentElement()); const ComputedStyle* document_element_style = @@ -103,8 +106,11 @@ initial_style->VisitedDependentColor(GetCSSPropertyColor())); // Change color scheme to dark. - GetDocument().SetColorScheme(ColorScheme::kDark); - EXPECT_EQ(ColorScheme::kDark, GetDocument().GetColorScheme()); + GetDocument().GetSettings()->SetPreferredColorScheme( + PreferredColorScheme::kDark); + ColorSchemeSet supported_schemes; + supported_schemes.Set(ColorScheme::kDark); + GetDocument().GetStyleEngine().SetSupportedColorSchemes(supported_schemes); UpdateAllLifecyclePhasesForTest(); document_element_style = GetDocument().documentElement()->GetComputedStyle();
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc index 818ef3f..12a024e7 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -343,7 +343,7 @@ scoped_refptr<NGPaintFragment>* current = NGPaintFragment::Find(&paint_fragment_, break_token); DCHECK(current); - bool has_old = current->get(); + const NGPaintFragment* old = current->get(); if (fragment) { *current = NGPaintFragment::Create(std::move(fragment), break_token, std::move(*current)); @@ -351,8 +351,11 @@ *current = nullptr; } - if (has_old) { + if (old && old != current->get()) { // Painting layer needs repaint when a DisplayItemClient is destroyed. + // TODO(kojii): We need this here for now, but this should be handled + // differently for better efficiency, in pre-paint tree walk to walk + // fragment tree, or before layout. crbug.com/941228 ObjectPaintInvalidator(*this).SlowSetPaintingLayerNeedsRepaint(); } }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc index ed292d47..5d970f9 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc
@@ -72,7 +72,7 @@ Radius(attributes), 1, PlatformSpreadMethodFromSVGType(attributes.SpreadMethod()), Gradient::ColorInterpolation::kUnpremultiplied, - Gradient::DegenerateHandling::kDisallow); + Gradient::DegenerateHandling::kAllow); gradient->AddColorStops(attributes.Stops()); return gradient; }
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index d4289a86..ef54735 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -347,38 +347,29 @@ if (IsSVGImageChromeClient() && !url.ProtocolIsData()) return ResourceRequestBlockedReason::kOrigin; - network::mojom::RequestContextFrameType frame_type = - resource_request.GetFrameType(); - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, frame_type); - // Measure the number of legacy URL schemes ('ftp://') and the number of // embedded-credential ('http://user:password@...') resources embedded as // subresources. - if (frame_type != network::mojom::RequestContextFrameType::kTopLevel) { - bool is_subresource = - frame_type == network::mojom::RequestContextFrameType::kNone; - const FetchClientSettingsObject& fetch_client_settings_object = - GetResourceFetcherProperties().GetFetchClientSettingsObject(); - const SecurityOrigin* embedding_origin = - is_subresource ? fetch_client_settings_object.GetSecurityOrigin() - : GetParentSecurityOrigin(); - DCHECK(embedding_origin); - if (SchemeRegistry::ShouldTreatURLSchemeAsLegacy(url.Protocol()) && - !SchemeRegistry::ShouldTreatURLSchemeAsLegacy( - embedding_origin->Protocol())) { - CountDeprecation(WebFeature::kLegacyProtocolEmbeddedAsSubresource); + const FetchClientSettingsObject& fetch_client_settings_object = + GetResourceFetcherProperties().GetFetchClientSettingsObject(); + const SecurityOrigin* embedding_origin = + fetch_client_settings_object.GetSecurityOrigin(); + DCHECK(embedding_origin); + if (SchemeRegistry::ShouldTreatURLSchemeAsLegacy(url.Protocol()) && + !SchemeRegistry::ShouldTreatURLSchemeAsLegacy( + embedding_origin->Protocol())) { + CountDeprecation(WebFeature::kLegacyProtocolEmbeddedAsSubresource); - return ResourceRequestBlockedReason::kOrigin; - } - - if (ShouldBlockFetchAsCredentialedSubresource(resource_request, url)) - return ResourceRequestBlockedReason::kOrigin; + return ResourceRequestBlockedReason::kOrigin; } + if (ShouldBlockFetchAsCredentialedSubresource(resource_request, url)) + return ResourceRequestBlockedReason::kOrigin; + // Check for mixed content. We do this second-to-last so that when folks block // mixed content via CSP, they don't get a mixed content warning, but a CSP // warning instead. - if (ShouldBlockFetchByMixedContentCheck(request_context, frame_type, + if (ShouldBlockFetchByMixedContentCheck(request_context, resource_request.GetRedirectStatus(), url, reporting_policy)) return ResourceRequestBlockedReason::kMixedContent;
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h index f4d562c..31af7a8 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.h +++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -79,7 +79,6 @@ virtual bool IsSVGImageChromeClient() const = 0; virtual bool ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType, - network::mojom::RequestContextFrameType, ResourceRequest::RedirectStatus, const KURL&, SecurityViolationReportingPolicy) const = 0;
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc index fcaf048..f66849a 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -81,7 +81,6 @@ } bool ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType, - network::mojom::RequestContextFrameType, ResourceRequest::RedirectStatus, const KURL&, SecurityViolationReportingPolicy) const override {
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 2810703..421eb16 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -221,6 +221,15 @@ void UnregisterPopupOpeningObserver(PopupOpeningObserver*) override {} void NotifyPopupOpeningObservers() const override {} + void FallbackCursorModeLockCursor(LocalFrame* frame, + bool left, + bool right, + bool up, + bool down) override {} + + void FallbackCursorModeSetCursorVisibility(LocalFrame* frame, + bool visible) override {} + void SetCursorForPlugin(const WebCursorInfo&, LocalFrame*) override {} void InstallSupplements(LocalFrame&) override {}
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index e3ad178..f2a0f31a 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -315,7 +315,7 @@ // Reload should reflect the current data saver setting. if (IsReloadLoadType(MasterDocumentLoader()->LoadType())) - request.ClearHTTPHeaderField(http_names::kSaveData); + request.ClearHttpHeaderField(http_names::kSaveData); if (save_data_enabled_) request.SetHTTPHeaderField(http_names::kSaveData, "on"); @@ -504,11 +504,7 @@ *GetFrame(), &frame_or_imported_document_->GetDocument(), resource_loading_policy, PreloadHelper::kLoadAll, nullptr); - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - if (response.HasMajorCertificateErrors() && - request.GetFrameType() != - network::mojom::RequestContextFrameType::kTopLevel) { + if (response.HasMajorCertificateErrors()) { MixedContentChecker::HandleCertificateError(GetFrame(), response, request.GetRequestContext()); } @@ -679,8 +675,6 @@ } void FrameFetchContext::ModifyRequestForCSP(ResourceRequest& resource_request) { - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - resource_request.GetFrameType()); if (GetResourceFetcherProperties().IsDetached()) return; @@ -883,16 +877,8 @@ // Set the first party for cookies url if it has not been set yet (new // requests). This value will be updated during redirects, consistent with // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-2.1.1? - if (request.SiteForCookies().IsNull()) { - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - if (request.GetFrameType() == - network::mojom::RequestContextFrameType::kTopLevel) { - request.SetSiteForCookies(request.Url()); - } else { - request.SetSiteForCookies(GetSiteForCookies()); - } - } + if (request.SiteForCookies().IsNull()) + request.SetSiteForCookies(GetSiteForCookies()); } bool FrameFetchContext::AllowScriptFromSource(const KURL& url) const { @@ -999,7 +985,6 @@ bool FrameFetchContext::ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType request_context, - network::mojom::RequestContextFrameType frame_type, ResourceRequest::RedirectStatus redirect_status, const KURL& url, SecurityViolationReportingPolicy reporting_policy) const { @@ -1007,17 +992,13 @@ // TODO(yhirano): Implement the detached case. return false; } - return MixedContentChecker::ShouldBlockFetch(GetFrame(), request_context, - frame_type, redirect_status, url, - reporting_policy); + return MixedContentChecker::ShouldBlockFetch( + GetFrame(), request_context, redirect_status, url, reporting_policy); } bool FrameFetchContext::ShouldBlockFetchAsCredentialedSubresource( const ResourceRequest& resource_request, const KURL& url) const { - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - resource_request.GetFrameType()); - // URLs with no embedded credentials should load correctly. if (url.User().IsEmpty() && url.Pass().IsEmpty()) return false;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h index 5f7a38635..6b31d6d 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -186,7 +186,6 @@ override; bool ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType, - network::mojom::RequestContextFrameType, ResourceRequest::RedirectStatus, const KURL&, SecurityViolationReportingPolicy) const override;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc index 6393b35..9ca08af 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -1114,8 +1114,6 @@ DispatchDidLoadResourceFromMemoryCache( testing::AllOf( testing::Property(&ResourceRequest::Url, url), - testing::Property(&ResourceRequest::GetFrameType, - network::mojom::RequestContextFrameType::kNone), testing::Property(&ResourceRequest::GetRequestContext, mojom::RequestContextType::IMAGE)), testing::Property(&ResourceResponse::IsNull, true)));
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 5709c2f..7e97ab7 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -42,6 +42,7 @@ #include "base/unguessable_token.h" #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-shared.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" @@ -50,7 +51,6 @@ #include "third_party/blink/public/platform/web_mixed_content.h" #include "third_party/blink/public/platform/web_mixed_content_context_type.h" #include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/web/commit_result.mojom-shared.h" #include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/public/web/web_history_item.h" #include "third_party/blink/public/web/web_navigation_params.h"
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/third_party/blink/renderer/core/loader/mixed_content_checker.cc index 8bfa4eee..e9dd7c4e 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -200,11 +200,8 @@ } } -bool RequestIsSubframeSubresource( - Frame* frame, - network::mojom::RequestContextFrameType frame_type) { - return (frame && frame != frame->Tree().Top() && - frame_type != network::mojom::RequestContextFrameType::kNested); +bool RequestIsSubframeSubresource(Frame* frame) { + return frame && frame != frame->Tree().Top(); } static bool IsInsecureUrl(const KURL& url) { @@ -244,24 +241,19 @@ } // static -Frame* MixedContentChecker::InWhichFrameIsContentMixed( - Frame* frame, - network::mojom::RequestContextFrameType frame_type, - const KURL& url, - const LocalFrame* source) { - // We only care about subresource loads; top-level navigations cannot be mixed - // content. Neither can frameless requests. - if (frame_type == network::mojom::RequestContextFrameType::kTopLevel || - !frame) +Frame* MixedContentChecker::InWhichFrameIsContentMixed(LocalFrame* frame, + const KURL& url) { + // Frameless requests cannot be mixed content. + if (!frame) return nullptr; // Check the top frame first. Frame& top = frame->Tree().Top(); - MeasureStricterVersionOfIsMixedContent(top, url, source); + MeasureStricterVersionOfIsMixedContent(top, url, frame); if (IsMixedContent(top.GetSecurityContext()->GetSecurityOrigin(), url)) return ⊤ - MeasureStricterVersionOfIsMixedContent(*frame, url, source); + MeasureStricterVersionOfIsMixedContent(*frame, url, frame); if (IsMixedContent(frame->GetSecurityContext()->GetSecurityOrigin(), url)) return frame; @@ -351,18 +343,10 @@ bool MixedContentChecker::ShouldBlockFetch( LocalFrame* frame, mojom::RequestContextType request_context, - network::mojom::RequestContextFrameType frame_type, ResourceRequest::RedirectStatus redirect_status, const KURL& url, SecurityViolationReportingPolicy reporting_policy) { - // Frame-level loads are checked by the browser. No need to check them again - // here. - if (frame_type != network::mojom::RequestContextFrameType::kNone) - return false; - - Frame* effective_frame = EffectiveFrameForFrameType(frame, frame_type); - Frame* mixed_frame = - InWhichFrameIsContentMixed(effective_frame, frame_type, url, frame); + Frame* mixed_frame = InWhichFrameIsContentMixed(frame, url); if (!mixed_frame) return false; @@ -397,14 +381,6 @@ // look at the loaded URL. If we're dealing with a CORS-enabled scheme, then // block mixed frames as active content. Otherwise, treat frames as passive // content. - // - // FIXME: Remove this temporary hack once we have a reasonable API for - // launching external applications via URLs. http://crbug.com/318788 and - // https://crbug.com/393481 - if (frame_type == network::mojom::RequestContextFrameType::kNested && - !SchemeRegistry::ShouldTreatURLSchemeAsCorsEnabled(url.Protocol())) - context_type = WebMixedContentContextType::kOptionallyBlockable; - switch (context_type) { case WebMixedContentContextType::kOptionallyBlockable: allowed = !strict_mode; @@ -424,7 +400,7 @@ // https://a.com and not realizing that they are in fact allowing an // insecure script on https://b.com. if (!settings->GetAllowRunningOfInsecureContent() && - RequestIsSubframeSubresource(effective_frame, frame_type) && + RequestIsSubframeSubresource(frame) && IsMixedContent(frame->GetSecurityContext()->GetSecurityOrigin(), url)) { UseCounter::Count(frame->GetDocument(), @@ -559,8 +535,7 @@ const FrameFetchContext& frame_fetch_context, LocalFrame* frame, const KURL& url) { - Frame* mixed_frame = InWhichFrameIsContentMixed( - frame, network::mojom::RequestContextFrameType::kNone, url, frame); + Frame* mixed_frame = InWhichFrameIsContentMixed(frame, url); if (!mixed_frame) return true; @@ -636,8 +611,7 @@ if (url.ProtocolIs("javascript")) return false; - Frame* mixed_frame = InWhichFrameIsContentMixed( - frame, network::mojom::RequestContextFrameType::kNone, url, frame); + Frame* mixed_frame = InWhichFrameIsContentMixed(frame, url); if (!mixed_frame) return false; @@ -712,19 +686,6 @@ } } -Frame* MixedContentChecker::EffectiveFrameForFrameType( - LocalFrame* frame, - network::mojom::RequestContextFrameType frame_type) { - // If we're loading the main resource of a subframe, ensure that we check - // against the parent of the active frame, rather than the frame itself. - if (frame_type != network::mojom::RequestContextFrameType::kNested) - return frame; - - Frame* parent_frame = frame->Tree().Parent(); - DCHECK(parent_frame); - return parent_frame; -} - void MixedContentChecker::HandleCertificateError( LocalFrame* frame, const ResourceResponse& response, @@ -809,25 +770,10 @@ WebMixedContentContextType MixedContentChecker::ContextTypeForInspector( LocalFrame* frame, const ResourceRequest& request) { - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - Frame* effective_frame = - EffectiveFrameForFrameType(frame, request.GetFrameType()); - - Frame* mixed_frame = InWhichFrameIsContentMixed( - effective_frame, request.GetFrameType(), request.Url(), frame); + Frame* mixed_frame = InWhichFrameIsContentMixed(frame, request.Url()); if (!mixed_frame) return WebMixedContentContextType::kNotMixedContent; - // See comment in ShouldBlockFetch() about loading the main resource of a - // subframe. - if (request.GetFrameType() == - network::mojom::RequestContextFrameType::kNested && - !SchemeRegistry::ShouldTreatURLSchemeAsCorsEnabled( - request.Url().Protocol())) { - return WebMixedContentContextType::kOptionallyBlockable; - } - bool strict_mixed_content_checking_for_plugin = mixed_frame->GetSettings() && mixed_frame->GetSettings()->GetStrictMixedContentCheckingForPlugin();
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker.h b/third_party/blink/renderer/core/loader/mixed_content_checker.h index 4e0cad7..b615aaf56 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker.h +++ b/third_party/blink/renderer/core/loader/mixed_content_checker.h
@@ -69,7 +69,6 @@ public: static bool ShouldBlockFetch(LocalFrame*, mojom::RequestContextType, - network::mojom::RequestContextFrameType, ResourceRequest::RedirectStatus, const KURL&, SecurityViolationReportingPolicy = @@ -104,12 +103,6 @@ LocalFrame*, const ResourceRequest&); - // Returns the frame that should be considered the effective frame - // for a mixed content check for the given frame type. - static Frame* EffectiveFrameForFrameType( - LocalFrame*, - network::mojom::RequestContextFrameType); - static void HandleCertificateError(LocalFrame*, const ResourceResponse&, mojom::RequestContextType); @@ -134,11 +127,7 @@ private: FRIEND_TEST_ALL_PREFIXES(MixedContentCheckerTest, HandleCertificateError); - static Frame* InWhichFrameIsContentMixed( - Frame*, - network::mojom::RequestContextFrameType, - const KURL&, - const LocalFrame*); + static Frame* InWhichFrameIsContentMixed(LocalFrame*, const KURL&); static ConsoleMessage* CreateConsoleMessageAboutFetch( const KURL&,
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc index ee3cbf4..d42a72b 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker_test.cc
@@ -194,14 +194,12 @@ // Test that a mixed content favicon is correctly blocked. EXPECT_TRUE(MixedContentChecker::ShouldBlockFetch( &dummy_page_holder->GetFrame(), mojom::RequestContextType::FAVICON, - network::mojom::RequestContextFrameType::kNone, ResourceRequest::RedirectStatus::kNoRedirect, http_favicon_url, SecurityViolationReportingPolicy::kSuppressReporting)); // Test that a secure favicon is not blocked. EXPECT_FALSE(MixedContentChecker::ShouldBlockFetch( &dummy_page_holder->GetFrame(), mojom::RequestContextType::FAVICON, - network::mojom::RequestContextFrameType::kNone, ResourceRequest::RedirectStatus::kNoRedirect, https_favicon_url, SecurityViolationReportingPolicy::kSuppressReporting)); }
diff --git a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc index 07963eb..f232980 100644 --- a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
@@ -45,8 +45,6 @@ CSSStyleSheetResource* CSSStyleSheetResource::Fetch(FetchParameters& params, ResourceFetcher* fetcher, ResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); params.SetRequestContext(mojom::RequestContextType::STYLE); CSSStyleSheetResource* resource = ToCSSStyleSheetResource( fetcher->RequestResource(params, CSSStyleSheetResourceFactory(), client));
diff --git a/third_party/blink/renderer/core/loader/resource/document_resource.cc b/third_party/blink/renderer/core/loader/resource/document_resource.cc index 446eaacd..7de90d0 100644 --- a/third_party/blink/renderer/core/loader/resource/document_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/document_resource.cc
@@ -36,8 +36,6 @@ DocumentResource* DocumentResource::FetchSVGDocument(FetchParameters& params, ResourceFetcher* fetcher, ResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); DCHECK_EQ(params.GetResourceRequest().GetFetchRequestMode(), network::mojom::FetchRequestMode::kSameOrigin); params.SetRequestContext(mojom::RequestContextType::IMAGE);
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource.cc b/third_party/blink/renderer/core/loader/resource/font_resource.cc index 62ea94e..4a1561c 100644 --- a/third_party/blink/renderer/core/loader/resource/font_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/font_resource.cc
@@ -78,8 +78,6 @@ FontResource* FontResource::Fetch(FetchParameters& params, ResourceFetcher* fetcher, FontResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); params.SetRequestContext(mojom::RequestContextType::FONT); return ToFontResource( fetcher->RequestResource(params, FontResourceFactory(), client));
diff --git a/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc b/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc index e50ee7a..a94ef7b2 100644 --- a/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/link_fetch_resource.cc
@@ -14,8 +14,6 @@ FetchParameters& params, ResourceFetcher* fetcher) { DCHECK_EQ(type, ResourceType::kLinkPrefetch); - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); return fetcher->RequestResource(params, LinkResourceFactory(type), nullptr); }
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc index 84f5e8e3..4d14780 100644 --- a/third_party/blink/renderer/core/loader/resource/script_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -35,10 +35,13 @@ #include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h" +#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" #include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h" +#include "third_party/blink/renderer/platform/loader/fetch/response_body_loader.h" #include "third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h" #include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h" #include "third_party/blink/renderer/platform/loader/subresource_integrity.h" @@ -75,8 +78,6 @@ ResourceFetcher* fetcher, ResourceClient* client, StreamingAllowed streaming_allowed) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); DCHECK(IsRequestContextSupported( params.GetResourceRequest().GetRequestContext())); ScriptResource* resource = ToScriptResource( @@ -118,8 +119,17 @@ ScriptResource::~ScriptResource() = default; +void ScriptResource::Prefinalize() { + // Reset and cancel the watcher. This has to be called in the prefinalizer, + // rather than relying on the destructor, as accesses by the watcher of the + // script resource between prefinalization and destruction are invalid. See + // https://crbug.com/905975#c34 for more details. + watcher_.reset(); +} + void ScriptResource::Trace(blink::Visitor* visitor) { visitor->Trace(streamer_); + visitor->Trace(response_body_loader_client_); TextResource::Trace(visitor); } @@ -238,13 +248,93 @@ return Resource::CanUseCacheValidator(); } -void ScriptResource::NotifyDataReceived(const char* data, size_t size) { +void ScriptResource::ResponseBodyReceived( + ResponseBodyLoaderDrainableInterface& body_loader) { + ResponseBodyLoaderClient* response_body_loader_client; + CHECK(!data_pipe_); + data_pipe_ = body_loader.DrainAsDataPipe(&response_body_loader_client); + if (!data_pipe_) + return; + + response_body_loader_client_ = response_body_loader_client; + watcher_ = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, + Loader()->GetLoadingTaskRunner()); + + watcher_->Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_READABLE, + MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, + WTF::BindRepeating(&ScriptResource::OnDataPipeReadable, + WrapWeakPersistent(this))); + CHECK(data_pipe_); + watcher_->ArmOrNotify(); +} + +void ScriptResource::OnDataPipeReadable(MojoResult result, + const mojo::HandleSignalsState& state) { + switch (result) { + case MOJO_RESULT_OK: + // All good, so read the data that we were notified that we received. + break; + + case MOJO_RESULT_CANCELLED: + // The consumer handle got closed, which means this script resource is + // done loading, and did so without streaming (otherwise the watcher + // wouldn't have been armed, and the handle ownership would have passed to + // the streamer). + CHECK(streaming_state_ == StreamingState::kFinishedNotificationSent || + streaming_state_ == StreamingState::kStreamingNotAllowed); + return; + + case MOJO_RESULT_FAILED_PRECONDITION: + // This means the producer finished and streamed to completion. + watcher_.reset(); + response_body_loader_client_->DidFinishLoadingBody(); + return; + + case MOJO_RESULT_SHOULD_WAIT: + NOTREACHED(); + return; + + default: + // Some other error occurred. + watcher_.reset(); + response_body_loader_client_->DidFailLoadingBody(); + return; + } + CHECK(state.readable()); + CHECK(data_pipe_); + + const void* data; + uint32_t data_size; + MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE; + MojoResult begin_read_result = + data_pipe_->BeginReadData(&data, &data_size, flags_to_pass); + // There should be data, so this read should succeed. + CHECK_EQ(begin_read_result, MOJO_RESULT_OK); + + response_body_loader_client_->DidReceiveData( + base::make_span(reinterpret_cast<const char*>(data), data_size)); + + MojoResult end_read_result = data_pipe_->EndReadData(data_size); + + CHECK_EQ(end_read_result, MOJO_RESULT_OK); + CheckStreamingState(); if (streamer_) { DCHECK_EQ(streaming_state_, StreamingState::kStreaming); - streamer_->NotifyAppendData(); + if (streamer_->TryStartStreaming(&data_pipe_, + response_body_loader_client_.Get())) { + CHECK(!data_pipe_); + // This reset will also cancel the watcher. + watcher_.reset(); + return; + } } - TextResource::NotifyDataReceived(data, size); + + // TODO(leszeks): Depending on how small the chunks are, we may want to + // loop until a certain number of bytes are synchronously read rather than + // going back to the scheduler. + watcher_->ArmOrNotify(); } void ScriptResource::NotifyFinished() { @@ -265,6 +355,8 @@ // call) break; case StreamingState::kStreamingNotAllowed: + watcher_.reset(); + data_pipe_.reset(); AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); break; @@ -284,6 +376,11 @@ void ScriptResource::StreamingFinished() { CHECK(streamer_); CHECK_EQ(streaming_state_, StreamingState::kWaitingForStreamingToEnd); + CHECK(!data_pipe_ || streamer_->StreamingSuppressed()); + // We may still have a watcher if a) streaming never started (e.g. script too + // small) and b) an external error triggered the finished notification. + watcher_.reset(); + data_pipe_.reset(); AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); } @@ -323,7 +420,16 @@ // Note that we don't need to iterate through the segments of the data, as // the streamer will do that itself. CHECK_GT(Data()->size(), 0u); - streamer_->NotifyAppendData(); + if (data_pipe_) { + if (streamer_->TryStartStreaming(&data_pipe_, + response_body_loader_client_.Get())) { + CHECK(!data_pipe_); + // This reset will also cancel the watcher. + watcher_.reset(); + } else { + CHECK(data_pipe_); + } + } } // If the we're is already loaded, notify the streamer about that too. if (IsLoaded()) { @@ -354,6 +460,8 @@ not_streaming_reason_ = ScriptStreamer::kStreamingDisabled; // Trigger the finished notification if needed. if (IsLoaded()) { + CHECK(!watcher_ || !watcher_->IsWatching()); + data_pipe_.reset(); AdvanceStreamingState(StreamingState::kFinishedNotificationSent); TextResource::NotifyFinished(); } @@ -425,6 +533,8 @@ break; case StreamingState::kFinishedNotificationSent: CHECK(!streamer_ || streamer_->IsFinished()); + CHECK(!watcher_ || !watcher_->IsWatching()); + CHECK(!data_pipe_); CHECK(IsLoaded()); break; }
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.h b/third_party/blink/renderer/core/loader/resource/script_resource.h index 75d1028..9ed6d69 100644 --- a/third_party/blink/renderer/core/loader/resource/script_resource.h +++ b/third_party/blink/renderer/core/loader/resource/script_resource.h
@@ -42,6 +42,7 @@ class FetchParameters; class KURL; class ResourceFetcher; +class ResponseBodyLoaderClient; // ScriptResource is a resource representing a JavaScript script. It is only // used for "classic" scripts, i.e. not modules. @@ -54,6 +55,8 @@ // See also: // https://docs.google.com/document/d/143GOPl_XVgLPFfO-31b_MdBcnjklLEX2OIg_6eN6fQ4 class CORE_EXPORT ScriptResource final : public TextResource { + USING_PRE_FINALIZER(ScriptResource, Prefinalize); + public: // For scripts fetched with kAllowStreaming, the ScriptResource expects users // to call StartStreaming to start streaming the loaded data, and @@ -90,6 +93,9 @@ const TextResourceDecoderOptions&); ~ScriptResource() override; + void ResponseBodyReceived( + ResponseBodyLoaderDrainableInterface& body_loader) override; + void Trace(blink::Visitor*) override; void OnMemoryDump(WebMemoryDumpLevelOfDetail, @@ -155,8 +161,6 @@ void DestroyDecodedDataForFailedRevalidation() override; - void NotifyDataReceived(const char* data, size_t size) override; - // ScriptResources are considered finished when either: // 1. Loading + streaming completes, or // 2. Loading completes + streaming was never started + someone called @@ -193,6 +197,8 @@ } }; + void Prefinalize(); + bool CanUseCacheValidator() const override; void AdvanceStreamingState(StreamingState new_state); @@ -200,7 +206,15 @@ // Check that invariants for the state hold. void CheckStreamingState() const; + void OnDataPipeReadable(MojoResult result, + const mojo::HandleSignalsState& state); + ParkableString source_text_; + + mojo::ScopedDataPipeConsumerHandle data_pipe_; + std::unique_ptr<mojo::SimpleWatcher> watcher_; + Member<ResponseBodyLoaderClient> response_body_loader_client_; + Member<ScriptStreamer> streamer_; ScriptStreamer::NotStreamingReason not_streaming_reason_ = ScriptStreamer::kDidntTryToStartStreaming;
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc index 22996cb..ce2662b 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -137,7 +137,6 @@ bool WorkerFetchContext::ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType request_context, - network::mojom::RequestContextFrameType frame_type, ResourceRequest::RedirectStatus redirect_status, const KURL& url, SecurityViolationReportingPolicy reporting_policy) const {
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h index da3b64ce7..71c8b580 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.h +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -60,7 +60,6 @@ override; bool ShouldBlockFetchByMixedContentCheck( mojom::RequestContextType, - network::mojom::RequestContextFrameType, ResourceRequest::RedirectStatus, const KURL&, SecurityViolationReportingPolicy) const override;
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index aa32a5d3..27c80c3 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -4,7 +4,10 @@ #include "third_party/blink/renderer/core/messaging/blink_transferable_message.h" +#include <utility> +#include "mojo/public/cpp/base/big_buffer.h" #include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/platform/blob/blob_data.h" namespace blink { @@ -17,6 +20,38 @@ BlinkTransferableMessage& BlinkTransferableMessage::operator=( BlinkTransferableMessage&&) = default; +scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage( + const SkBitmap& sk_bitmap) { + auto handle = WTF::ArrayBufferContents::CreateDataHandle( + sk_bitmap.computeByteSize(), WTF::ArrayBufferContents::kZeroInitialize); + if (!handle) + return nullptr; + + WTF::ArrayBufferContents array_buffer_contents( + std::move(handle), WTF::ArrayBufferContents::kNotShared); + if (!array_buffer_contents.Data()) + return nullptr; + + SkImageInfo info = sk_bitmap.info(); + if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(), + info.minRowBytes(), 0, 0)) + return nullptr; + + return blink::StaticBitmapImage::Create(array_buffer_contents, info); +} + +base::Optional<SkBitmap> ToSkBitmap( + const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image) { + const sk_sp<SkImage> image = + static_bitmap_image->PaintImageForCurrentFrame().GetSkImage(); + SkBitmap result; + if (image && image->asLegacyBitmap( + &result, SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode)) { + return result; + } + return base::nullopt; +} + BlinkTransferableMessage ToBlinkTransferableMessage( TransferableMessage message) { BlinkTransferableMessage result; @@ -47,6 +82,43 @@ message.user_activation->was_active); } result.transfer_user_activation = message.transfer_user_activation; + + if (!message.array_buffer_contents_array.empty()) { + SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array; + array_buffer_contents_array.ReserveInitialCapacity( + base::checked_cast<wtf_size_t>( + message.array_buffer_contents_array.size())); + + for (auto& item : message.array_buffer_contents_array) { + mojo_base::BigBuffer& big_buffer = item->contents; + auto handle = WTF::ArrayBufferContents::CreateDataHandle( + big_buffer.size(), WTF::ArrayBufferContents::kZeroInitialize); + WTF::ArrayBufferContents contents(std::move(handle), + WTF::ArrayBufferContents::kNotShared); + memcpy(contents.Data(), big_buffer.data(), big_buffer.size()); + array_buffer_contents_array.push_back(std::move(contents)); + } + result.message->SetArrayBufferContentsArray( + std::move(array_buffer_contents_array)); + } + + if (!message.image_bitmap_contents_array.empty()) { + SerializedScriptValue::ImageBitmapContentsArray image_bitmap_contents_array; + image_bitmap_contents_array.ReserveInitialCapacity( + base::checked_cast<wtf_size_t>( + message.image_bitmap_contents_array.size())); + + for (auto& sk_bitmap : message.image_bitmap_contents_array) { + const scoped_refptr<StaticBitmapImage> bitmap_contents = + ToStaticBitmapImage(sk_bitmap); + if (!bitmap_contents) + continue; + image_bitmap_contents_array.push_back(bitmap_contents); + } + result.message->SetImageBitmapContentsArray( + std::move(image_bitmap_contents_array)); + } + return result; } @@ -78,6 +150,30 @@ message.user_activation->was_active); } result.transfer_user_activation = message.transfer_user_activation; + + auto& array_buffer_contents_array = + message.message->GetArrayBufferContentsArray(); + result.array_buffer_contents_array.reserve( + array_buffer_contents_array.size()); + for (auto& contents : array_buffer_contents_array) { + uint8_t* allocation_start = static_cast<uint8_t*>(contents.Data()); + mojo_base::BigBuffer buffer( + base::make_span(allocation_start, contents.DataLength())); + result.array_buffer_contents_array.push_back( + mojom::SerializedArrayBufferContents::New(std::move(buffer))); + } + + auto& image_bitmap_contents_array = + message.message->GetImageBitmapContentsArray(); + result.image_bitmap_contents_array.reserve( + image_bitmap_contents_array.size()); + for (auto& contents : image_bitmap_contents_array) { + base::Optional<SkBitmap> bitmap = ToSkBitmap(contents); + if (!bitmap) + continue; + result.image_bitmap_contents_array.push_back(std::move(bitmap.value())); + } + return result; }
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.h b/third_party/blink/renderer/core/messaging/blink_transferable_message.h index 06e4b05d..b1ca9705 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.h +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.h
@@ -39,6 +39,12 @@ DISALLOW_COPY_AND_ASSIGN(BlinkTransferableMessage); }; +CORE_EXPORT scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage( + const SkBitmap& sk_bitmap); + +CORE_EXPORT base::Optional<SkBitmap> ToSkBitmap( + const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image); + CORE_EXPORT BlinkTransferableMessage ToBlinkTransferableMessage(TransferableMessage); // Returned message will still be backed by the SerializedScriptValue in the
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc index b855cd7..180fe59 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
@@ -10,39 +10,6 @@ namespace mojo { -namespace { - -scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage( - const SkBitmap& sk_bitmap) { - auto handle = WTF::ArrayBufferContents::CreateDataHandle( - sk_bitmap.computeByteSize(), WTF::ArrayBufferContents::kZeroInitialize); - if (!handle) - return nullptr; - - WTF::ArrayBufferContents array_buffer_contents( - std::move(handle), WTF::ArrayBufferContents::kNotShared); - if (!array_buffer_contents.Data()) - return nullptr; - - SkImageInfo info = sk_bitmap.info(); - if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(), - info.minRowBytes(), 0, 0)) - return nullptr; - - return blink::StaticBitmapImage::Create(array_buffer_contents, info); -} - -bool ToSkBitmap( - const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image, - SkBitmap& dest) { - const sk_sp<SkImage> image = - static_bitmap_image->PaintImageForCurrentFrame().GetSkImage(); - return image && image->asLegacyBitmap( - &dest, SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode); -} - -} // namespace - Vector<SkBitmap> StructTraits<blink::mojom::blink::TransferableMessage::DataView, blink::BlinkTransferableMessage>:: @@ -51,11 +18,11 @@ out.ReserveInitialCapacity( input.message->GetImageBitmapContentsArray().size()); for (auto& bitmap_contents : input.message->GetImageBitmapContentsArray()) { - SkBitmap bitmap; - if (!ToSkBitmap(bitmap_contents, bitmap)) { + base::Optional<SkBitmap> bitmap = blink::ToSkBitmap(bitmap_contents); + if (!bitmap) { return Vector<SkBitmap>(); } - out.push_back(std::move(bitmap)); + out.push_back(std::move(bitmap.value())); } return out; } @@ -97,7 +64,7 @@ image_bitmap_contents_array; for (auto& sk_bitmap : sk_bitmaps) { const scoped_refptr<blink::StaticBitmapImage> bitmap_contents = - ToStaticBitmapImage(sk_bitmap); + blink::ToStaticBitmapImage(sk_bitmap); if (!bitmap_contents) { return false; }
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 0557ac8..ae3970a9 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -384,6 +384,15 @@ std::move(callback).Run(false); } + virtual void FallbackCursorModeLockCursor(LocalFrame* frame, + bool left, + bool right, + bool up, + bool down) = 0; + + virtual void FallbackCursorModeSetCursorVisibility(LocalFrame* frame, + bool visible) = 0; + virtual void Trace(blink::Visitor*); protected:
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 6980c49..513ee0d 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -903,6 +903,15 @@ web_frame->LocalRootFrameWidget()->RequestDecode(image, std::move(callback)); } +void ChromeClientImpl::FallbackCursorModeLockCursor(LocalFrame* frame, + bool left, + bool right, + bool up, + bool down) {} + +void ChromeClientImpl::FallbackCursorModeSetCursorVisibility(LocalFrame* frame, + bool visible) {} + void ChromeClientImpl::SetEventListenerProperties( LocalFrame* frame, cc::EventListenerClass event_class,
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h index 61633e6e..f6b8fc9 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.h +++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -250,6 +250,15 @@ // WebWidget is closed. void SetClosed() { closed_ = true; } + void FallbackCursorModeLockCursor(LocalFrame* frame, + bool left, + bool right, + bool up, + bool down) override; + + void FallbackCursorModeSetCursorVisibility(LocalFrame* frame, + bool visible) override; + private: bool IsChromeClientImpl() const override { return true; }
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index dc2b8fa..ca943ff 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -700,6 +700,13 @@ } break; } + case SettingsDelegate::kColorSchemeChange: + for (Frame* frame = MainFrame(); frame; + frame = frame->Tree().TraverseNext()) { + if (auto* local_frame = DynamicTo<LocalFrame>(frame)) + local_frame->GetDocument()->GetStyleEngine().ColorSchemeChanged(); + } + break; } }
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/third_party/blink/renderer/core/page/pointer_lock_controller.cc index 7ac1e69..2ee21d9 100644 --- a/third_party/blink/renderer/core/page/pointer_lock_controller.cc +++ b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -118,6 +118,15 @@ void PointerLockController::DidAcquirePointerLock() { EnqueueEvent(event_type_names::kPointerlockchange, element_.Get()); lock_pending_ = false; + if (element_) { + LocalFrame* frame = element_->GetDocument().GetFrame(); + pointer_lock_position_ = frame->LocalFrameRoot() + .GetEventHandler() + .LastKnownMousePositionInRootFrame(); + pointer_lock_screen_position_ = frame->LocalFrameRoot() + .GetEventHandler() + .LastKnownMouseScreenPosition(); + } } void PointerLockController::DidNotAcquirePointerLock() { @@ -159,6 +168,17 @@ } } +void PointerLockController::GetPointerLockPosition( + FloatPoint* lock_position, + FloatPoint* lock_screen_position) { + if (element_ && !lock_pending_) { + DCHECK(lock_position); + DCHECK(lock_screen_position); + *lock_position = pointer_lock_position_; + *lock_screen_position = pointer_lock_screen_position_; + } +} + void PointerLockController::ClearElement() { lock_pending_ = false; element_ = nullptr;
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.h b/third_party/blink/renderer/core/page/pointer_lock_controller.h index 681c3e4..f4595e423 100644 --- a/third_party/blink/renderer/core/page/pointer_lock_controller.h +++ b/third_party/blink/renderer/core/page/pointer_lock_controller.h
@@ -29,6 +29,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/geometry/float_point.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -39,6 +40,8 @@ class Page; class WebMouseEvent; +// This class handles mouse pointer lock and unlock, and dispatching mouse +// events when locked. See: https://w3c.github.io/pointerlock class CORE_EXPORT PointerLockController final : public GarbageCollected<PointerLockController> { public: @@ -61,6 +64,10 @@ const Vector<WebMouseEvent>& predicted_events, const AtomicString& event_type); + // Fetch the locked mouse position when pointer is locked. The values are not + // changed if pointer is not locked. + void GetPointerLockPosition(FloatPoint* lock_position, + FloatPoint* lock_screen_position); void Trace(blink::Visitor*); private: @@ -73,6 +80,11 @@ Member<Element> element_; Member<Document> document_of_removed_element_while_waiting_for_unlock_; + // Store the locked position so that the event position keeps unchanged when + // in locked states. These values only get set when entering lock states. + FloatPoint pointer_lock_position_; + FloatPoint pointer_lock_screen_position_; + DISALLOW_COPY_AND_ASSIGN(PointerLockController); };
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc index 16d6abf0..7d8214d 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -318,6 +318,9 @@ if (layer->GetLayoutObject().IsVideo()) info.is_under_video = true; + + if (layer->GetLayoutObject().IsStickyPositioned()) + info.is_under_position_sticky = true; } void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs( @@ -348,13 +351,21 @@ RoundedIntSize(root_layer_->GetScrollableArea()->GetScrollOffset())); } + // For sticky-positioned elements, the scroll offset is sometimes included and + // sometimes not, depending on whether the sticky element is affixed or still + // scrolling. This makes caching difficult, as compared to Fixed position + // elements which have consistent behavior. So we disable caching for + // sticky-positioned subtrees. + ClipRectsCacheSlot cache_slot = info.is_under_position_sticky + ? kUncachedClipRects + : kAbsoluteClipRectsIgnoringViewportClip; + ClipRect clip_rect; layer->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) .CalculateBackgroundClipRect( ClipRectsContext(root_layer_, &root_layer_->GetLayoutObject().FirstFragment(), - kAbsoluteClipRectsIgnoringViewportClip, - kIgnorePlatformOverlayScrollbarSize, + cache_slot, kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClipAndScroll), clip_rect); IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect()); @@ -402,6 +413,7 @@ properties.scroll_parent = info.scrolling_ancestor; properties.is_under_video = info.is_under_video; + properties.is_under_position_sticky = info.is_under_position_sticky; layer->UpdateAncestorDependentCompositingInputs(properties); }
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h index 86574662..3393699 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -62,6 +62,7 @@ bool needs_reparent_scroll_for_fixed = false; bool is_under_video = false; + bool is_under_position_sticky = false; }; void UpdateSelfAndDescendantsRecursively(PaintLayer*,
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/third_party/blink/renderer/core/paint/filter_effect_builder.cc index 3dd4e661..09bc30c8 100644 --- a/third_party/blink/renderer/core/paint/filter_effect_builder.cc +++ b/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -159,14 +159,14 @@ } case FilterOperation::GRAYSCALE: { Vector<float> input_parameters = GrayscaleMatrix( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount()); + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount()); effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX, input_parameters); break; } case FilterOperation::SEPIA: { Vector<float> input_parameters = SepiaMatrix( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount()); + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount()); effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX, input_parameters); break; @@ -174,7 +174,7 @@ case FilterOperation::SATURATE: { Vector<float> input_parameters; input_parameters.push_back(clampTo<float>( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount())); + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount())); effect = FEColorMatrix::Create( parent_filter, FECOLORMATRIX_TYPE_SATURATE, input_parameters); break; @@ -182,14 +182,14 @@ case FilterOperation::HUE_ROTATE: { Vector<float> input_parameters; input_parameters.push_back(clampTo<float>( - ToBasicColorMatrixFilterOperation(filter_operation)->Amount())); + To<BasicColorMatrixFilterOperation>(filter_operation)->Amount())); effect = FEColorMatrix::Create( parent_filter, FECOLORMATRIX_TYPE_HUEROTATE, input_parameters); break; } case FilterOperation::INVERT: { BasicComponentTransferFilterOperation* component_transfer_operation = - ToBasicComponentTransferFilterOperation(filter_operation); + To<BasicComponentTransferFilterOperation>(filter_operation); ComponentTransferFunction transfer_function; transfer_function.type = FECOMPONENTTRANSFER_TYPE_TABLE; Vector<float> transfer_parameters; @@ -211,7 +211,7 @@ Vector<float> transfer_parameters; transfer_parameters.push_back(0); transfer_parameters.push_back(clampTo<float>( - ToBasicComponentTransferFilterOperation(filter_operation) + To<BasicComponentTransferFilterOperation>(filter_operation) ->Amount())); transfer_function.table_values = transfer_parameters; @@ -225,7 +225,7 @@ ComponentTransferFunction transfer_function; transfer_function.type = FECOMPONENTTRANSFER_TYPE_LINEAR; transfer_function.slope = clampTo<float>( - ToBasicComponentTransferFilterOperation(filter_operation) + To<BasicComponentTransferFilterOperation>(filter_operation) ->Amount()); transfer_function.intercept = 0; @@ -239,7 +239,7 @@ ComponentTransferFunction transfer_function; transfer_function.type = FECOMPONENTTRANSFER_TYPE_LINEAR; float amount = clampTo<float>( - ToBasicComponentTransferFilterOperation(filter_operation) + To<BasicComponentTransferFilterOperation>(filter_operation) ->Amount()); transfer_function.slope = amount; transfer_function.intercept = -0.5 * amount + 0.5; @@ -325,7 +325,7 @@ case FilterOperation::SEPIA: case FilterOperation::SATURATE: case FilterOperation::HUE_ROTATE: { - float amount = ToBasicColorMatrixFilterOperation(*op).Amount(); + float amount = To<BasicColorMatrixFilterOperation>(*op).Amount(); switch (op->GetType()) { case FilterOperation::GRAYSCALE: filters.AppendGrayscaleFilter(amount); @@ -348,7 +348,7 @@ case FilterOperation::OPACITY: case FilterOperation::BRIGHTNESS: case FilterOperation::CONTRAST: { - float amount = ToBasicComponentTransferFilterOperation(*op).Amount(); + float amount = To<BasicComponentTransferFilterOperation>(*op).Amount(); switch (op->GetType()) { case FilterOperation::INVERT: filters.AppendInvertFilter(amount);
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index 32617043..de058c6 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -51,7 +51,7 @@ StyleImage* bg_image = bg_layer->GetImage(); if (!bg_image || !bg_image->IsImageResource()) continue; - const StyleFetchedImage* fetched_image = ToStyleFetchedImage(bg_image); + const StyleFetchedImage* fetched_image = To<StyleFetchedImage>(bg_image); const String url = fetched_image->Url().StrippedForUseAsReferrer(); concatenated_result.Append(url.Utf8().data(), url.length()); }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index e440c62..9d623df 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -464,7 +464,7 @@ return FragmentRange(nullptr, false); } -void NGPaintFragment::InlineFragemntsIncludingCulledFor( +void NGPaintFragment::InlineFragmentsIncludingCulledFor( const LayoutObject& layout_object, Callback callback, void* context) { @@ -482,7 +482,12 @@ ToLayoutInlineOrNull(&layout_object)) { for (LayoutObject* child = layout_inline->FirstChild(); child; child = child->NextSibling()) { - InlineFragemntsIncludingCulledFor(*child, callback, context); + // |layout_inline| may still have non-inline children, e.g., + // 'position:absolute'. Skip them as they don't contribute to the culled + // rects of |layout_inline|. + if (!child->IsInline()) + continue; + InlineFragmentsIncludingCulledFor(*child, callback, context); } } }
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h index 48a4d3d..04ef80a 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -264,7 +264,7 @@ // Same as |InlineFragmentsFor()| but this function includes descendants if // the |layout_object| is culled (i.e., did not generate fragments.) typedef void (*Callback)(NGPaintFragment*, void*); - static void InlineFragemntsIncludingCulledFor(const LayoutObject&, + static void InlineFragmentsIncludingCulledFor(const LayoutObject&, Callback callback, void* context);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 7d619ac..dcd77467 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -762,6 +762,7 @@ const LayoutBoxModelObject* clipping_container = nullptr; bool is_under_video = false; + bool is_under_position_sticky = false; }; void SetNeedsVisualOverflowRecalc(); void SetNeedsCompositingInputsUpdate();
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc index b068340..3e738351 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -1031,4 +1031,92 @@ } } +TEST_F(PaintLayerClipperTest, + StickyLayerClipRectInDocumentSpaceWithNestedScroller) { + SetBodyInnerHTML(R"HTML( + <div style="width:200px; height:200px;"></div> + <div style="position:sticky; left:100px; top:100px; width:300px; height:400px; overflow:scroll;"> + <div style="width:200px; height:300px; overflow:hidden;"> + <div id="target" style="position:relative;"></div> + </div> + <div style="height:3000px;"></div> + </div> + <div style="height:3000px;"></div> + )HTML"); + + Element* target = GetDocument().getElementById("target"); + PaintLayer* target_layer = + ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); + + // At 10, target is still scrolling - clip_rect shouldn't change. + GetDocument().domWindow()->scrollTo(0, 10); + GetDocument() + .GetLayoutView() + ->Layer() + ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) + .ClearClipRectsIncludingDescendants(); + + { + ClipRect clip_rect; + target_layer + ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) + .CalculateBackgroundClipRect( + ClipRectsContext(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, + kIgnorePlatformOverlayScrollbarSize, + kIgnoreOverflowClipAndScroll), + clip_rect); + EXPECT_EQ(LayoutRect(100, 208, 200, 300), clip_rect.Rect()); + } + + // At 50, target is still scrolling - clip_rect shouldn't change. + GetDocument().domWindow()->scrollTo(0, 50); + { + ClipRect clip_rect; + target_layer + ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) + .CalculateBackgroundClipRect( + ClipRectsContext(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, + kIgnorePlatformOverlayScrollbarSize, + kIgnoreOverflowClipAndScroll), + clip_rect); + EXPECT_EQ(LayoutRect(100, 208, 200, 300), clip_rect.Rect()); + } + + // At 150, target is fixed - clip_rect should now increase. + GetDocument().domWindow()->scrollTo(0, 150); + { + ClipRect clip_rect; + target_layer + ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) + .CalculateBackgroundClipRect( + ClipRectsContext(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, + kIgnorePlatformOverlayScrollbarSize, + kIgnoreOverflowClipAndScroll), + clip_rect); + EXPECT_EQ(LayoutRect(100, 250, 200, 300), clip_rect.Rect()); + } + + // At 250, target is still fixed - clip_rect should keep increasing. + GetDocument().domWindow()->scrollTo(0, 250); + { + ClipRect clip_rect; + target_layer + ->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper) + .CalculateBackgroundClipRect( + ClipRectsContext(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, + kIgnorePlatformOverlayScrollbarSize, + kIgnoreOverflowClipAndScroll), + clip_rect); + EXPECT_EQ(LayoutRect(100, 350, 200, 300), clip_rect.Rect()); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 981edef..a10bef0 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -624,6 +624,10 @@ object.StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden) return true; + // TODO(crbug.com/900241): Currently kDirectReasonsForTransformProperty + // includes all will-change compositing hints including opacity. This is + // needed to avoid creating/deleting transform nodes on start/end of an + // opacity animation. https://crbug.com/942681 if (direct_compositing_reasons & CompositingReason::kDirectReasonsForTransformProperty) return true; @@ -739,10 +743,18 @@ static CompositingReasons CompositingReasonsForEffectProperty() { // TODO(crbug.com/900241): See the comment in compositing_reasons.h about // the bug for the reason of this. - return RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || - RuntimeEnabledFeatures::CompositeAfterPaintEnabled() - ? CompositingReason::kDirectReasonsForEffectProperty - : CompositingReason::kActiveOpacityAnimation; + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + return CompositingReason::kDirectReasonsForEffectProperty; + } + // We also need to create effect node if the transform node is created for + // will-change to avoid raster invalidation (caused by otherwise a created/ + // deleted effect node) when we start/stop a transform animation. + // https://crbug.com/942681 + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + return CompositingReason::kDirectReasonsForEffectProperty | + CompositingReason::kWillChangeCompositingHint; + } + return CompositingReason::kActiveOpacityAnimation; } static bool NeedsEffect(const LayoutObject& object, @@ -1037,10 +1049,18 @@ static CompositingReasons CompositingReasonsForFilterProperty() { // TODO(crbug.com/900241): See the comment in compositing_reasons.h about // the bug for the reason of this. - return RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || - RuntimeEnabledFeatures::CompositeAfterPaintEnabled() - ? CompositingReason::kDirectReasonsForFilterProperty - : CompositingReason::kActiveFilterAnimation; + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + return CompositingReason::kDirectReasonsForFilterProperty; + } + // We also need to create filter node if the transform node is created for + // will-change to avoid raster invalidation (caused by otherwise a created/ + // deleted filter node) when we start/stop a transform/opacity animation. + // https://crbug.com/942681 + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + return CompositingReason::kDirectReasonsForFilterProperty | + CompositingReason::kWillChangeCompositingHint; + } + return CompositingReason::kActiveFilterAnimation; } static bool NeedsFilter(const LayoutObject& object, @@ -1101,7 +1121,8 @@ // On the other hand, "B" should not be clipped because the overflow clip // is not in its containing block chain, but as the filter output will be // clipped, so a blurred "B" may still be invisible. - state.output_clip = context_.current.clip; + if (!state.filter.IsEmpty()) + state.output_clip = context_.current.clip; // TODO(trchen): A filter may contain spatial operations such that an // output pixel may depend on an input pixel outside of the output clip. @@ -1132,10 +1153,11 @@ if (properties_->Filter()) { context_.current_effect = properties_->Filter(); // TODO(trchen): Change input clip to expansion hint once implemented. - const ClipPaintPropertyNode* input_clip = - properties_->Filter()->OutputClip(); - context_.current.clip = context_.absolute_position.clip = - context_.fixed_position.clip = input_clip; + if (const auto* input_clip = properties_->Filter()->OutputClip()) { + DCHECK_EQ(input_clip, context_.current.clip); + context_.absolute_position.clip = context_.fixed_position.clip = + input_clip; + } } }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index 57c8719..ddc29db 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -3175,7 +3175,7 @@ c_properties->Transform()->Matrix()); EXPECT_FALSE(c_properties->Transform()->HasRenderingContext()); EXPECT_TRUE(c_properties->Transform()->FlattensInheritedTransform()); - EXPECT_EQ(c_properties->Effect(), nullptr); + EXPECT_EQ(c_properties->Filter(), nullptr); const auto* d_properties = PaintPropertiesForElement("d"); ASSERT_NE(d_properties, nullptr); @@ -5601,9 +5601,19 @@ opacity_element->setAttribute(html_names::kStyleAttr, "opacity: 0.5"); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); - // All paint chunks contained by the new opacity effect node need to be - // re-painted. - EXPECT_TRUE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint()); + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + // TODO(crbug.com/900241): In BlinkGenPropertyTrees/CompositeAfterPaint we + // create effect and filter nodes when the transform node needs compositing, + // for crbug.com/942681. + // TODO(crbug.com/943671): CompositeAfterPaint also does this but the layer + // is marked needing repaint because of paint invalidation. Figure out if + // this is an over invalidation. + EXPECT_FALSE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint()); + } else { + // All paint chunks contained by the new opacity effect node need to be + // re-painted. + EXPECT_TRUE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint()); + } } TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithMask) { @@ -6515,7 +6525,15 @@ .LocalBorderBoxProperties(); EXPECT_EQ(clip_path_properties->MaskClip(), span_all_state.Clip().Parent()->Parent()); - EXPECT_EQ(clip_path_properties->Effect(), span_all_state.Effect().Parent()); + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { + // TODO(crbug.com/900241): In BlinkGenPropertyTrees/CompositeAfterPaint we + // create effect and filter nodes when the transform node needs compositing, + // for crbug.com/942681. + EXPECT_EQ(clip_path_properties->Effect(), + span_all_state.Effect().Parent()->Parent()->Parent()); + } else { + EXPECT_EQ(clip_path_properties->Effect(), span_all_state.Effect().Parent()); + } } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc index 5b8e0353..dd34552f 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -111,10 +111,9 @@ void PaintTimingDetector::NotifyNodeRemoved(const LayoutObject& object) { if (!object.GetNode()) return; - text_paint_timing_detector_->NotifyNodeRemoved( - DOMNodeIds::IdForNode(object.GetNode())); - image_paint_timing_detector_->NotifyNodeRemoved( - DOMNodeIds::IdForNode(object.GetNode())); + DOMNodeId node_id = DOMNodeIds::IdForNode(object.GetNode()); + text_paint_timing_detector_->NotifyNodeRemoved(node_id); + image_paint_timing_detector_->NotifyNodeRemoved(node_id); } void PaintTimingDetector::NotifyInputEvent(WebInputEvent::Type type) { @@ -150,30 +149,23 @@ } uint64_t PaintTimingDetector::CalculateVisualSize( - const LayoutRect& invalidated_rect, - const PaintLayer& painting_layer) const { - return CalculateVisualSize(invalidated_rect, painting_layer.GetLayoutObject() - .FirstFragment() - .LocalBorderBoxProperties()); -} - -uint64_t PaintTimingDetector::CalculateVisualSize( - const LayoutRect& invalidated_rect, + const LayoutRect& visual_rect, const PropertyTreeState& current_paint_chunk_properties) const { // This case should be dealt with outside the function. - DCHECK(!invalidated_rect.IsEmpty()); + DCHECK(!visual_rect.IsEmpty()); // As Layout objects live in different transform spaces, the object's rect // should be projected to the viewport's transform space. - FloatClipRect visual_rect = FloatClipRect(FloatRect(invalidated_rect)); - GeometryMapper::LocalToAncestorVisualRect( - current_paint_chunk_properties, PropertyTreeState::Root(), visual_rect); - FloatRect& visual_rect_float = visual_rect.Rect(); + FloatClipRect float_clip_visual_rect = FloatClipRect(FloatRect(visual_rect)); + GeometryMapper::LocalToAncestorVisualRect(current_paint_chunk_properties, + PropertyTreeState::Root(), + float_clip_visual_rect); + FloatRect& float_visual_rect = float_clip_visual_rect.Rect(); if (frame_view_->GetFrame().LocalFrameRoot().IsMainFrame()) - return visual_rect_float.Size().Area(); + return float_visual_rect.Size().Area(); // OOPIF. The final rect lives in the iframe's root frame space. We need to // project it to the top frame space. - LayoutRect layout_visual_rect(visual_rect_float); + LayoutRect layout_visual_rect(float_visual_rect); frame_view_->GetFrame() .LocalFrameRoot() .View()
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.h b/third_party/blink/renderer/core/paint/paint_timing_detector.h index 4053527..f312b4ee 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -14,7 +14,6 @@ class LayoutObject; class LocalFrameView; -class PaintLayer; class LayoutRect; class TextPaintTimingDetector; class ImagePaintTimingDetector; @@ -56,9 +55,10 @@ bool NeedToNotifyInputOrScroll(); void NotifyScroll(ScrollType scroll_type); void DidChangePerformanceTiming(); - uint64_t CalculateVisualSize(const LayoutRect& invalidated_rect, - const PaintLayer& painting_layer) const; - uint64_t CalculateVisualSize(const LayoutRect& invalidated_rect, + + // |visual_rect| should be an object's bounding rect in the space of + // PropertyTreeState. + uint64_t CalculateVisualSize(const LayoutRect& visual_rect, const PropertyTreeState&) const; void Dispose();
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc index 8b5ec37..37184bb 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + #include "third_party/blink/renderer/core/paint/text_paint_timing_detector.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" @@ -30,7 +32,7 @@ } TextPaintTimingDetector::TextPaintTimingDetector(LocalFrameView* frame_view) - : size_ordered_set_(&LargeTextFirst), + : records_manager_(), timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault), this, &TextPaintTimingDetector::TimerFired), @@ -72,22 +74,19 @@ } void TextPaintTimingDetector::Analyze() { - TextRecord* largest_text_first_paint = FindLargestPaintCandidate(); - DCHECK(!largest_text_first_paint || - !largest_text_first_paint->first_paint_time.is_null()); - if (largest_text_first_paint && - largest_text_first_paint->first_paint_time != largest_text_paint_) { - OnLargestTextDetected(*largest_text_first_paint); + TextRecord* candidate = records_manager_.FindLargestPaintCandidate(); + DCHECK(!candidate || !candidate->first_paint_time.is_null()); + if (candidate && candidate->first_paint_time != largest_text_paint_) { + OnLargestTextDetected(*candidate); frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming(); } } void TextPaintTimingDetector::OnPaintFinished() { - if (!texts_to_record_swap_time_.empty()) { - // Start repeating timer only once after the first text paint. - if (!timer_.IsActive()) { + if (records_manager_.NeedMeausuringPaintTime()) { + // Start repeating timer only once at the first text paint. + if (!timer_.IsActive()) timer_.StartRepeating(kTimerDelay, FROM_HERE); - } if (!awaiting_swap_promise_) { RegisterNotifySwapTime( CrossThreadBind(&TextPaintTimingDetector::ReportSwapTime, @@ -99,10 +98,10 @@ void TextPaintTimingDetector::NotifyNodeRemoved(DOMNodeId node_id) { if (!is_recording_) return; - if (id_record_map_.find(node_id) == id_record_map_.end()) + if (!records_manager_.IsKnownVisibleNode(node_id)) return; - detached_ids_.insert(node_id); - if (id_record_map_.size() == detached_ids_.size() && + records_manager_.SetNodeDetachedIfNeeded(node_id); + if (records_manager_.AreAllVisibleNodesDetached() && largest_text_paint_ != base::TimeTicks()) { largest_text_paint_ = base::TimeTicks(); frame_view_->GetPaintTimingDetector().DidChangePerformanceTiming(); @@ -126,19 +125,7 @@ void TextPaintTimingDetector::ReportSwapTime( WebLayerTreeView::SwapResult result, base::TimeTicks timestamp) { - // If texts_to_record_swap_time_.size == 0, it means the array has been - // consumed in a callback earlier than this one. That violates the assumption - // that only one or zero callback will be called after one OnPaintFinished. - DCHECK_GT(texts_to_record_swap_time_.size(), 0UL); - while (!texts_to_record_swap_time_.empty()) { - DOMNodeId node_id = texts_to_record_swap_time_.front(); - DCHECK(id_record_map_.Contains(node_id)); - TextRecord* record = id_record_map_.at(node_id); - record->first_paint_time = timestamp; - size_ordered_set_.insert(record->AsWeakPtr()); - - texts_to_record_swap_time_.pop(); - } + records_manager_.AssignPaintTimeToQueuedNodes(timestamp); awaiting_swap_promise_ = false; } @@ -147,6 +134,7 @@ const PropertyTreeState& current_paint_chunk_properties) { if (!is_recording_) return; + DCHECK(!records_manager_.HasTooManyNodes()); // TODO(crbug.com/933479): Use LayoutObject::GeneratingNode() to include // anonymous objects' rect. Node* node = object.GetNode(); @@ -155,83 +143,162 @@ DOMNodeId node_id = DOMNodeIds::IdForNode(node); DCHECK_NE(node_id, kInvalidDOMNodeId); + records_manager_.MarkNodeReattachedIfNeeded(node_id); + // This metric defines the size of a text by its first size. So it // early-returns if the text has been recorded. - if (size_zero_node_ids_.Contains(node_id)) + if (records_manager_.HasRecorded(node_id)) return; - // The node is reattached. - if (id_record_map_.Contains(node_id) && detached_ids_.Contains(node_id)) - detached_ids_.erase(node_id); - if (id_record_map_.Contains(node_id)) - return; - // When node_id is not found in id_record_map_, this invalidation is - // the text's first invalidation. - uint64_t rect_size = 0; + uint64_t visual_size = 0; // Compared to object.FirstFragment().VisualRect(), this will include other // fragments of the object. LayoutRect visual_rect = object.FragmentsVisualRectBoundingBox(); if (!visual_rect.IsEmpty()) { - rect_size = frame_view_->GetPaintTimingDetector().CalculateVisualSize( + visual_size = frame_view_->GetPaintTimingDetector().CalculateVisualSize( visual_rect, current_paint_chunk_properties); } - DVLOG(2) << "Node id (" << node_id << "): size=" << rect_size + DVLOG(2) << "Node id (" << node_id << "): size=" << visual_size << ", type=" << object.DebugName(); - // When rect_size == 0, it either means the text size is 0 or the text is out - // of viewport. In either case, we don't record their time for efficiency. - if (rect_size == 0) { - size_zero_node_ids_.insert(node_id); + // When visual_size == 0, it either means the text size is 0 or the text is + // out of viewport. In either case, we don't record their time for efficiency. + if (visual_size == 0) { + records_manager_.RecordInvisibleNode(node_id); } else { - // Non-trivial text is found. - std::unique_ptr<TextRecord> record = std::make_unique<TextRecord>(); - record->node_id = node_id; - record->first_size = rect_size; -#ifndef NDEBUG - if (object.IsText()) { - record->text = ToLayoutText(&object)->GetText(); - } else if (object.IsFileUploadControl()) { - record->text = ToLayoutFileUploadControl(&object)->FileTextValue(); - } else { - record->text = String("NON-TEXT_OBJECT"); - } -#endif - id_record_map_.insert(node_id, std::move(record)); - texts_to_record_swap_time_.push(node_id); + records_manager_.RecordVisibleNode(node_id, visual_size, object); + records_manager_.QueueToMeasurePaintTime(node_id); } - if (id_record_map_.size() + size_zero_node_ids_.size() >= - kTextNodeNumberLimit) { + if (records_manager_.HasTooManyNodes()) { TRACE_EVENT_INSTANT2("loading", "TextPaintTimingDetector::OverNodeLimit", - TRACE_EVENT_SCOPE_THREAD, "recorded_node_count", - id_record_map_.size(), "size_zero_node_count", - size_zero_node_ids_.size()); + TRACE_EVENT_SCOPE_THREAD, "count_size_non_zero_nodes", + records_manager_.CountVisibleNodes(), + "count_size_zero_nodes", + records_manager_.CountInvisibleNodes()); StopRecordEntries(); } } +TextRecord* TextPaintTimingDetector::FindLargestPaintCandidate() { + return records_manager_.FindLargestPaintCandidate(); +} + void TextPaintTimingDetector::StopRecordEntries() { timer_.Stop(); is_recording_ = false; } -TextRecord* TextPaintTimingDetector::FindLargestPaintCandidate() { - return FindCandidate(size_ordered_set_); -} - -TextRecord* TextPaintTimingDetector::FindCandidate( - const TextRecordSet& ordered_set) { - for (auto it = ordered_set.begin(); it != ordered_set.end(); ++it) { - if (detached_ids_.Contains((*it)->node_id) || - (*it)->first_paint_time.is_null()) - continue; - DCHECK(id_record_map_.Contains((*it)->node_id)); - return (*it).get(); - } - return nullptr; -} - void TextPaintTimingDetector::Trace(blink::Visitor* visitor) { visitor->Trace(frame_view_); } + +TextRecordsManager::TextRecordsManager() : size_ordered_set_(&LargeTextFirst) {} + +bool TextRecordsManager::AreAllVisibleNodesDetached() const { + return visible_node_map.size() == detached_ids_.size(); +} + +void TextRecordsManager::SetNodeDetachedIfNeeded(const DOMNodeId& node_id) { + if (!visible_node_map.Contains(node_id)) + return; + if (detached_ids_.Contains(node_id)) + return; + detached_ids_.insert(node_id); + is_result_invalidated_ = true; +} + +void TextRecordsManager::AssignPaintTimeToQueuedNodes( + const base::TimeTicks& timestamp) { + // If texts_queued_for_paint_time_.size == 0, it means the array has been + // consumed in a callback earlier than this one. That violates the assumption + // that only one or zero callback will be called after one OnPaintFinished. + DCHECK_GT(texts_queued_for_paint_time_.size(), 0UL); + while (!texts_queued_for_paint_time_.empty()) { + DOMNodeId node_id = texts_queued_for_paint_time_.front(); + DCHECK(visible_node_map.Contains(node_id)); + TextRecord* record = visible_node_map.at(node_id); + DCHECK_EQ(record->first_paint_time, base::TimeTicks()); + record->first_paint_time = timestamp; + + texts_queued_for_paint_time_.pop(); + is_result_invalidated_ = true; + } +} + +void TextRecordsManager::MarkNodeReattachedIfNeeded(const DOMNodeId& node_id) { + if (!detached_ids_.Contains(node_id)) + return; + DCHECK(visible_node_map.Contains(node_id) || + invisible_node_ids_.Contains(node_id)); + detached_ids_.erase(node_id); + is_result_invalidated_ = true; +} + +bool TextRecordsManager::HasRecorded(const DOMNodeId& node_id) const { + return visible_node_map.Contains(node_id) || + invisible_node_ids_.Contains(node_id); +} + +void TextRecordsManager::RecordInvisibleNode(const DOMNodeId& node_id) { + DCHECK(!HasTooManyNodes()); + invisible_node_ids_.insert(node_id); +} + +void TextRecordsManager::RecordVisibleNode(const DOMNodeId& node_id, + const uint64_t& visual_size, + const LayoutObject& text_object) { + DCHECK(!HasTooManyNodes()); + DCHECK_GT(visual_size, 0u); + std::unique_ptr<TextRecord> record = + std::make_unique<TextRecord>(node_id, visual_size); +#ifndef NDEBUG + String text; + if (text_object.IsText()) { + text = ToLayoutText(&text_object)->GetText(); + } else if (text_object.IsFileUploadControl()) { + text = ToLayoutFileUploadControl(&text_object)->FileTextValue(); + } else { + text = String("NON-TEXT-OBJECT"); + } + record->text = text; +#endif + size_ordered_set_.insert(record->AsWeakPtr()); + visible_node_map.insert(node_id, std::move(record)); + is_result_invalidated_ = true; +} + +void TextRecordsManager::QueueToMeasurePaintTime(const DOMNodeId& node_id) { + texts_queued_for_paint_time_.push(node_id); +} + +bool TextRecordsManager::HasTooManyNodes() const { + return visible_node_map.size() + invisible_node_ids_.size() >= + kTextNodeNumberLimit; +} + +TextRecord* TextRecordsManager::FindLargestPaintCandidate() { + // TODO(crbug/944248): An identified bug here is that the records with the + // same size will be silently ignored by |size_ordered_set_|. This is what + // causes these two sizes to be different. + DCHECK_GE(visible_node_map.size(), size_ordered_set_.size()); + if (!is_result_invalidated_) + return cached_largest_paint_candidate_; + TextRecord* new_largest_paint_candidate = nullptr; + for (auto it = size_ordered_set_.begin(); it != size_ordered_set_.end(); + ++it) { + // WeakPtr::IsValid() is expensive. We use raw pointer to reduce the checks. + TextRecord* text_record = (*it).get(); + DCHECK(text_record); + if (detached_ids_.Contains(text_record->node_id) || + text_record->first_paint_time.is_null()) + continue; + DCHECK(visible_node_map.Contains(text_record->node_id)); + new_largest_paint_candidate = text_record; + break; + } + cached_largest_paint_candidate_ = new_largest_paint_candidate; + is_result_invalidated_ = false; + return new_largest_paint_candidate; +} } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector.h b/third_party/blink/renderer/core/paint/text_paint_timing_detector.h index fd70cbd..9e237fb 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
@@ -5,6 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_PAINT_TIMING_DETECTOR_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_PAINT_TIMING_DETECTOR_H_ +#include <memory> +#include <queue> +#include <set> + #include "third_party/blink/public/platform/web_layer_tree_view.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" @@ -20,6 +24,9 @@ class TextRecord : public base::SupportsWeakPtr<TextRecord> { public: + TextRecord(DOMNodeId new_node_id, uint64_t new_first_size) + : node_id(new_node_id), first_size(new_first_size) {} + DOMNodeId node_id = kInvalidDOMNodeId; uint64_t first_size = 0; // This is treated as unset. @@ -27,14 +34,67 @@ #ifndef NDEBUG String text = ""; #endif + DISALLOW_COPY_AND_ASSIGN(TextRecord); +}; + +class TextRecordsManager { + using TextRecordSetComparator = bool (*)(const base::WeakPtr<TextRecord>&, + const base::WeakPtr<TextRecord>&); + using TextRecordSet = + std::set<base::WeakPtr<TextRecord>, TextRecordSetComparator>; + friend class TextPaintTimingDetectorTest; + + public: + TextRecordsManager(); + TextRecord* FindLargestPaintCandidate(); + + bool AreAllVisibleNodesDetached() const; + void SetNodeDetachedIfNeeded(const DOMNodeId&); + void MarkNodeReattachedIfNeeded(const DOMNodeId&); + + void RecordInvisibleNode(const DOMNodeId&); + void RecordVisibleNode(const DOMNodeId&, + const uint64_t& visual_size, + const LayoutObject&); + bool NeedMeausuringPaintTime() const { + return !texts_queued_for_paint_time_.empty(); + } + void QueueToMeasurePaintTime(const DOMNodeId&); + void AssignPaintTimeToQueuedNodes(const base::TimeTicks&); + + bool HasTooManyNodes() const; + bool HasRecorded(const DOMNodeId&) const; + + size_t CountVisibleNodes() const { return visible_node_map.size(); } + size_t CountInvisibleNodes() const { return invisible_node_ids_.size(); } + + bool IsKnownVisibleNode(const DOMNodeId& node_id) const { + return visible_node_map.Contains(node_id); + } + + private: + // This is used to cache the largest text paint result for better efficiency. + // The result will be invalidated whenever any change is done to the variables + // used in |FindLargestPaintCandidate|. + bool is_result_invalidated_ = false; + HashMap<DOMNodeId, std::unique_ptr<TextRecord>> visible_node_map; + HashSet<DOMNodeId> invisible_node_ids_; + HashSet<DOMNodeId> detached_ids_; + // This is used to order the nodes in |visible_node_map| so that we can find + // the largest node efficiently. Note that the entries in |size_ordered_set_| + // and |visible_node_map| should always be added/deleted together. + TextRecordSet size_ordered_set_; + std::queue<DOMNodeId> texts_queued_for_paint_time_; + TextRecord* cached_largest_paint_candidate_; + + DISALLOW_COPY_AND_ASSIGN(TextRecordsManager); }; // TextPaintTimingDetector contains Largest Text Paint. // // Largest Text Paint timing measures when the largest text element gets painted // within viewport. Specifically, it: -// 1. Tracks all texts' first invalidation, recording their visual size, paint -// time. +// 1. Tracks all texts' first paints, recording their visual size, paint time. // 2. Every 1 second after the first text pre-paint, the algorithm starts an // analysis. In the analysis: // 2.1 Largest Text Paint finds the text with the largest first visual size, @@ -50,19 +110,15 @@ using ReportTimeCallback = WTF::CrossThreadFunction<void(WebLayerTreeView::SwapResult, base::TimeTicks)>; - using TextRecordSetComparator = bool (*)(const base::WeakPtr<TextRecord>&, - const base::WeakPtr<TextRecord>&); - using TextRecordSet = - std::set<base::WeakPtr<TextRecord>, TextRecordSetComparator>; friend class TextPaintTimingDetectorTest; public: TextPaintTimingDetector(LocalFrameView* frame_view); void RecordText(const LayoutObject& object, const PropertyTreeState&); - TextRecord* FindLargestPaintCandidate(); void OnPaintFinished(); void NotifyNodeRemoved(DOMNodeId); void Dispose() { timer_.Stop(); } + TextRecord* FindLargestPaintCandidate(); base::TimeTicks LargestTextPaint() const { return largest_text_paint_; } uint64_t LargestTextPaintSize() const { return largest_text_paint_size_; } void StopRecordEntries(); @@ -80,23 +136,22 @@ base::TimeTicks timestamp); void RegisterNotifySwapTime(ReportTimeCallback callback); void OnLargestTextDetected(const TextRecord&); - TextRecord* FindCandidate(const TextRecordSet& ordered_set); - HashMap<DOMNodeId, std::unique_ptr<TextRecord>> id_record_map_; - HashSet<DOMNodeId> size_zero_node_ids_; - HashSet<DOMNodeId> detached_ids_; - TextRecordSet size_ordered_set_; - std::queue<DOMNodeId> texts_to_record_swap_time_; + TextRecordsManager records_manager_; // Make sure that at most one swap promise is ongoing. bool awaiting_swap_promise_ = false; unsigned largest_text_candidate_index_max_ = 0; bool is_recording_ = true; + bool has_records_changed_ = true; + base::TimeTicks largest_text_paint_; uint64_t largest_text_paint_size_ = 0; TaskRunnerTimer<TextPaintTimingDetector> timer_; Member<LocalFrameView> frame_view_; + + DISALLOW_COPY_AND_ASSIGN(TextPaintTimingDetector); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc index fface27..ece9cc9a 100644 --- a/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc
@@ -40,16 +40,16 @@ unsigned CountVisibleTexts() { return GetPaintTimingDetector() .GetTextPaintTimingDetector() - .id_record_map_.size() - + .records_manager_.visible_node_map.size() - GetPaintTimingDetector() .GetTextPaintTimingDetector() - .detached_ids_.size(); + .records_manager_.detached_ids_.size(); } unsigned CountDetachedTexts() { return GetPaintTimingDetector() .GetTextPaintTimingDetector() - .detached_ids_.size(); + .records_manager_.detached_ids_.size(); } void InvokeCallback() { @@ -70,7 +70,7 @@ UpdateAllLifecyclePhasesForTest(); TextPaintTimingDetector& detector = GetPaintTimingDetector().GetTextPaintTimingDetector(); - if (!detector.texts_to_record_swap_time_.empty()) { + if (!detector.records_manager_.texts_queued_for_paint_time_.empty()) { detector.ReportSwapTime(WebLayerTreeView::SwapResult::kDidSwap, CurrentTimeTicks()); } @@ -79,7 +79,7 @@ size_t CountPendingSwapTime(LocalFrameView& frame_view) { TextPaintTimingDetector& detector = frame_view.GetPaintTimingDetector().GetTextPaintTimingDetector(); - return detector.texts_to_record_swap_time_.size(); + return detector.records_manager_.texts_queued_for_paint_time_.size(); } void ChildFrameSwapTimeCallBack() { @@ -120,7 +120,15 @@ } TextRecord* TextRecordOfLargestTextPaint() { - return GetPaintTimingDetector() + return GetFrameView() + .GetPaintTimingDetector() + .GetTextPaintTimingDetector() + .FindLargestPaintCandidate(); + } + + TextRecord* ChildFrameTextRecordOfLargestTextPaint() { + return GetChildFrameView() + .GetPaintTimingDetector() .GetTextPaintTimingDetector() .FindLargestPaintCandidate(); } @@ -251,9 +259,7 @@ SetFontSize(long_text, 100); UpdateAllLifecyclePhasesAndSimulateSwapTime(); - TextRecord* record = GetPaintTimingDetector() - .GetTextPaintTimingDetector() - .FindLargestPaintCandidate(); + TextRecord* record = TextRecordOfLargestTextPaint(); EXPECT_EQ(TextRecordOfLargestTextPaint()->node_id, NodeIdOfText(long_text)); TimeTicks firing_time = record->first_paint_time; EXPECT_GE(firing_time, time1); @@ -272,9 +278,7 @@ <div class='out'>text outside of viewport</div> )HTML"); UpdateAllLifecyclePhasesAndSimulateSwapTime(); - EXPECT_FALSE(GetPaintTimingDetector() - .GetTextPaintTimingDetector() - .FindLargestPaintCandidate()); + EXPECT_FALSE(TextRecordOfLargestTextPaint()); } TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_IgnoreRemovedText) { @@ -487,10 +491,7 @@ UpdateAllLifecyclePhasesForTest(); EXPECT_EQ(CountPendingSwapTime(GetChildFrameView()), 1u); ChildFrameSwapTimeCallBack(); - TextRecord* text = GetChildFrameView() - .GetPaintTimingDetector() - .GetTextPaintTimingDetector() - .FindLargestPaintCandidate(); + TextRecord* text = ChildFrameTextRecordOfLargestTextPaint(); EXPECT_TRUE(text); }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index bbfbe50..a52c8bf 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -170,7 +170,8 @@ kShouldFire, }; -ShouldFireErrorEvent ParseAndRegisterImportMap(ScriptElementBase& element) { +ShouldFireErrorEvent ParseAndRegisterImportMap(ScriptElementBase& element, + const TextPosition& position) { Document& element_document = element.GetDocument(); Document* context_document = element_document.ContextDocument(); DCHECK(context_document); @@ -201,12 +202,20 @@ UseCounter::Count(*context_document, WebFeature::kImportMap); KURL base_url = element_document.BaseURL(); - ImportMap* import_map = ImportMap::Create( - *modulator, element.TextFromChildren(), base_url, element_document); + const String import_map_text = element.TextFromChildren(); + ImportMap* import_map = ImportMap::Create(*modulator, import_map_text, + base_url, element_document); if (!import_map) return ShouldFireErrorEvent::kShouldFire; + // https://github.com/WICG/import-maps/issues/105 + if (!ContentSecurityPolicy::ShouldBypassMainWorld(&element_document) && + !element.AllowInlineScriptForCSP(element.GetNonceForElement(), + position.line_, import_map_text)) { + return ShouldFireErrorEvent::kShouldFire; + } + modulator->RegisterImportMap(import_map); return ShouldFireErrorEvent::kDoNotFire; } @@ -390,13 +399,26 @@ if (BlockForNoModule(script_type_, element_->NomoduleAttributeValue())) return false; + // TODO(csharrison): This logic only works if the tokenizer/parser was not + // blocked waiting for scripts when the element was inserted. This usually + // fails for instance, on second document.write if a script writes twice + // in a row. To fix this, the parser might have to keep track of raw + // string position. + // + // Also PendingScript's contructor has the same code. + const bool is_in_document_write = element_document.IsInDocumentWrite(); + + // Reset line numbering for nested writes. + TextPosition position = + is_in_document_write ? TextPosition() : script_start_position; + // 13. if (!IsScriptForEventSupported()) return false; // Process the import map. if (is_import_map) { - if (ParseAndRegisterImportMap(*element_) == + if (ParseAndRegisterImportMap(*element_, position) == ShouldFireErrorEvent::kShouldFire) { element_document.GetTaskRunner(TaskType::kDOMManipulation) ->PostTask(FROM_HERE, @@ -475,19 +497,6 @@ DCHECK(!prepared_pending_script_); - // TODO(csharrison): This logic only works if the tokenizer/parser was not - // blocked waiting for scripts when the element was inserted. This usually - // fails for instance, on second document.write if a script writes twice - // in a row. To fix this, the parser might have to keep track of raw - // string position. - // - // Also PendingScript's contructor has the same code. - const bool is_in_document_write = element_document.IsInDocumentWrite(); - - // Reset line numbering for nested writes. - TextPosition position = - is_in_document_write ? TextPosition() : script_start_position; - // <spec step="22">Let options be a script fetch options whose cryptographic // nonce is cryptographic nonce, integrity metadata is integrity metadata, // parser metadata is parser metadata, credentials mode is module script
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 9dd4db74..d6377d2 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1080,7 +1080,7 @@ background_layer; background_layer = background_layer->Next()) { if (StyleImage* image = background_layer->GetImage()) { if (image->IsImageResource() && image->IsLazyloadPossiblyDeferred()) - ToStyleFetchedImage(image)->LoadDeferredImage(document); + To<StyleFetchedImage>(image)->LoadDeferredImage(document); } } }
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 869c66e..f6bc14cf 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2350,6 +2350,10 @@ // Load the images of CSS properties that were deferred by LazyLoad. void LoadDeferredImages(Document&) const; + ColorScheme GetColorScheme() const { + return DarkColorScheme() ? ColorScheme::kDark : ColorScheme::kLight; + } + private: void SetVisitedLinkBackgroundColor(const StyleColor& v) { SetVisitedLinkBackgroundColorInternal(v);
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index 23a5a94..c958e8fd 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -1074,5 +1074,12 @@ default_value: "false", custom_compare: true, }, + { + name: "DarkColorScheme", + field_template: "monotonic_flag", + type_name: "bool", + default_value: "false", + inherited: true, + }, ], }
diff --git a/third_party/blink/renderer/core/style/filter_operation.cc b/third_party/blink/renderer/core/style/filter_operation.cc index b7f77234..c4f426c5 100644 --- a/third_party/blink/renderer/core/style/filter_operation.cc +++ b/third_party/blink/renderer/core/style/filter_operation.cc
@@ -84,7 +84,7 @@ double from_amount; if (from) { SECURITY_DCHECK(from->IsSameType(*this)); - from_amount = ToBasicColorMatrixFilterOperation(from)->Amount(); + from_amount = To<BasicColorMatrixFilterOperation>(from)->Amount(); } else { switch (type_) { case GRAYSCALE: @@ -124,7 +124,7 @@ double from_amount; if (from) { SECURITY_DCHECK(from->IsSameType(*this)); - from_amount = ToBasicComponentTransferFilterOperation(from)->Amount(); + from_amount = To<BasicComponentTransferFilterOperation>(from)->Amount(); } else { switch (type_) { case OPACITY:
diff --git a/third_party/blink/renderer/core/style/filter_operation.h b/third_party/blink/renderer/core/style/filter_operation.h index 2d8ae00..8e25b506 100644 --- a/third_party/blink/renderer/core/style/filter_operation.h +++ b/third_party/blink/renderer/core/style/filter_operation.h
@@ -34,6 +34,7 @@ #include "third_party/blink/renderer/platform/graphics/box_reflection.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -205,11 +206,12 @@ type == FilterOperation::HUE_ROTATE; } -DEFINE_TYPE_CASTS(BasicColorMatrixFilterOperation, - FilterOperation, - op, - IsBasicColorMatrixFilterOperation(*op), - IsBasicColorMatrixFilterOperation(op)); +template <> +struct DowncastTraits<BasicColorMatrixFilterOperation> { + static bool AllowFrom(const FilterOperation& op) { + return IsBasicColorMatrixFilterOperation(op); + } +}; // INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component // transfer effect. @@ -251,11 +253,12 @@ type == FilterOperation::CONTRAST; } -DEFINE_TYPE_CASTS(BasicComponentTransferFilterOperation, - FilterOperation, - op, - IsBasicComponentTransferFilterOperation(*op), - IsBasicComponentTransferFilterOperation(op)); +template <> +struct DowncastTraits<BasicComponentTransferFilterOperation> { + static bool AllowFrom(const FilterOperation& op) { + return IsBasicComponentTransferFilterOperation(op); + } +}; class CORE_EXPORT BlurFilterOperation : public FilterOperation { public:
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.cc b/third_party/blink/renderer/core/style/style_fetched_image.cc index a052db8..a100e3f 100644 --- a/third_party/blink/renderer/core/style/style_fetched_image.cc +++ b/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -59,7 +59,7 @@ bool StyleFetchedImage::IsEqual(const StyleImage& other) const { if (!other.IsImageResource()) return false; - const auto& other_image = ToStyleFetchedImage(other); + const auto& other_image = To<StyleFetchedImage>(other); if (image_ != other_image.image_) return false; return url_ == other_image.url_;
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.h b/third_party/blink/renderer/core/style/style_fetched_image.h index c8d8275..3039806 100644 --- a/third_party/blink/renderer/core/style/style_fetched_image.h +++ b/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -27,6 +27,7 @@ #include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h" #include "third_party/blink/renderer/core/style/style_image.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -91,7 +92,12 @@ const KURL url_; }; -DEFINE_STYLE_IMAGE_TYPE_CASTS(StyleFetchedImage, IsImageResource()); +template <> +struct DowncastTraits<StyleFetchedImage> { + static bool AllowFrom(const StyleImage& styleImage) { + return styleImage.IsImageResource(); + } +}; } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/style/style_fetched_image_set.cc b/third_party/blink/renderer/core/style/style_fetched_image_set.cc index 41fe961..9a28d84 100644 --- a/third_party/blink/renderer/core/style/style_fetched_image_set.cc +++ b/third_party/blink/renderer/core/style/style_fetched_image_set.cc
@@ -55,7 +55,7 @@ bool StyleFetchedImageSet::IsEqual(const StyleImage& other) const { if (!other.IsImageResourceSet()) return false; - const auto& other_image = ToStyleFetchedImageSet(other); + const auto& other_image = To<StyleFetchedImageSet>(other); if (best_fit_image_ != other_image.best_fit_image_) return false; return url_ == other_image.url_;
diff --git a/third_party/blink/renderer/core/style/style_fetched_image_set.h b/third_party/blink/renderer/core/style/style_fetched_image_set.h index 131fcd8..b45894c 100644 --- a/third_party/blink/renderer/core/style/style_fetched_image_set.h +++ b/third_party/blink/renderer/core/style/style_fetched_image_set.h
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/style/style_image.h" #include "third_party/blink/renderer/platform/geometry/layout_size.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -100,7 +101,12 @@ const KURL url_; }; -DEFINE_STYLE_IMAGE_TYPE_CASTS(StyleFetchedImageSet, IsImageResourceSet()); +template <> +struct DowncastTraits<StyleFetchedImageSet> { + static bool AllowFrom(const StyleImage& styleImage) { + return styleImage.IsImageResourceSet(); + } +}; } // namespace blink
diff --git a/third_party/blink/renderer/core/style/style_generated_image.cc b/third_party/blink/renderer/core/style/style_generated_image.cc index a5e9f92..dc5fc162 100644 --- a/third_party/blink/renderer/core/style/style_generated_image.cc +++ b/third_party/blink/renderer/core/style/style_generated_image.cc
@@ -41,7 +41,7 @@ bool StyleGeneratedImage::IsEqual(const StyleImage& other) const { if (!other.IsGeneratedImage()) return false; - const auto& other_generated = ToStyleGeneratedImage(other); + const auto& other_generated = To<StyleGeneratedImage>(other); return image_generator_value_ == other_generated.image_generator_value_; }
diff --git a/third_party/blink/renderer/core/style/style_generated_image.h b/third_party/blink/renderer/core/style/style_generated_image.h index f11219b..d350642 100644 --- a/third_party/blink/renderer/core/style/style_generated_image.h +++ b/third_party/blink/renderer/core/style/style_generated_image.h
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/style/style_image.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -73,7 +74,12 @@ const bool fixed_size_; }; -DEFINE_STYLE_IMAGE_TYPE_CASTS(StyleGeneratedImage, IsGeneratedImage()); +template <> +struct DowncastTraits<StyleGeneratedImage> { + static bool AllowFrom(const StyleImage& styleImage) { + return styleImage.IsGeneratedImage(); + } +}; } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/style/style_image.h b/third_party/blink/renderer/core/style/style_image.h index a7eba89..e18da3e 100644 --- a/third_party/blink/renderer/core/style/style_image.h +++ b/third_party/blink/renderer/core/style/style_image.h
@@ -165,13 +165,5 @@ const LayoutSize& default_object_size) const; }; -#define DEFINE_STYLE_IMAGE_TYPE_CASTS(thisType, function) \ - DEFINE_TYPE_CASTS(thisType, StyleImage, styleImage, styleImage->function, \ - styleImage.function); \ - inline thisType* To##thisType(const Member<StyleImage>& styleImage) { \ - return To##thisType(styleImage.Get()); \ - } \ - typedef int NeedsSemiColonAfterDefineStyleImageTypeCasts - } // namespace blink #endif
diff --git a/third_party/blink/renderer/core/style/style_pending_image.h b/third_party/blink/renderer/core/style/style_pending_image.h index 9fcdb77..d99b114 100644 --- a/third_party/blink/renderer/core/style/style_pending_image.h +++ b/third_party/blink/renderer/core/style/style_pending_image.h
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/css/css_paint_value.h" #include "third_party/blink/renderer/core/style/style_image.h" #include "third_party/blink/renderer/platform/graphics/image.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -106,12 +107,17 @@ Member<CSSValue> value_; }; -DEFINE_STYLE_IMAGE_TYPE_CASTS(StylePendingImage, IsPendingImage()); +template <> +struct DowncastTraits<StylePendingImage> { + static bool AllowFrom(const StyleImage& styleImage) { + return styleImage.IsPendingImage(); + } +}; inline bool StylePendingImage::IsEqual(const StyleImage& other) const { if (!other.IsPendingImage()) return false; - const auto& other_pending = ToStylePendingImage(other); + const auto& other_pending = To<StylePendingImage>(other); return value_ == other_pending.value_; }
diff --git a/third_party/blink/renderer/core/workers/worker_backing_thread.cc b/third_party/blink/renderer/core/workers/worker_backing_thread.cc index e88187ba9..ee0cd03 100644 --- a/third_party/blink/renderer/core/workers/worker_backing_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_backing_thread.cc
@@ -71,9 +71,11 @@ backing_thread_->InitializeOnThread(); DCHECK(!isolate_); + ThreadScheduler* scheduler = BackingThread().PlatformThread().Scheduler(); isolate_ = V8PerIsolateData::Initialize( - backing_thread_->PlatformThread().Scheduler()->V8TaskRunner(), + scheduler->V8TaskRunner(), V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot); + scheduler->SetV8Isolate(isolate_); AddWorkerIsolate(isolate_); V8Initializer::InitializeWorker(isolate_); @@ -83,8 +85,7 @@ ScriptWrappableMarkingVisitor::PerformCleanup); if (RuntimeEnabledFeatures::V8IdleTasksEnabled()) { V8PerIsolateData::EnableIdleTasks( - isolate_, std::make_unique<V8IdleTaskRunner>( - BackingThread().PlatformThread().Scheduler())); + isolate_, std::make_unique<V8IdleTaskRunner>(scheduler)); } Platform::Current()->DidStartWorkerThread(); @@ -105,6 +106,7 @@ void WorkerBackingThread::ShutdownOnBackingThread() { DCHECK(backing_thread_->IsCurrentThread()); + BackingThread().PlatformThread().Scheduler()->SetV8Isolate(nullptr); Platform::Current()->WillStopWorkerThread(); V8PerIsolateData::WillBeDestroyed(isolate_);
diff --git a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js index a6e90629..286231b 100644 --- a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js +++ b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
@@ -90,21 +90,6 @@ return highlightedUrl; } - - /** - * @param {!Protocol.Security.SecurityState} securityState - */ - setRanInsecureContentStyle(securityState) { - this._ranInsecureContentStyle = securityState; - } - - /** - * @param {!Protocol.Security.SecurityState} securityState - */ - setDisplayedInsecureContentStyle(securityState) { - this._displayedInsecureContentStyle = securityState; - } - /** * @param {!Protocol.Security.SecurityState} newSecurityState * @param {boolean} schemeIsCryptographic @@ -200,12 +185,9 @@ let securityState = /** @type {!Protocol.Security.SecurityState} */ (request.securityState()); - if (request.mixedContentType === Protocol.Security.MixedContentType.Blockable && this._ranInsecureContentStyle) - securityState = this._ranInsecureContentStyle; - else if ( - request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable && - this._displayedInsecureContentStyle) - securityState = this._displayedInsecureContentStyle; + if (request.mixedContentType === Protocol.Security.MixedContentType.Blockable || + request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable) + securityState = Protocol.Security.SecurityState.Insecure; if (this._origins.has(origin)) { const originState = this._origins.get(origin); @@ -687,9 +669,6 @@ this._explanations = explanations, this._insecureContentStatus = insecureContentStatus; this._schemeIsCryptographic = schemeIsCryptographic; - this._panel.setRanInsecureContentStyle(insecureContentStatus.ranInsecureContentStyle); - this._panel.setDisplayedInsecureContentStyle(insecureContentStatus.displayedInsecureContentStyle); - this.refreshExplanations(); }
diff --git a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc index 52b0450..232cf77 100644 --- a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc +++ b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
@@ -61,6 +61,7 @@ button->accessibleNode()->setRole("slider"); EXPECT_EQ("slider", button->accessibleNode()->role()); + GetDocument().View()->UpdateLifecycleToLayoutClean(); axButton = cache->GetOrCreate(button); EXPECT_EQ(ax::mojom::Role::kSlider, axButton->RoleValue()); } @@ -112,6 +113,7 @@ // Assert that the AX object was affected by ARIA attributes. auto* cache = AXObjectCache(); ASSERT_NE(nullptr, cache); + GetDocument().View()->UpdateLifecycleToLayoutClean(); auto* axButton = cache->GetOrCreate(button); EXPECT_EQ(ax::mojom::Role::kCheckBox, axButton->RoleValue()); ax::mojom::NameFrom name_from; @@ -123,6 +125,7 @@ button->accessibleNode()->setRole("radio"); button->accessibleNode()->setLabel("Radio"); button->accessibleNode()->setDisabled(false, false); + GetDocument().View()->UpdateLifecycleToLayoutClean(); // Assert that the AX object was affected by AOM properties. axButton = cache->GetOrCreate(button); @@ -134,6 +137,7 @@ button->accessibleNode()->setRole(g_null_atom); button->accessibleNode()->setLabel(g_null_atom); button->accessibleNode()->setDisabled(false, true); + GetDocument().View()->UpdateLifecycleToLayoutClean(); // The AX Object should now revert to ARIA. axButton = cache->GetOrCreate(button); @@ -156,6 +160,7 @@ auto* cache = AXObjectCache(); ASSERT_NE(nullptr, cache); + GetDocument().View()->UpdateLifecycleToLayoutClean(); auto* ax_slider = cache->GetOrCreate(slider); float value = 0.0f; EXPECT_TRUE(ax_slider->MinValueForRange(&value));
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index a65910e..9a09a72 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -2588,7 +2588,8 @@ // changed event must be fired. This ensures the AT is notified that the // selected state has changed, so that it does not read "unselected" as // the user navigates through the items. - AXObjectCache().HandleAriaSelectedChanged(active_descendant->GetNode()); + AXObjectCache().HandleAriaSelectedChangedWithCleanLayout( + active_descendant->GetNode()); } // Mark this node dirty. AXEventGenerator will automatically infer
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index da4794c..aed9832 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -3383,6 +3383,19 @@ return String(); } +String AXNodeObject::Title(ax::mojom::NameFrom name_from) const { + if (name_from == ax::mojom::NameFrom::kTitle) + return String(); + + if (const auto* element = GetElement()) { + String title = element->title(); + if (!title.IsEmpty()) + return title; + } + + return String(); +} + String AXNodeObject::PlaceholderFromNativeAttribute() const { Node* node = GetNode(); if (!node || !blink::IsTextControl(*node))
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index 2218d24d..b4357f3 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -172,6 +172,7 @@ DescriptionSources*, AXRelatedObjectVector*) const override; String Placeholder(ax::mojom::NameFrom) const override; + String Title(ax::mojom::NameFrom) const override; bool NameFromLabelElement() const override; // Location
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 3964f5e2..27f5a0c2 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -628,6 +628,11 @@ // present and if it wasn't already exposed by one of the two functions above. virtual String Placeholder(ax::mojom::NameFrom) const { return String(); } + // Takes the result of nameFrom and retrieves the HTML Title of the object, + // if present and if it wasn't already exposed by |GetName| above. + // HTML Title is typically used as a tooltip. + virtual String Title(ax::mojom::NameFrom) const { return String(); } + // Internal functions used by name and description, above. typedef HeapHashSet<Member<const AXObject>> AXObjectSet; virtual String TextAlternative(bool recursive,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 5aaa514..64634af4 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -92,6 +92,17 @@ using namespace html_names; +namespace { +// Return a node for the current layout object or ancestor layout object. +Node* GetClosestNodeForLayoutObject(LayoutObject* layout_object) { + if (!layout_object) + return nullptr; + Node* node = layout_object->GetNode(); + return node ? node : GetClosestNodeForLayoutObject(layout_object->Parent()); +} + +} // namespace + // static AXObjectCache* AXObjectCacheImpl::Create(Document& document) { return MakeGarbageCollected<AXObjectCacheImpl>(document); @@ -103,14 +114,12 @@ modification_count_(0), validation_message_axid_(0), relation_cache_(std::make_unique<AXRelationCache>(this)), - notification_post_timer_( - document.GetTaskRunner(TaskType::kInternalDefault), - this, - &AXObjectCacheImpl::NotificationPostTimerFired), accessibility_event_permission_(mojom::PermissionStatus::ASK), permission_observer_binding_(this) { if (document_->LoadEventFinished()) AddPermissionStatusListener(); + documents_.insert(&document); + document.View()->RegisterForLifecycleNotifications(this); } AXObjectCacheImpl::~AXObjectCacheImpl() { @@ -120,14 +129,18 @@ } void AXObjectCacheImpl::Dispose() { - notification_post_timer_.Stop(); - for (auto& entry : objects_) { AXObject* obj = entry.value; obj->Detach(); RemoveAXID(obj); } + for (auto document : documents_) { + if (!document || !document->View()) + continue; + document->View()->UnregisterFromLifecycleNotifications(this); + } + #if DCHECK_IS_ON() has_been_disposed_ = true; #endif @@ -137,6 +150,22 @@ return GetOrCreate(document_); } +void AXObjectCacheImpl::InitializePopup(Document* document) { + if (!document || documents_.Contains(document) || document->View()) + return; + + documents_.insert(document); + document->View()->RegisterForLifecycleNotifications(this); +} + +void AXObjectCacheImpl::DisposePopup(Document* document) { + if (documents_.Contains(document) || document->View()) + return; + + document->View()->UnregisterFromLifecycleNotifications(this); + documents_.erase(document); +} + AXObject* AXObjectCacheImpl::FocusedImageMapUIElement( HTMLAreaElement* area_element) { // Find the corresponding accessibility object for the HTMLAreaElement. This @@ -686,10 +715,53 @@ return AXObject::InOrderTraversalIterator(); } +void AXObjectCacheImpl::DeferTreeUpdateInternal(Node* node, + base::OnceClosure callback) { + tree_update_callback_queue_.push_back( + std::make_pair(WrapWeakPersistent(node), std::move(callback))); +} + +void AXObjectCacheImpl::DeferTreeUpdate( + void (AXObjectCacheImpl::*method)(Node*), + Node* node) { + base::OnceClosure callback = + WTF::Bind(method, WrapWeakPersistent(this), WrapWeakPersistent(node)); + DeferTreeUpdateInternal(node, std::move(callback)); +} + +void AXObjectCacheImpl::DeferTreeUpdate( + void (AXObjectCacheImpl::*method)(const QualifiedName&, Element* element), + const QualifiedName& attr_name, + Element* element) { + base::OnceClosure callback = WTF::Bind( + method, WrapWeakPersistent(this), attr_name, WrapWeakPersistent(element)); + DeferTreeUpdateInternal(element, std::move(callback)); +} + +void AXObjectCacheImpl::DeferTreeUpdate( + void (AXObjectCacheImpl::*method)(Node*, AXObject*), + Node* node, + AXObject* obj) { + base::OnceClosure callback = + WTF::Bind(method, WrapWeakPersistent(this), WrapWeakPersistent(node), + WrapWeakPersistent(obj)); + DeferTreeUpdateInternal(node, std::move(callback)); +} + void AXObjectCacheImpl::SelectionChanged(Node* node) { - AXObject* nearestAncestor = NearestExistingAncestor(node); - if (nearestAncestor) - nearestAncestor->SelectionChanged(); + if (!node) + return; + + DeferTreeUpdate(&AXObjectCacheImpl::SelectionChangedWithCleanLayout, node); +} + +void AXObjectCacheImpl::SelectionChangedWithCleanLayout(Node* node) { + if (!node) + return; + + AXObject* ax_object = GetOrCreate(node); + if (ax_object) + ax_object->SelectionChanged(); } void AXObjectCacheImpl::UpdateReverseRelations( @@ -699,16 +771,30 @@ } void AXObjectCacheImpl::TextChanged(Node* node) { - TextChanged(Get(node), node); + if (!node) + return; + + DeferTreeUpdate(&AXObjectCacheImpl::TextChangedWithCleanLayout, node); } void AXObjectCacheImpl::TextChanged(LayoutObject* layout_object) { - if (layout_object) - TextChanged(Get(layout_object), layout_object->GetNode()); + if (!layout_object) + return; + + // TODO(aboxhall): audit calls to this and figure out when this is called + // when node might be null + Node* node = GetClosestNodeForLayoutObject(layout_object); + if (node) { + DeferTreeUpdate(&AXObjectCacheImpl::TextChangedWithCleanLayout, node); + return; + } + + TextChanged(Get(layout_object), layout_object->GetNode()); } void AXObjectCacheImpl::TextChanged(AXObject* obj, Node* node_for_relation_update) { + // TODO(aboxhall): Figure out when this may be called with dirty layout if (obj) obj->TextChanged(); @@ -718,7 +804,17 @@ PostNotification(obj, ax::mojom::Event::kTextChanged); } -void AXObjectCacheImpl::FocusableChanged(Element* element) { +void AXObjectCacheImpl::TextChangedWithCleanLayout(Node* node) { + if (!node) + return; + + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + TextChanged(Get(node), node); +} + +void AXObjectCacheImpl::FocusableChangedWithCleanLayout(Element* element) { + DCHECK(element); + DCHECK(!element->GetDocument().NeedsLayoutTreeUpdateForNode(*element)); AXObject* obj = GetOrCreate(element); if (!obj) return; @@ -727,7 +823,7 @@ // Elements that are hidden but focusable are not ignored. Therefore, if a // hidden element's focusable state changes, it's ignored state must be // recomputed. - ChildrenChanged(element->parentNode()); + ChildrenChangedWithCleanLayout(element->parentNode()); } else { // Refresh the focusable state on the exposed object. MarkAXObjectDirty(obj, false); @@ -736,6 +832,10 @@ void AXObjectCacheImpl::DocumentTitleChanged() { PostNotification(Root(), ax::mojom::Event::kDocumentTitleChanged); + // If title changes at a point where paint is clean, send notification + // immediately. + if (document_->Lifecycle().GetState() >= DocumentLifecycle::kPaintClean) + PostNotificationsAfterLayout(document_); } void AXObjectCacheImpl::UpdateCacheAfterNodeIsAttached(Node* node) { @@ -763,20 +863,8 @@ void AXObjectCacheImpl::ChildrenChanged(Node* node) { if (!node) return; - if (node->GetDocument().IsFlatTreeTraversalForbidden() || - node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)) { - nodes_changed_during_layout_.push_back(node); - return; - } - ChildrenChanged(Get(node), node); -} -// Return a node for the current layout object or ancestor layout object. -Node* GetClosestNodeForLayoutObject(LayoutObject* layout_object) { - if (!layout_object) - return nullptr; - Node* node = layout_object->GetNode(); - return node ? node : GetClosestNodeForLayoutObject(layout_object->Parent()); + DeferTreeUpdate(&AXObjectCacheImpl::ChildrenChangedWithCleanLayout, node); } void AXObjectCacheImpl::ChildrenChanged(LayoutObject* layout_object) { @@ -785,10 +873,8 @@ Node* node = GetClosestNodeForLayoutObject(layout_object); - if (node && (node->GetDocument().IsFlatTreeTraversalForbidden() || - node->GetDocument().NeedsLayoutTreeUpdateForNode(*node) || - node->NeedsDistributionRecalc())) { - nodes_changed_during_layout_.push_back(node); + if (node) { + DeferTreeUpdate(&AXObjectCacheImpl::ChildrenChangedWithCleanLayout, node); return; } @@ -799,18 +885,30 @@ void AXObjectCacheImpl::ChildrenChanged(AccessibleNode* accessible_node) { if (!accessible_node) return; - Element* element = accessible_node->element(); - if (element && - (element->GetDocument().NeedsLayoutTreeUpdateForNode(*element) || - element->NeedsDistributionRecalc())) { - nodes_changed_during_layout_.push_back(element); - return; - } + AXObject* object = Get(accessible_node); ChildrenChanged(object, object ? object->GetNode() : nullptr); } +void AXObjectCacheImpl::ChildrenChangedWithCleanLayout(Node* node) { + if (!node) + return; + + DCHECK(node->GetDocument().Lifecycle().GetState() >= + DocumentLifecycle::kLayoutClean); +#ifndef NDEBUG + if (node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)) { + LOG(ERROR) << "Node needs layout tree update: " << node; + node->ShowTreeForThisAcrossFrame(); + } +#endif + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + + ChildrenChanged(Get(node), node); +} + void AXObjectCacheImpl::ChildrenChanged(AXObject* obj, Node* optional_node) { + // TODO(aboxhall): Figure out when this may be called with dirty layout if (obj) obj->ChildrenChanged(); @@ -823,36 +921,27 @@ void AXObjectCacheImpl::ProcessUpdatesAfterLayout(Document& document) { if (document.Lifecycle().GetState() < DocumentLifecycle::kLayoutClean) return; - VectorOf<Node> old_nodes_changed_during_layout; - nodes_changed_during_layout_.swap(old_nodes_changed_during_layout); - for (auto node : old_nodes_changed_during_layout) { + TreeUpdateCallbackQueue old_tree_update_callback_queue; + tree_update_callback_queue_.swap(old_tree_update_callback_queue); + for (auto& pair : old_tree_update_callback_queue) { + Node* node = pair.first; + if (!node) + continue; + base::OnceClosure& callback = pair.second; if (node->GetDocument() != document) { - nodes_changed_during_layout_.push_back(node); + tree_update_callback_queue_.push_back( + std::make_pair(WrapWeakPersistent(node), std::move(callback))); continue; } - ChildrenChanged(Get(node), node); - } - - AttributesChangedVector old_attributes_changed_during_layout; - attributes_changed_during_layout_.swap(old_attributes_changed_during_layout); - for (auto pair : old_attributes_changed_during_layout) { - auto attribute_name = pair.first; - auto element = pair.second; - if (element->GetDocument() != document) { - attributes_changed_during_layout_.push_back( - std::make_pair(attribute_name, element)); - continue; - } - HandleAttributeChanged(attribute_name, element); + std::move(callback).Run(); } } -void AXObjectCacheImpl::NotificationPostTimerFired(TimerBase*) { - notification_post_timer_.Stop(); - - unsigned i = 0, count = notifications_to_post_.size(); - for (i = 0; i < count; ++i) { - AXObject* obj = notifications_to_post_[i].first; +void AXObjectCacheImpl::PostNotificationsAfterLayout(Document* document) { + NotificationVector old_notifications_to_post; + notifications_to_post_.swap(old_notifications_to_post); + for (auto& pair : old_notifications_to_post) { + AXObject* obj = pair.first; if (!obj->AXObjectID()) continue; @@ -860,6 +949,12 @@ if (obj->IsDetached()) continue; + ax::mojom::Event notification = pair.second; + if (obj->GetDocument() != document) { + notifications_to_post_.push_back(std::make_pair(obj, notification)); + continue; + } + #if DCHECK_IS_ON() // Make sure none of the layout views are in the process of being layed out. // Notifications should only be sent after the layoutObject has finished @@ -871,7 +966,6 @@ } #endif - ax::mojom::Event notification = notifications_to_post_[i].second; PostPlatformNotification(obj, notification); if (notification == ax::mojom::Event::kChildrenChanged && @@ -879,8 +973,6 @@ obj->LastKnownIsIgnoredValue() != obj->AccessibilityIsIgnored()) ChildrenChanged(obj->ParentObject()); } - - notifications_to_post_.clear(); } void AXObjectCacheImpl::PostNotification(LayoutObject* layout_object, @@ -904,8 +996,6 @@ modification_count_++; notifications_to_post_.push_back(std::make_pair(object, notification)); - if (!notification_post_timer_.IsActive()) - notification_post_timer_.StartOneShot(TimeDelta(), FROM_HERE); } bool AXObjectCacheImpl::IsAriaOwned(const AXObject* object) const { @@ -993,17 +1083,25 @@ void AXObjectCacheImpl::HandleAttributeChanged( const QualifiedName& attr_name, AccessibleNode* accessible_node) { + if (!accessible_node) + return; modification_count_++; if (AXObject* obj = Get(accessible_node)) PostNotification(obj, ax::mojom::Event::kAriaAttributeChanged); } -void AXObjectCacheImpl::HandleAriaExpandedChange(Node* node) { +void AXObjectCacheImpl::HandleAriaExpandedChangeWithCleanLayout(Node* node) { + if (!node) + return; + + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); if (AXObject* obj = GetOrCreate(node)) obj->HandleAriaExpandedChanged(); } -void AXObjectCacheImpl::HandleAriaSelectedChanged(Node* node) { +void AXObjectCacheImpl::HandleAriaSelectedChangedWithCleanLayout(Node* node) { + DCHECK(node); + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); AXObject* obj = Get(node); if (!obj) return; @@ -1036,7 +1134,10 @@ } } -void AXObjectCacheImpl::HandleActiveDescendantChanged(Node* node) { +void AXObjectCacheImpl::HandleActiveDescendantChangedWithCleanLayout( + Node* node) { + DCHECK(node); + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); // Changing the active descendant should trigger recomputing all // cached values even if it doesn't result in a notification, because // it can affect what's focusable or not. @@ -1050,10 +1151,12 @@ // as this may require a different subclass of AXObject. // Role changes are disallowed by the spec but we must handle it gracefully, see // https://www.w3.org/TR/wai-aria-1.1/#h-roles for more information. -void AXObjectCacheImpl::HandleRoleChange(Node* node) { +void AXObjectCacheImpl::HandleRoleChangeWithCleanLayout(Node* node) { if (!node) return; // Virtual AOM node. + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + // Invalidate the current object and make the parent reconsider its children. if (AXObject* obj = Get(node)) { // Save parent for later use. @@ -1079,81 +1182,108 @@ } } -void AXObjectCacheImpl::HandleRoleChangeIfNotEditable(Node* node) { +void AXObjectCacheImpl::HandleRoleChangeIfNotEditableWithCleanLayout( + Node* node) { if (!node) return; + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + // Do not invalidate object if the role doesn't actually change when it's a // text control, otherwise unique id will change on platform side, and confuse // some screen readers as user edits. // TODO(aleventhal) Ideally the text control check would be removed, and - // HandleRoleChange() and only ever invalidate when the role actually changes. - // For example: - // if (obj->RoleValue() == obj->ComputeAccessibilityRole()) return; - // However, doing that would require waiting for layout to complete, as - // ComputeAccessibilityRole() looks at layout objects. + // HandleRoleChangeWithCleanLayout() and only ever invalidate when the role + // actually changes. For example: + // if (obj->RoleValue() == obj->ComputeAccessibilityRole()) + // return; + // However, doing that would require + // waiting for layout to complete, as ComputeAccessibilityRole() looks at + // layout objects. if (AXObject* obj = Get(node)) { if (!obj->IsTextControl()) - HandleRoleChange(node); + HandleRoleChangeWithCleanLayout(node); } } -void AXObjectCacheImpl::HandleAttributeChanged(const QualifiedName& attr_name, +bool AXObjectCacheImpl::HandleAttributeChanged(const QualifiedName& attr_name, Element* element) { if (!element) - return; + return false; - if (element->GetDocument().NeedsLayoutTreeUpdateForNode(*element) || - element->NeedsDistributionRecalc()) { - attributes_changed_during_layout_.push_back( - std::make_pair(attr_name, element)); - return; + DeferTreeUpdate(&AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout, + attr_name, element); + + if (attr_name == kRoleAttr || attr_name == kTypeAttr || + attr_name == kSizeAttr || attr_name == kAltAttr || + attr_name == kTitleAttr || + (attr_name == kForAttr && IsHTMLLabelElement(*element)) || + attr_name == kIdAttr || attr_name == kTabindexAttr || + attr_name == kDisabledAttr) { + return true; } + return attr_name.LocalName().StartsWith("aria-"); +} - if (attr_name == kRoleAttr || attr_name == kTypeAttr) - HandleRoleChange(element); - else if (attr_name == kSizeAttr || attr_name == kAriaHaspopupAttr) - HandleRoleChangeIfNotEditable(element); // Role won't change on edits. - else if (attr_name == kAltAttr || attr_name == kTitleAttr) - TextChanged(element); - else if (attr_name == kForAttr && IsHTMLLabelElement(*element)) - LabelChanged(element); - else if (attr_name == kIdAttr) +void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout( + const QualifiedName& attr_name, + Element* element) { + DCHECK(element); + DCHECK(!element->GetDocument().NeedsLayoutTreeUpdateForNode(*element)); + if (attr_name == kRoleAttr || attr_name == kTypeAttr) { + HandleRoleChangeWithCleanLayout(element); + } else if (attr_name == kSizeAttr || attr_name == kAriaHaspopupAttr) { + // Role won't change on edits. + HandleRoleChangeIfNotEditableWithCleanLayout(element); + } else if (attr_name == kAltAttr || attr_name == kTitleAttr) { + TextChangedWithCleanLayout(element); + } else if (attr_name == kForAttr && IsHTMLLabelElement(*element)) { + LabelChangedWithCleanLayout(element); + } else if (attr_name == kIdAttr) { MaybeNewRelationTarget(element, Get(element)); - else if (attr_name == kTabindexAttr) - FocusableChanged(element); - else if (attr_name == kDisabledAttr) + } else if (attr_name == kTabindexAttr) { + FocusableChangedWithCleanLayout(element); + } else if (attr_name == kDisabledAttr) { MarkElementDirty(element, false); + } if (!attr_name.LocalName().StartsWith("aria-")) return; // Perform updates specific to each attribute. - if (attr_name == kAriaActivedescendantAttr) - HandleActiveDescendantChanged(element); - else if (attr_name == kAriaValuenowAttr || attr_name == kAriaValuetextAttr) + if (attr_name == kAriaActivedescendantAttr) { + HandleActiveDescendantChangedWithCleanLayout(element); + } else if (attr_name == kAriaValuenowAttr || + attr_name == kAriaValuetextAttr) { PostNotification(element, ax::mojom::Event::kValueChanged); - else if (attr_name == kAriaLabelAttr || attr_name == kAriaLabeledbyAttr || - attr_name == kAriaLabelledbyAttr) - TextChanged(element); - else if (attr_name == kAriaDescribedbyAttr) - TextChanged(element); // TODO do we need a DescriptionChanged() ? - else if (attr_name == kAriaCheckedAttr || attr_name == kAriaPressedAttr) + } else if (attr_name == kAriaLabelAttr || attr_name == kAriaLabeledbyAttr || + attr_name == kAriaLabelledbyAttr) { + TextChangedWithCleanLayout(element); + } else if (attr_name == kAriaDescribedbyAttr) { + // TODO do we need a DescriptionChanged() ? + TextChangedWithCleanLayout(element); + } else if (attr_name == kAriaCheckedAttr || attr_name == kAriaPressedAttr) { CheckedStateChanged(element); - else if (attr_name == kAriaSelectedAttr) - HandleAriaSelectedChanged(element); - else if (attr_name == kAriaExpandedAttr) - HandleAriaExpandedChange(element); - else if (attr_name == kAriaHiddenAttr) - ChildrenChanged(element->parentNode()); - else if (attr_name == kAriaInvalidAttr) + } else if (attr_name == kAriaSelectedAttr) { + HandleAriaSelectedChangedWithCleanLayout(element); + } else if (attr_name == kAriaExpandedAttr) { + HandleAriaExpandedChangeWithCleanLayout(element); + } else if (attr_name == kAriaHiddenAttr) { + ChildrenChangedWithCleanLayout(element->parentNode()); + } else if (attr_name == kAriaInvalidAttr) { PostNotification(element, ax::mojom::Event::kInvalidStatusChanged); - else if (attr_name == kAriaErrormessageAttr) + } else if (attr_name == kAriaErrormessageAttr) { MarkElementDirty(element, false); - else if (attr_name == kAriaOwnsAttr) - ChildrenChanged(element); - else + } else if (attr_name == kAriaOwnsAttr) { + ChildrenChangedWithCleanLayout(element); + // Ensure aria-owns update fires on original parent as well + if (AXObject* obj = GetOrCreate(element)) { + obj->ClearChildren(); + obj->AddChildren(); + } + } else { PostNotification(element, ax::mojom::Event::kAriaAttributeChanged); + } } void AXObjectCacheImpl::HandleAutofillStateChanged(Element* elem, @@ -1243,8 +1373,8 @@ MarkElementDirty(form_control, false); } -void AXObjectCacheImpl::LabelChanged(Element* element) { - TextChanged(ToHTMLLabelElement(element)->control()); +void AXObjectCacheImpl::LabelChangedWithCleanLayout(Element* element) { + TextChangedWithCleanLayout(ToHTMLLabelElement(element)->control()); } void AXObjectCacheImpl::InlineTextBoxesUpdated( @@ -1377,9 +1507,8 @@ return; AXObject* old_focused_object = Get(old_focused_node); - - PostPlatformNotification(old_focused_object, ax::mojom::Event::kBlur); - PostPlatformNotification(focused_object, ax::mojom::Event::kFocus); + PostNotification(old_focused_object, ax::mojom::Event::kBlur); + PostNotification(focused_object, ax::mojom::Event::kFocus); } void AXObjectCacheImpl::HandleInitialFocus() { @@ -1456,6 +1585,10 @@ void AXObjectCacheImpl::HandleLoadComplete(Document* document) { PostNotification(GetOrCreate(document), ax::mojom::Event::kLoadComplete); + // If load complete comes through after the lifecycle has finished, + // send notification immediately. + if (document->Lifecycle().GetState() >= DocumentLifecycle::kPaintClean) + PostNotificationsAfterLayout(document); AddPermissionStatusListener(); } @@ -1471,21 +1604,20 @@ return; if (obj->AccessibilityIsIgnored()) obj = obj->ParentObjectUnignored(); - PostPlatformNotification(obj, ax::mojom::Event::kScrolledToAnchor); + PostNotification(obj, ax::mojom::Event::kScrolledToAnchor); } void AXObjectCacheImpl::HandleScrollPositionChanged( LocalFrameView* frame_view) { AXObject* target_ax_object = GetOrCreate(frame_view->GetFrame().GetDocument()); - PostPlatformNotification(target_ax_object, - ax::mojom::Event::kScrollPositionChanged); + PostNotification(target_ax_object, ax::mojom::Event::kScrollPositionChanged); } void AXObjectCacheImpl::HandleScrollPositionChanged( LayoutObject* layout_object) { - PostPlatformNotification(GetOrCreate(layout_object), - ax::mojom::Event::kScrollPositionChanged); + PostNotification(GetOrCreate(layout_object), + ax::mojom::Event::kScrollPositionChanged); } const AtomicString& AXObjectCacheImpl::ComputedRoleForNode(Node* node) { @@ -1513,7 +1645,7 @@ hit->GetLayoutObject()->IsLayoutEmbeddedContent()) return; - PostPlatformNotification(hit, ax::mojom::Event::kHover); + PostNotification(hit, ax::mojom::Event::kHover); } } @@ -1585,6 +1717,16 @@ WrapPersistent(this))); } +void AXObjectCacheImpl::WillStartLifecycleUpdate(const LocalFrameView&) {} + +void AXObjectCacheImpl::DidFinishLifecycleUpdate(const LocalFrameView& view) { + Document* document = view.GetFrame().GetDocument(); + if (document) { + ProcessUpdatesAfterLayout(*document); + PostNotificationsAfterLayout(document); + } +} + void AXObjectCacheImpl::ContextDestroyed(ExecutionContext*) { permission_service_.reset(); permission_observer_binding_.Close(); @@ -1597,9 +1739,7 @@ visitor->Trace(objects_); visitor->Trace(notifications_to_post_); - visitor->Trace(nodes_changed_during_layout_); - visitor->Trace(attributes_changed_during_layout_); - + visitor->Trace(documents_); AXObjectCache::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h index 57af4fe..d65b44f5 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -30,6 +30,8 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_OBJECT_CACHE_IMPL_H_ #include <memory> +#include <utility> +#include <vector> #include "base/macros.h" #include "mojo/public/cpp/bindings/binding.h" @@ -37,6 +39,7 @@ #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h" #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/modules/accessibility/ax_object.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -53,7 +56,8 @@ // This class should only be used from inside the accessibility directory. class MODULES_EXPORT AXObjectCacheImpl : public AXObjectCacheBase, - public mojom::blink::PermissionObserver { + public mojom::blink::PermissionObserver, + public LocalFrameView::LifecycleNotificationObserver { public: static AXObjectCache* Create(Document&); @@ -66,6 +70,10 @@ void Dispose() override; + // Register/remove popups + void InitializePopup(Document* document) override; + void DisposePopup(Document* document) override; + // // Iterators. // @@ -98,14 +106,14 @@ // changed. void TextChanged(LayoutObject*) override; void TextChanged(AXObject*, Node* optional_node = nullptr); - void FocusableChanged(Element* element); + void FocusableChangedWithCleanLayout(Element* element); void DocumentTitleChanged() override; // Called when a node has just been attached, so we can make sure we have the // right subclass of AXObject. void UpdateCacheAfterNodeIsAttached(Node*) override; void DidInsertChildrenOfNode(Node*) override; - void HandleAttributeChanged(const QualifiedName& attr_name, + bool HandleAttributeChanged(const QualifiedName& attr_name, Element*) override; void HandleAutofillStateChanged(Element*, bool) override; void HandleValidationMessageVisibilityChanged( @@ -175,11 +183,11 @@ void MaybeNewRelationTarget(Node* node, AXObject* obj); - void HandleActiveDescendantChanged(Node*); - void HandleRoleChange(Node*); - void HandleRoleChangeIfNotEditable(Node*); - void HandleAriaExpandedChange(Node*); - void HandleAriaSelectedChanged(Node*); + void HandleActiveDescendantChangedWithCleanLayout(Node*); + void HandleRoleChangeWithCleanLayout(Node*); + void HandleRoleChangeIfNotEditableWithCleanLayout(Node*); + void HandleAriaExpandedChangeWithCleanLayout(Node*); + void HandleAriaSelectedChangedWithCleanLayout(Node*); bool AccessibilityEnabled(); bool InlineTextBoxAccessibilityEnabled(); @@ -235,9 +243,13 @@ // For built-in HTML form validation messages. AXObject* ValidationMessageObjectIfInvalid(); + // LifecycleNotificationObserver overrides. + void WillStartLifecycleUpdate(const LocalFrameView&) override; + void DidFinishLifecycleUpdate(const LocalFrameView&) override; + protected: void PostPlatformNotification(AXObject*, ax::mojom::Event); - void LabelChanged(Element*); + void LabelChangedWithCleanLayout(Element*); AXObject* CreateFromRenderer(LayoutObject*); AXObject* CreateFromNode(Node*); @@ -269,10 +281,10 @@ bool has_been_disposed_ = false; #endif - TaskRunnerTimer<AXObjectCacheImpl> notification_post_timer_; - HeapVector<std::pair<Member<AXObject>, ax::mojom::Event>> - notifications_to_post_; - void NotificationPostTimerFired(TimerBase*); + typedef HeapVector<std::pair<Member<AXObject>, ax::mojom::Event>> + NotificationVector; + NotificationVector notifications_to_post_; + void PostNotificationsAfterLayout(Document*); // ContextLifecycleObserver overrides. void ContextDestroyed(ExecutionContext*) override; @@ -306,6 +318,25 @@ AXObject* GetOrCreateValidationMessageObject(); void RemoveValidationMessageObject(); + // Enqueue a callback to the given method to be run after layout is + // complete. + void DeferTreeUpdate(void (AXObjectCacheImpl::*method)(Node*), Node* node); + void DeferTreeUpdate(void (AXObjectCacheImpl::*method)(const QualifiedName&, + Element* element), + const QualifiedName& attr_name, + Element* element); + void DeferTreeUpdate(void (AXObjectCacheImpl::*method)(Node*, AXObject*), + Node* node, + AXObject* obj); + + void DeferTreeUpdateInternal(Node* node, base::OnceClosure callback); + + void SelectionChangedWithCleanLayout(Node* node); + void TextChangedWithCleanLayout(Node* node); + void ChildrenChangedWithCleanLayout(Node* node); + void HandleAttributeChangedWithCleanLayout(const QualifiedName& attr_name, + Element* element); + // Whether the user has granted permission for the user to install event // listeners for accessibility events using the AOM. mojom::PermissionStatus accessibility_event_permission_; @@ -314,9 +345,11 @@ mojom::blink::PermissionServicePtr permission_service_; mojo::Binding<mojom::blink::PermissionObserver> permission_observer_binding_; - VectorOf<Node> nodes_changed_during_layout_; - typedef VectorOfPairs<QualifiedName, Element> AttributesChangedVector; - AttributesChangedVector attributes_changed_during_layout_; + // The main document, plus any page popups. + HeapHashSet<WeakMember<Document>> documents_; + typedef std::vector<std::pair<WeakPersistent<Node>, base::OnceClosure>> + TreeUpdateCallbackQueue; + TreeUpdateCallbackQueue tree_update_callback_queue_; DISALLOW_COPY_AND_ASSIGN(AXObjectCacheImpl); };
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc index 3b0ae5b..a78b8ac 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -69,11 +69,11 @@ const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument()); ASSERT_TRUE(ax_selection.IsValid()); - EXPECT_TRUE(ax_selection.Base().IsTextPosition()); + ASSERT_TRUE(ax_selection.Base().IsTextPosition()); EXPECT_EQ(ax_static_text_1, ax_selection.Base().ContainerObject()); EXPECT_EQ(3, ax_selection.Base().TextOffset()); - EXPECT_FALSE(ax_selection.Extent().IsTextPosition()); + ASSERT_FALSE(ax_selection.Extent().IsTextPosition()); EXPECT_EQ(ax_paragraph_2, ax_selection.Extent().ContainerObject()); EXPECT_EQ(1, ax_selection.Extent().ChildIndex()); @@ -412,10 +412,10 @@ // The extended selection should start after the children of the paragraph // before the first aria-hidden element and end right before the paragraph // after the last aria-hidden element. - EXPECT_FALSE(ax_selection_extend.Base().IsTextPosition()); + ASSERT_FALSE(ax_selection_extend.Base().IsTextPosition()); EXPECT_EQ(ax_before, ax_selection_extend.Base().ContainerObject()); EXPECT_EQ(1, ax_selection_extend.Base().ChildIndex()); - EXPECT_FALSE(ax_selection_extend.Extent().IsTextPosition()); + ASSERT_FALSE(ax_selection_extend.Extent().IsTextPosition()); EXPECT_EQ(ax_main, ax_selection_extend.Extent().ContainerObject()); EXPECT_EQ(ax_after->IndexInParent(), ax_selection_extend.Extent().ChildIndex()); @@ -566,10 +566,10 @@ AXSelection::FromCurrentSelection(ToTextControl(*input)); ASSERT_TRUE(ax_selection.IsValid()); - EXPECT_TRUE(ax_selection.Base().IsTextPosition()); + ASSERT_TRUE(ax_selection.Base().IsTextPosition()); EXPECT_EQ(ax_input, ax_selection.Base().ContainerObject()); EXPECT_EQ(0, ax_selection.Base().TextOffset()); - EXPECT_TRUE(ax_selection.Extent().IsTextPosition()); + ASSERT_TRUE(ax_selection.Extent().IsTextPosition()); EXPECT_EQ(ax_input, ax_selection.Extent().ContainerObject()); EXPECT_EQ(18, ax_selection.Extent().TextOffset()); } @@ -610,14 +610,182 @@ AXSelection::FromCurrentSelection(ToTextControl(*textarea)); ASSERT_TRUE(ax_selection.IsValid()); - EXPECT_TRUE(ax_selection.Base().IsTextPosition()); + ASSERT_TRUE(ax_selection.Base().IsTextPosition()); EXPECT_EQ(ax_textarea, ax_selection.Base().ContainerObject()); EXPECT_EQ(0, ax_selection.Base().TextOffset()); - EXPECT_TRUE(ax_selection.Extent().IsTextPosition()); + ASSERT_TRUE(ax_selection.Extent().IsTextPosition()); EXPECT_EQ(ax_textarea, ax_selection.Extent().ContainerObject()); EXPECT_EQ(53, ax_selection.Extent().TextOffset()); } +TEST_F(AccessibilitySelectionTest, + FromCurrentSelectionInContentEditableWithSoftLineBreaks) { + GetPage().GetSettings().SetScriptEnabled(true); + SetBodyInnerHTML(R"HTML( + <div id="contenteditable" role="textbox" contenteditable + style="max-width: 5px; overflow-wrap: normal;"> + Inside contenteditable field. + </div> + )HTML"); + + ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid()); + + // We want to select all the text in the content editable, but not the + // editable itself. + Element* const script_element = + GetDocument().CreateRawElement(html_names::kScriptTag); + ASSERT_NE(nullptr, script_element); + script_element->setTextContent(R"SCRIPT( + const contenteditable = document.querySelector('div[contenteditable]'); + contenteditable.focus(); + const firstLine = contenteditable.firstChild; + const lastLine = contenteditable.lastChild; + const range = document.createRange(); + range.setStart(firstLine, 0); + range.setEnd(lastLine, lastLine.nodeValue.length); + const selection = getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + )SCRIPT"); + GetDocument().body()->AppendChild(script_element); + UpdateAllLifecyclePhasesForTest(); + + const AXObject* ax_contenteditable = + GetAXObjectByElementId("contenteditable"); + ASSERT_NE(nullptr, ax_contenteditable); + ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue()); + const AXObject* ax_static_text = ax_contenteditable->FirstChild(); + ASSERT_NE(nullptr, ax_static_text); + // Guard against the structure of the accessibility tree unexpectedly + // changing, causing a hard to debug test failure. + ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue()) + << "A content editable with only text inside it should have static text " + "children."; + // Guard against both ComputedName().length() and selection extent offset + // returning 0. + ASSERT_LT(0u, ax_static_text->ComputedName().length()); + + const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument()); + ASSERT_TRUE(ax_selection.IsValid()); + + ASSERT_TRUE(ax_selection.Base().IsTextPosition()); + EXPECT_EQ(ax_static_text, ax_selection.Base().ContainerObject()); + EXPECT_EQ(0, ax_selection.Base().TextOffset()); + ASSERT_TRUE(ax_selection.Extent().IsTextPosition()); + EXPECT_EQ(ax_static_text, ax_selection.Extent().ContainerObject()); + EXPECT_EQ(ax_static_text->ComputedName().length(), + unsigned{ax_selection.Extent().TextOffset()}); +} + +TEST_F(AccessibilitySelectionTest, + FromCurrentSelectionInContentEditableSelectFirstSoftLineBreak) { + GetPage().GetSettings().SetScriptEnabled(true); + // There should be no white space between the opening tag of the content + // editable and the text inside it, otherwise selection offsets would be + // wrong. + SetBodyInnerHTML(R"HTML( + <div id="contenteditable" role="textbox" contenteditable + style="max-width: 5px; overflow-wrap: normal;">Line one. + </div> + )HTML"); + + ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid()); + + Element* const script_element = + GetDocument().CreateRawElement(html_names::kScriptTag); + ASSERT_NE(nullptr, script_element); + script_element->setTextContent(R"SCRIPT( + const contenteditable = document.querySelector('div[contenteditable]'); + contenteditable.focus(); + const text = contenteditable.firstChild; + const range = document.createRange(); + range.setStart(text, 4); + range.setEnd(text, 4); + const selection = getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + selection.modify('extend', 'forward', 'character'); + )SCRIPT"); + GetDocument().body()->AppendChild(script_element); + UpdateAllLifecyclePhasesForTest(); + + const AXObject* ax_contenteditable = + GetAXObjectByElementId("contenteditable"); + ASSERT_NE(nullptr, ax_contenteditable); + ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue()); + const AXObject* ax_static_text = ax_contenteditable->FirstChild(); + ASSERT_NE(nullptr, ax_static_text); + // Guard against the structure of the accessibility tree unexpectedly + // changing, causing a hard to debug test failure. + ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue()) + << "A content editable with only text inside it should have static text " + "children."; + + const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument()); + ASSERT_TRUE(ax_selection.IsValid()); + + ASSERT_TRUE(ax_selection.Base().IsTextPosition()); + EXPECT_EQ(ax_static_text, ax_selection.Base().ContainerObject()); + EXPECT_EQ(4, ax_selection.Base().TextOffset()); + ASSERT_TRUE(ax_selection.Extent().IsTextPosition()); + EXPECT_EQ(ax_static_text, ax_selection.Extent().ContainerObject()); + EXPECT_EQ(5, ax_selection.Extent().TextOffset()); +} + +TEST_F(AccessibilitySelectionTest, + FromCurrentSelectionInContentEditableSelectFirstHardLineBreak) { + GetPage().GetSettings().SetScriptEnabled(true); + // There should be no white space between the opening tag of the content + // editable and the text inside it, otherwise selection offsets would be + // wrong. + SetBodyInnerHTML(R"HTML( + <div id="contenteditable" role="textbox" contenteditable + style="max-width: 5px; overflow-wrap: normal;">Inside<br>contenteditable. + </div> + )HTML"); + + ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid()); + + Element* const script_element = + GetDocument().CreateRawElement(html_names::kScriptTag); + ASSERT_NE(nullptr, script_element); + script_element->setTextContent(R"SCRIPT( + const contenteditable = document.querySelector('div[contenteditable]'); + contenteditable.focus(); + const firstLine = contenteditable.firstChild; + const range = document.createRange(); + range.setStart(firstLine, 6); + range.setEnd(firstLine, 6); + const selection = getSelection(); + selection.removeAllRanges(); + selection.addRange(range); + selection.modify('extend', 'forward', 'character'); + )SCRIPT"); + GetDocument().body()->AppendChild(script_element); + UpdateAllLifecyclePhasesForTest(); + + const AXObject* ax_contenteditable = + GetAXObjectByElementId("contenteditable"); + ASSERT_NE(nullptr, ax_contenteditable); + ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue()); + ASSERT_EQ(3, ax_contenteditable->ChildCount()) + << "The content editable should have two lines with a line break between " + "them."; + const AXObject* ax_static_text_2 = ax_contenteditable->Children()[2]; + ASSERT_NE(nullptr, ax_static_text_2); + ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text_2->RoleValue()); + + const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument()); + ASSERT_TRUE(ax_selection.IsValid()); + + ASSERT_FALSE(ax_selection.Base().IsTextPosition()); + EXPECT_EQ(ax_contenteditable, ax_selection.Base().ContainerObject()); + EXPECT_EQ(1, ax_selection.Base().ChildIndex()); + ASSERT_TRUE(ax_selection.Extent().IsTextPosition()); + EXPECT_EQ(ax_static_text_2, ax_selection.Extent().ContainerObject()); + EXPECT_EQ(0, ax_selection.Extent().TextOffset()); +} + TEST_F(AccessibilitySelectionTest, ClearCurrentSelectionInTextField) { GetPage().GetSettings().SetScriptEnabled(true); SetBodyInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h b/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h index 98309d2..72f8261b 100644 --- a/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h +++ b/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ATTESTATION_RESPONSE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ATTESTATION_RESPONSE_H_ -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom-blink.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" #include "third_party/blink/renderer/modules/credentialmanager/authenticator_response.h" #include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h index d442236..0228425 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h +++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_CREDENTIAL_MANAGER_PROXY_H_ #include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom-blink.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h index 5e35519..cb5ee7e 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h +++ b/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_CREDENTIAL_MANAGER_TYPE_CONVERTERS_H_ #include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h" -#include "third_party/blink/public/platform/modules/webauthn/authenticator.mojom-blink.h" +#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5 index d8974877..5e0c0eb2 100644 --- a/third_party/blink/renderer/modules/event_target_modules_names.json5 +++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -17,7 +17,7 @@ "MediaKeySession", "FileWriter", "HID", - "IdleStatus", + "IdleDetector", "ImageCapture", "IDBDatabase", "IDBOpenDBRequest",
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc index ef79de3..b60cea9 100644 --- a/third_party/blink/renderer/modules/exported/web_ax_object.cc +++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -96,19 +96,20 @@ } }; -#if DCHECK_IS_ON() -// It's not safe to call some WebAXObject APIs if a layout is pending. -// Clients should call updateLayoutAndCheckValidity first. static bool IsLayoutClean(Document* document) { if (!document || !document->View()) return false; - return document->Lifecycle().GetState() >= DocumentLifecycle::kLayoutClean || - ((document->Lifecycle().GetState() == DocumentLifecycle::kStyleClean || - document->Lifecycle().GetState() == - DocumentLifecycle::kLayoutSubtreeChangeClean) && - !document->View()->NeedsLayout()); + if (document->View()->NeedsLayout()) + return false; + DocumentLifecycle::LifecycleState state = document->Lifecycle().GetState(); + if (state >= DocumentLifecycle::kLayoutClean || + state == DocumentLifecycle::kStyleClean || + state == DocumentLifecycle::kLayoutSubtreeChangeClean) { + return true; + } + + return false; } -#endif void WebAXObject::Reset() { private_.Reset(); @@ -146,8 +147,11 @@ bool WebAXObject::UpdateLayoutAndCheckValidity() { if (!IsDetached()) { Document* document = private_->GetDocument(); - if (!document || !document->View() || - !document->View()->UpdateLifecycleToCompositingCleanPlusScrolling()) + if (!document || !document->View()) + return false; + if (IsLayoutClean(document)) + return true; + if (!document->View()->UpdateLifecycleToCompositingCleanPlusScrolling()) return false; } @@ -973,6 +977,13 @@ return private_->Placeholder(name_from); } +WebString WebAXObject::Title(ax::mojom::NameFrom name_from) const { + if (IsDetached()) + return WebString(); + + return private_->Title(name_from); +} + bool WebAXObject::SupportsRangeValue() const { if (IsDetached()) return false;
diff --git a/third_party/blink/renderer/modules/filesystem/async_callback_helper.h b/third_party/blink/renderer/modules/filesystem/async_callback_helper.h index 5114722..1d97d9bc 100644 --- a/third_party/blink/renderer/modules/filesystem/async_callback_helper.h +++ b/third_party/blink/renderer/modules/filesystem/async_callback_helper.h
@@ -69,6 +69,26 @@ }, WrapPersistentIfNeeded(resolver)); } + + // The two methods below are not templetized, to be used exclusively for + // VoidCallbacks. + static base::OnceCallback<void()> VoidSuccessCallback( + V8VoidCallback* success_callback) { + auto success_callback_wrapper = WTF::Bind( + [](V8PersistentCallbackInterface<V8VoidCallback>* persistent_callback) { + persistent_callback->InvokeAndReportException(nullptr); + }, + WrapPersistentIfNeeded( + ToV8PersistentCallbackInterface(success_callback))); + return success_callback_wrapper; + } + + static base::OnceCallback<void()> VoidSuccessPromise( + ScriptPromiseResolver* resolver) { + return WTF::Bind( + [](ScriptPromiseResolver* resolver) { resolver->Resolve(); }, + WrapPersistentIfNeeded(resolver)); + } }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/directory_entry.cc b/third_party/blink/renderer/modules/filesystem/directory_entry.cc index ef10104..e14b35c 100644 --- a/third_party/blink/renderer/modules/filesystem/directory_entry.cc +++ b/third_party/blink/renderer/modules/filesystem/directory_entry.cc
@@ -76,9 +76,13 @@ void DirectoryEntry::removeRecursively(V8VoidCallback* success_callback, V8ErrorCallback* error_callback) const { - file_system_->RemoveRecursively( - this, VoidCallbacks::OnDidSucceedV8Impl::Create(success_callback), - ScriptErrorCallback::Wrap(error_callback)); + auto success_callback_wrapper = + AsyncCallbackHelper::VoidSuccessCallback(success_callback); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + + file_system_->RemoveRecursively(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); } void DirectoryEntry::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc b/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc index b707ba1..89d669c6 100644 --- a/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc +++ b/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc
@@ -87,8 +87,12 @@ void DirectoryEntrySync::removeRecursively(ExceptionState& exception_state) { auto* sync_helper = MakeGarbageCollected<VoidCallbacksSyncHelper>(); - file_system_->RemoveRecursively(this, nullptr, - sync_helper->GetErrorCallback(), + + auto error_callback_wrapper = WTF::Bind(&VoidCallbacksSyncHelper::OnError, + WrapPersistentIfNeeded(sync_helper)); + + file_system_->RemoveRecursively(this, VoidCallbacks::SuccessCallback(), + std::move(error_callback_wrapper), DOMFileSystemBase::kSynchronous); sync_helper->GetResultOrThrow(exception_state); }
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system.cc b/third_party/blink/renderer/modules/filesystem/dom_file_system.cc index 91c2dcf..f9aa652 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_file_system.cc +++ b/third_party/blink/renderer/modules/filesystem/dom_file_system.cc
@@ -160,27 +160,29 @@ void DOMFileSystem::CreateWriter( const FileEntry* file_entry, - FileWriterCallbacks::OnDidCreateFileWriterCallback* success_callback, - ErrorCallbackBase* error_callback) { + FileWriterCallbacks::SuccessCallback success_callback, + FileWriterCallbacks::ErrorCallback error_callback) { DCHECK(file_entry); FileWriter* file_writer = FileWriter::Create(GetExecutionContext()); auto callbacks = std::make_unique<FileWriterCallbacks>( - file_writer, success_callback, error_callback, context_); + file_writer, std::move(success_callback), std::move(error_callback), + context_); FileSystemDispatcher::From(context_).InitializeFileWriter( CreateFileSystemURL(file_entry), std::move(callbacks)); } void DOMFileSystem::CreateFile( const FileEntry* file_entry, - SnapshotFileCallback::OnDidCreateSnapshotFileCallback* success_callback, - ErrorCallbackBase* error_callback) { + SnapshotFileCallback::SuccessCallback success_callback, + SnapshotFileCallback::ErrorCallback error_callback) { KURL file_system_url = CreateFileSystemURL(file_entry); FileSystemDispatcher::From(context_).CreateSnapshotFile( - file_system_url, std::make_unique<SnapshotFileCallback>( - this, file_entry->name(), file_system_url, - success_callback, error_callback, context_)); + file_system_url, + std::make_unique<SnapshotFileCallback>( + this, file_entry->name(), file_system_url, + std::move(success_callback), std::move(error_callback), context_)); } void DOMFileSystem::ScheduleCallback(ExecutionContext* execution_context,
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system.h b/third_party/blink/renderer/modules/filesystem/dom_file_system.h index 9fe4bcc..8d8e9da6 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_file_system.h +++ b/third_party/blink/renderer/modules/filesystem/dom_file_system.h
@@ -89,11 +89,11 @@ bool HasPendingActivity() const final; void CreateWriter(const FileEntry*, - FileWriterCallbacks::OnDidCreateFileWriterCallback*, - ErrorCallbackBase*); + FileWriterCallbacks::SuccessCallback, + FileWriterCallbacks::ErrorCallback); void CreateFile(const FileEntry*, - SnapshotFileCallback::OnDidCreateSnapshotFileCallback*, - ErrorCallbackBase*); + SnapshotFileCallback::SuccessCallback, + SnapshotFileCallback::ErrorCallback); // Schedule a callback. This should not cross threads (should be called on the // same context thread).
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system_base.cc b/third_party/blink/renderer/modules/filesystem/dom_file_system_base.cc index c99739c4..dd08da5e 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_file_system_base.cc +++ b/third_party/blink/renderer/modules/filesystem/dom_file_system_base.cc
@@ -314,20 +314,20 @@ dispatcher.Copy(src, dest, std::move(callbacks)); } -void DOMFileSystemBase::Remove( - const EntryBase* entry, - VoidCallbacks::OnDidSucceedCallback* success_callback, - ErrorCallbackBase* error_callback, - SynchronousType synchronous_type) { +void DOMFileSystemBase::Remove(const EntryBase* entry, + VoidCallbacks::SuccessCallback success_callback, + ErrorCallback error_callback, + SynchronousType synchronous_type) { DCHECK(entry); // We don't allow calling remove() on the root directory. if (entry->fullPath() == String(DOMFilePath::kRoot)) { - ReportError(error_callback, base::File::FILE_ERROR_INVALID_OPERATION); + ReportError(std::move(error_callback), + base::File::FILE_ERROR_INVALID_OPERATION); return; } auto callbacks = std::make_unique<VoidCallbacks>( - success_callback, error_callback, context_, this); + std::move(success_callback), std::move(error_callback), context_, this); const KURL& url = CreateFileSystemURL(entry); FileSystemDispatcher& dispatcher = FileSystemDispatcher::From(context_); if (synchronous_type == kSynchronous) @@ -338,19 +338,20 @@ void DOMFileSystemBase::RemoveRecursively( const EntryBase* entry, - VoidCallbacks::OnDidSucceedCallback* success_callback, - ErrorCallbackBase* error_callback, + VoidCallbacks::SuccessCallback success_callback, + ErrorCallback error_callback, SynchronousType synchronous_type) { DCHECK(entry); DCHECK(entry->isDirectory()); // We don't allow calling remove() on the root directory. if (entry->fullPath() == String(DOMFilePath::kRoot)) { - ReportError(error_callback, base::File::FILE_ERROR_INVALID_OPERATION); + ReportError(std::move(error_callback), + base::File::FILE_ERROR_INVALID_OPERATION); return; } auto callbacks = std::make_unique<VoidCallbacks>( - success_callback, error_callback, context_, this); + std::move(success_callback), std::move(error_callback), context_, this); const KURL& url = CreateFileSystemURL(entry); FileSystemDispatcher& dispatcher = FileSystemDispatcher::From(context_); if (synchronous_type == kSynchronous)
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h b/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h index 4631ce6..d5c7e33 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h +++ b/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h
@@ -126,12 +126,12 @@ EntryCallbacks::ErrorCallback, SynchronousType = kAsynchronous); void Remove(const EntryBase*, - VoidCallbacks::OnDidSucceedCallback*, - ErrorCallbackBase*, + VoidCallbacks::SuccessCallback, + VoidCallbacks::ErrorCallback, SynchronousType = kAsynchronous); void RemoveRecursively(const EntryBase*, - VoidCallbacks::OnDidSucceedCallback*, - ErrorCallbackBase*, + VoidCallbacks::SuccessCallback, + VoidCallbacks::ErrorCallback, SynchronousType = kAsynchronous); void GetParent(const EntryBase*, EntryCallbacks::SuccessCallback,
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc b/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc index 7303f7b..a06af476 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc +++ b/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc
@@ -166,9 +166,17 @@ FileWriterSync* file_writer = FileWriterSync::Create(context_); auto* sync_helper = MakeGarbageCollected<FileWriterCallbacksSyncHelper>(); + + auto success_callback_wrapper = + WTF::Bind(&FileWriterCallbacksSyncHelper::OnSuccess, + WrapPersistentIfNeeded(sync_helper)); + auto error_callback_wrapper = + WTF::Bind(&FileWriterCallbacksSyncHelper::OnError, + WrapPersistentIfNeeded(sync_helper)); + auto callbacks = std::make_unique<FileWriterCallbacks>( - file_writer, sync_helper->GetSuccessCallback(), - sync_helper->GetErrorCallback(), context_); + file_writer, std::move(success_callback_wrapper), + std::move(error_callback_wrapper), context_); FileSystemDispatcher::From(context_).InitializeFileWriterSync( CreateFileSystemURL(file_entry), std::move(callbacks));
diff --git a/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc b/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc index b0cb444..d8f4edd 100644 --- a/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc +++ b/third_party/blink/renderer/modules/filesystem/dom_window_file_system.cc
@@ -125,11 +125,16 @@ return; } + auto success_callback_wrapper = + AsyncCallbackHelper::SuccessCallback<Entry>(success_callback); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + LocalFileSystem::From(*document)->ResolveURL( document, completed_url, - std::make_unique<ResolveURICallbacks>( - ResolveURICallbacks::OnDidGetEntryV8Impl::Create(success_callback), - ScriptErrorCallback::Wrap(error_callback), document), + std::make_unique<ResolveURICallbacks>(std::move(success_callback_wrapper), + std::move(error_callback_wrapper), + document), LocalFileSystem::kAsynchronous); }
diff --git a/third_party/blink/renderer/modules/filesystem/entry.cc b/third_party/blink/renderer/modules/filesystem/entry.cc index 83f2cd8c..b2b0cd9 100644 --- a/third_party/blink/renderer/modules/filesystem/entry.cc +++ b/third_party/blink/renderer/modules/filesystem/entry.cc
@@ -116,9 +116,14 @@ UseCounter::Count(ExecutionContext::From(script_state), WebFeature::kEntry_Remove_Method_IsolatedFileSystem); } - file_system_->Remove( - this, VoidCallbacks::OnDidSucceedV8Impl::Create(success_callback), - ScriptErrorCallback::Wrap(error_callback)); + + auto success_callback_wrapper = + AsyncCallbackHelper::VoidSuccessCallback(success_callback); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + + file_system_->Remove(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); } void Entry::getParent(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/filesystem/entry_sync.cc b/third_party/blink/renderer/modules/filesystem/entry_sync.cc index f9036ab..77271db 100644 --- a/third_party/blink/renderer/modules/filesystem/entry_sync.cc +++ b/third_party/blink/renderer/modules/filesystem/entry_sync.cc
@@ -100,7 +100,12 @@ void EntrySync::remove(ExceptionState& exception_state) const { auto* sync_helper = MakeGarbageCollected<VoidCallbacksSyncHelper>(); - file_system_->Remove(this, nullptr, sync_helper->GetErrorCallback(), + + auto error_callback_wrapper = WTF::Bind(&VoidCallbacksSyncHelper::OnError, + WrapPersistentIfNeeded(sync_helper)); + + file_system_->Remove(this, VoidCallbacks::SuccessCallback(), + std::move(error_callback_wrapper), DOMFileSystemBase::kSynchronous); sync_helper->GetResultOrThrow(exception_state); }
diff --git a/third_party/blink/renderer/modules/filesystem/file_entry.cc b/third_party/blink/renderer/modules/filesystem/file_entry.cc index 08c93bd..1dc28d98 100644 --- a/third_party/blink/renderer/modules/filesystem/file_entry.cc +++ b/third_party/blink/renderer/modules/filesystem/file_entry.cc
@@ -31,8 +31,10 @@ #include "third_party/blink/renderer/modules/filesystem/file_entry.h" #include "third_party/blink/renderer/core/fileapi/file.h" +#include "third_party/blink/renderer/modules/filesystem/async_callback_helper.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" #include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h" +#include "third_party/blink/renderer/modules/filesystem/file_writer.h" namespace blink { @@ -41,20 +43,32 @@ void FileEntry::createWriter(V8FileWriterCallback* success_callback, V8ErrorCallback* error_callback) { - filesystem()->CreateWriter( - this, - FileWriterCallbacks::OnDidCreateFileWriterV8Impl::Create( - success_callback), - ScriptErrorCallback::Wrap(error_callback)); + auto success_callback_wrapper = WTF::Bind( + [](V8PersistentCallbackInterface<V8FileWriterCallback>* + persistent_callback, + FileWriterBase* file_writer) { + // The call sites must pass a FileWriter in |file_writer|. + persistent_callback->InvokeAndReportException( + nullptr, static_cast<FileWriter*>(file_writer)); + }, + WrapPersistentIfNeeded( + ToV8PersistentCallbackInterface(success_callback))); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + + filesystem()->CreateWriter(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); } void FileEntry::file(V8FileCallback* success_callback, V8ErrorCallback* error_callback) { - filesystem()->CreateFile( - this, - SnapshotFileCallback::OnDidCreateSnapshotFileV8Impl::Create( - success_callback), - ScriptErrorCallback::Wrap(error_callback)); + auto success_callback_wrapper = + AsyncCallbackHelper::SuccessCallback<File>(success_callback); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + + filesystem()->CreateFile(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); } void FileEntry::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_base_handle.cc b/third_party/blink/renderer/modules/filesystem/file_system_base_handle.cc index 11c6785..8dc6755 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_base_handle.cc +++ b/third_party/blink/renderer/modules/filesystem/file_system_base_handle.cc
@@ -62,10 +62,13 @@ ScriptPromise FileSystemBaseHandle::remove(ScriptState* script_state) { auto* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise result = resolver->Promise(); - filesystem()->Remove( - this, - MakeGarbageCollected<VoidCallbacks::OnDidSucceedPromiseImpl>(resolver), - MakeGarbageCollected<PromiseErrorCallback>(resolver)); + + auto success_callback_wrapper = + AsyncCallbackHelper::VoidSuccessPromise(resolver); + auto error_callback_wrapper = AsyncCallbackHelper::ErrorPromise(resolver); + + filesystem()->Remove(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); return result; }
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc index 53495b1..ab582ba5 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc +++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
@@ -113,15 +113,6 @@ // EntryCallbacks ------------------------------------------------------------- -void EntryCallbacks::OnDidGetEntryV8Impl::Trace(blink::Visitor* visitor) { - visitor->Trace(callback_); - OnDidGetEntryCallback::Trace(visitor); -} - -void EntryCallbacks::OnDidGetEntryV8Impl::OnSuccess(Entry* entry) { - callback_->InvokeAndReportException(nullptr, entry); -} - EntryCallbacks::EntryCallbacks(SuccessCallback success_callback, ErrorCallback error_callback, ExecutionContext* context, @@ -205,7 +196,9 @@ ErrorCallback error_callback, ExecutionContext* context, mojom::blink::FileSystemType type) - : FileSystemCallbacksBase(/*error_callback=*/nullptr, nullptr, context), + : FileSystemCallbacksBase(/*error_callback=*/nullptr, + /*file_system=*/nullptr, + context), success_callback_(std::move(success_callback)), error_callback_(std::move(error_callback)), type_(type) {} @@ -229,12 +222,14 @@ // ResolveURICallbacks -------------------------------------------------------- -ResolveURICallbacks::ResolveURICallbacks( - OnDidGetEntryCallback* success_callback, - ErrorCallbackBase* error_callback, - ExecutionContext* context) - : FileSystemCallbacksBase(error_callback, nullptr, context), - success_callback_(success_callback) { +ResolveURICallbacks::ResolveURICallbacks(SuccessCallback success_callback, + ErrorCallback error_callback, + ExecutionContext* context) + : FileSystemCallbacksBase(/*error_callback=*/nullptr, + /*file_system=*/nullptr, + context), + success_callback_(std::move(success_callback)), + error_callback_(std::move(error_callback)) { DCHECK(success_callback_); } @@ -259,14 +254,15 @@ ? static_cast<Entry*>( DirectoryEntry::Create(filesystem, absolute_path)) : static_cast<Entry*>(FileEntry::Create(filesystem, absolute_path)); - success_callback_.Release()->OnSuccess(entry); + + std::move(success_callback_).Run(entry); } void ResolveURICallbacks::DidFail(base::File::Error error) { if (!error_callback_) return; - error_callback_.Release()->Invoke(error); + std::move(error_callback_).Run(error); } // MetadataCallbacks ---------------------------------------------------------- @@ -295,67 +291,46 @@ // FileWriterCallbacks ---------------------------------------------------- -void FileWriterCallbacks::OnDidCreateFileWriterV8Impl::Trace( - blink::Visitor* visitor) { - visitor->Trace(callback_); - OnDidCreateFileWriterCallback::Trace(visitor); -} - -void FileWriterCallbacks::OnDidCreateFileWriterV8Impl::OnSuccess( - FileWriterBase* file_writer) { - // The call sites must pass a FileWriter in |file_writer|. - callback_->InvokeAndReportException(nullptr, - static_cast<FileWriter*>(file_writer)); -} - -FileWriterCallbacks::FileWriterCallbacks( - FileWriterBase* file_writer, - OnDidCreateFileWriterCallback* success_callback, - ErrorCallbackBase* error_callback, - ExecutionContext* context) - : FileSystemCallbacksBase(error_callback, nullptr, context), +FileWriterCallbacks::FileWriterCallbacks(FileWriterBase* file_writer, + SuccessCallback success_callback, + ErrorCallback error_callback, + ExecutionContext* context) + : FileSystemCallbacksBase(/*error_callback =*/nullptr, + /*file_system =*/nullptr, + context), file_writer_(file_writer), - success_callback_(success_callback) {} + success_callback_(std::move(success_callback)), + error_callback_(std::move(error_callback)) {} void FileWriterCallbacks::DidCreateFileWriter(const KURL& path, int64_t length) { if (!success_callback_) return; + file_writer_->Initialize(path, length); - success_callback_.Release()->OnSuccess(file_writer_); + std::move(success_callback_).Run(file_writer_); } void FileWriterCallbacks::DidFail(base::File::Error error) { if (!error_callback_) return; - error_callback_.Release()->Invoke(error); + std::move(error_callback_).Run(error); } // SnapshotFileCallback ------------------------------------------------------- -void SnapshotFileCallback::OnDidCreateSnapshotFileV8Impl::Trace( - blink::Visitor* visitor) { - visitor->Trace(callback_); - OnDidCreateSnapshotFileCallback::Trace(visitor); -} - -void SnapshotFileCallback::OnDidCreateSnapshotFileV8Impl::OnSuccess( - File* file) { - callback_->InvokeAndReportException(nullptr, file); -} - -SnapshotFileCallback::SnapshotFileCallback( - DOMFileSystemBase* filesystem, - const String& name, - const KURL& url, - OnDidCreateSnapshotFileCallback* success_callback, - ErrorCallbackBase* error_callback, - ExecutionContext* context) - : FileSystemCallbacksBase(error_callback, filesystem, context), +SnapshotFileCallback::SnapshotFileCallback(DOMFileSystemBase* filesystem, + const String& name, + const KURL& url, + SuccessCallback success_callback, + ErrorCallback error_callback, + ExecutionContext* context) + : FileSystemCallbacksBase(/*error_callback=*/nullptr, filesystem, context), name_(name), url_(url), - success_callback_(success_callback) {} + success_callback_(std::move(success_callback)), + error_callback_(std::move(error_callback)) {} void SnapshotFileCallback::DidCreateSnapshotFile( const FileMetadata& metadata, @@ -369,61 +344,42 @@ // coined a File with a new handle that has the correct type set on it. This // allows the blob storage system to track when a temp file can and can't be // safely deleted. - success_callback_.Release()->OnSuccess(DOMFileSystemBase::CreateFile( - metadata, url_, file_system_->GetType(), name_)); + std::move(success_callback_) + .Run(DOMFileSystemBase::CreateFile(metadata, url_, + file_system_->GetType(), name_)); } void SnapshotFileCallback::DidFail(base::File::Error error) { if (!error_callback_) return; - error_callback_.Release()->Invoke(error); + std::move(error_callback_).Run(error); } // VoidCallbacks -------------------------------------------------------------- -void VoidCallbacks::OnDidSucceedV8Impl::Trace(blink::Visitor* visitor) { - visitor->Trace(callback_); - OnDidSucceedCallback::Trace(visitor); -} - -void VoidCallbacks::OnDidSucceedV8Impl::OnSuccess( - ExecutionContext* dummy_arg_for_sync_helper) { - callback_->InvokeAndReportException(nullptr); -} - -VoidCallbacks::OnDidSucceedPromiseImpl::OnDidSucceedPromiseImpl( - ScriptPromiseResolver* resolver) - : resolver_(resolver) {} - -void VoidCallbacks::OnDidSucceedPromiseImpl::Trace(Visitor* visitor) { - OnDidSucceedCallback::Trace(visitor); - visitor->Trace(resolver_); -} - -void VoidCallbacks::OnDidSucceedPromiseImpl::OnSuccess(ExecutionContext*) { - resolver_->Resolve(); -} - -VoidCallbacks::VoidCallbacks(OnDidSucceedCallback* success_callback, - ErrorCallbackBase* error_callback, +VoidCallbacks::VoidCallbacks(SuccessCallback success_callback, + ErrorCallback error_callback, ExecutionContext* context, DOMFileSystemBase* file_system) - : FileSystemCallbacksBase(error_callback, file_system, context), - success_callback_(success_callback) {} + : FileSystemCallbacksBase(/*error_callback =*/nullptr, + file_system, + context), + success_callback_(std::move(success_callback)), + error_callback_(std::move(error_callback)) {} void VoidCallbacks::DidSucceed() { if (!success_callback_) return; - success_callback_.Release()->OnSuccess(execution_context_.Get()); + std::move(success_callback_).Run(); } void VoidCallbacks::DidFail(base::File::Error error) { if (!error_callback_) return; - error_callback_.Release()->Invoke(error); + std::move(error_callback_).Run(error); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h index 244595d..5f03d1e 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h +++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
@@ -130,39 +130,6 @@ class EntryCallbacks final : public FileSystemCallbacksBase { public: - // TODO(tonikitoo,mek): This class is not being effectively by EntryCallbacks - // anymore. However, it still being referenced by ResolveURICallbacks and - // sync_callback_helper.h. Remove it when all classes have switched to simple - // success/error callbacks implementation, and there is no reference to it in - // sync_callback_helper.h and in ResolveURICallbacks anymore. - class OnDidGetEntryCallback - : public GarbageCollectedFinalized<OnDidGetEntryCallback> { - public: - virtual ~OnDidGetEntryCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(Entry*) = 0; - - protected: - OnDidGetEntryCallback() = default; - }; - - class OnDidGetEntryV8Impl : public OnDidGetEntryCallback { - public: - static OnDidGetEntryV8Impl* Create(V8EntryCallback* callback) { - return callback ? MakeGarbageCollected<OnDidGetEntryV8Impl>(callback) - : nullptr; - } - - OnDidGetEntryV8Impl(V8EntryCallback* callback) - : callback_(ToV8PersistentCallbackInterface(callback)) {} - - void Trace(blink::Visitor*) override; - void OnSuccess(Entry*) override; - - private: - Member<V8PersistentCallbackInterface<V8EntryCallback>> callback_; - }; - using SuccessCallback = base::OnceCallback<void(Entry*)>; using ErrorCallback = base::OnceCallback<void(base::File::Error)>; @@ -225,21 +192,6 @@ class FileSystemCallbacks final : public FileSystemCallbacksBase { public: - // TODO(tonikitoo,mek): This class is not being effectively used anymore. - // Remove it when all classes have switched to simple success/error callbacks - // implementation, and there is no reference to it in sync_callback_helper.h - // anymore. - class OnDidOpenFileSystemCallback - : public GarbageCollectedFinalized<OnDidOpenFileSystemCallback> { - public: - virtual ~OnDidOpenFileSystemCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(DOMFileSystem*) = 0; - - protected: - OnDidOpenFileSystemCallback() = default; - }; - using SuccessCallback = base::OnceCallback<void(DOMFileSystem*)>; using ErrorCallback = base::OnceCallback<void(base::File::Error)>; @@ -262,12 +214,10 @@ class ResolveURICallbacks final : public FileSystemCallbacksBase { public: - using OnDidGetEntryCallback = EntryCallbacks::OnDidGetEntryCallback; - using OnDidGetEntryV8Impl = EntryCallbacks::OnDidGetEntryV8Impl; + using SuccessCallback = EntryCallbacks::SuccessCallback; + using ErrorCallback = EntryCallbacks::ErrorCallback; - ResolveURICallbacks(OnDidGetEntryCallback*, - ErrorCallbackBase*, - ExecutionContext*); + ResolveURICallbacks(SuccessCallback, ErrorCallback, ExecutionContext*); // Called when a filesystem URL is resolved. void DidResolveURL(const String& name, @@ -280,7 +230,8 @@ void DidFail(base::File::Error error); private: - Persistent<OnDidGetEntryCallback> success_callback_; + SuccessCallback success_callback_; + ErrorCallback error_callback_; }; class MetadataCallbacks final : public FileSystemCallbacksBase { @@ -288,21 +239,6 @@ using SuccessCallback = base::OnceCallback<void(Metadata* metadata)>; using ErrorCallback = base::OnceCallback<void(base::File::Error error)>; - // TODO(tonikitoo,mek): This class is not being effectively used anymore. - // Remove it when all classes have switched to simple success/error callbacks - // implementation, and there is no reference to it in sync_callback_helper.h - // anymore. - class OnDidReadMetadataCallback - : public GarbageCollectedFinalized<OnDidReadMetadataCallback> { - public: - virtual ~OnDidReadMetadataCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(Metadata*) = 0; - - protected: - OnDidReadMetadataCallback() = default; - }; - MetadataCallbacks(SuccessCallback, ErrorCallback, ExecutionContext*, @@ -321,38 +257,12 @@ class FileWriterCallbacks final : public FileSystemCallbacksBase { public: - class OnDidCreateFileWriterCallback - : public GarbageCollectedFinalized<OnDidCreateFileWriterCallback> { - public: - virtual ~OnDidCreateFileWriterCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(FileWriterBase*) = 0; - - protected: - OnDidCreateFileWriterCallback() = default; - }; - - class OnDidCreateFileWriterV8Impl : public OnDidCreateFileWriterCallback { - public: - static OnDidCreateFileWriterV8Impl* Create(V8FileWriterCallback* callback) { - return callback - ? MakeGarbageCollected<OnDidCreateFileWriterV8Impl>(callback) - : nullptr; - } - - OnDidCreateFileWriterV8Impl(V8FileWriterCallback* callback) - : callback_(ToV8PersistentCallbackInterface(callback)) {} - - void Trace(blink::Visitor*) override; - void OnSuccess(FileWriterBase*) override; - - private: - Member<V8PersistentCallbackInterface<V8FileWriterCallback>> callback_; - }; + using SuccessCallback = base::OnceCallback<void(FileWriterBase* file_writer)>; + using ErrorCallback = base::OnceCallback<void(base::File::Error error)>; FileWriterCallbacks(FileWriterBase*, - OnDidCreateFileWriterCallback*, - ErrorCallbackBase*, + SuccessCallback, + ErrorCallback, ExecutionContext*); // Called when an AsyncFileWrter has been created successfully. @@ -363,46 +273,21 @@ private: Persistent<FileWriterBase> file_writer_; - Persistent<OnDidCreateFileWriterCallback> success_callback_; + SuccessCallback success_callback_; + ErrorCallback error_callback_; }; class SnapshotFileCallback final : public SnapshotFileCallbackBase, public FileSystemCallbacksBase { public: - class OnDidCreateSnapshotFileCallback - : public GarbageCollectedFinalized<OnDidCreateSnapshotFileCallback> { - public: - virtual ~OnDidCreateSnapshotFileCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(File*) = 0; - - protected: - OnDidCreateSnapshotFileCallback() = default; - }; - - class OnDidCreateSnapshotFileV8Impl : public OnDidCreateSnapshotFileCallback { - public: - static OnDidCreateSnapshotFileV8Impl* Create(V8FileCallback* callback) { - return callback - ? MakeGarbageCollected<OnDidCreateSnapshotFileV8Impl>(callback) - : nullptr; - } - - OnDidCreateSnapshotFileV8Impl(V8FileCallback* callback) - : callback_(ToV8PersistentCallbackInterface(callback)) {} - - void Trace(blink::Visitor*) override; - void OnSuccess(File*) override; - - private: - Member<V8PersistentCallbackInterface<V8FileCallback>> callback_; - }; + using SuccessCallback = base::OnceCallback<void(File* file)>; + using ErrorCallback = base::OnceCallback<void(base::File::Error error)>; SnapshotFileCallback(DOMFileSystemBase*, const String& name, const KURL&, - OnDidCreateSnapshotFileCallback*, - ErrorCallbackBase*, + SuccessCallback, + ErrorCallback, ExecutionContext*); // Called when a snapshot file is created successfully. @@ -415,51 +300,17 @@ private: String name_; KURL url_; - Persistent<OnDidCreateSnapshotFileCallback> success_callback_; + SuccessCallback success_callback_; + ErrorCallback error_callback_; }; class VoidCallbacks final : public FileSystemCallbacksBase { public: - class OnDidSucceedCallback - : public GarbageCollectedFinalized<OnDidSucceedCallback> { - public: - virtual ~OnDidSucceedCallback() = default; - virtual void Trace(blink::Visitor*) {} - virtual void OnSuccess(ExecutionContext* dummy_arg_for_sync_helper) = 0; + using SuccessCallback = base::OnceCallback<void()>; + using ErrorCallback = base::OnceCallback<void(base::File::Error error)>; - protected: - OnDidSucceedCallback() = default; - }; - - class OnDidSucceedV8Impl : public OnDidSucceedCallback { - public: - static OnDidSucceedV8Impl* Create(V8VoidCallback* callback) { - return callback ? MakeGarbageCollected<OnDidSucceedV8Impl>(callback) - : nullptr; - } - - OnDidSucceedV8Impl(V8VoidCallback* callback) - : callback_(ToV8PersistentCallbackInterface(callback)) {} - - void Trace(blink::Visitor*) override; - void OnSuccess(ExecutionContext* dummy_arg_for_sync_helper) override; - - private: - Member<V8PersistentCallbackInterface<V8VoidCallback>> callback_; - }; - - class OnDidSucceedPromiseImpl : public OnDidSucceedCallback { - public: - OnDidSucceedPromiseImpl(ScriptPromiseResolver*); - void Trace(Visitor*) override; - void OnSuccess(ExecutionContext*) override; - - private: - Member<ScriptPromiseResolver> resolver_; - }; - - VoidCallbacks(OnDidSucceedCallback*, - ErrorCallbackBase*, + VoidCallbacks(SuccessCallback, + ErrorCallback, ExecutionContext*, DOMFileSystemBase*); @@ -470,7 +321,8 @@ void DidFail(base::File::Error error); private: - Persistent<OnDidSucceedCallback> success_callback_; + SuccessCallback success_callback_; + ErrorCallback error_callback_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_directory_handle.cc b/third_party/blink/renderer/modules/filesystem/file_system_directory_handle.cc index 62aabff..822dfa66 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_directory_handle.cc +++ b/third_party/blink/renderer/modules/filesystem/file_system_directory_handle.cc
@@ -107,10 +107,13 @@ ScriptState* script_state) { auto* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise result = resolver->Promise(); - filesystem()->RemoveRecursively( - this, - MakeGarbageCollected<VoidCallbacks::OnDidSucceedPromiseImpl>(resolver), - MakeGarbageCollected<PromiseErrorCallback>(resolver)); + + auto success_callback_wrapper = + AsyncCallbackHelper::VoidSuccessPromise(resolver); + auto error_callback_wrapper = AsyncCallbackHelper::ErrorPromise(resolver); + + filesystem()->RemoveRecursively(this, std::move(success_callback_wrapper), + std::move(error_callback_wrapper)); return result; }
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_file_handle.cc b/third_party/blink/renderer/modules/filesystem/file_system_file_handle.cc index 6fb7dace..28c1741 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_file_handle.cc +++ b/third_party/blink/renderer/modules/filesystem/file_system_file_handle.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/file.h" +#include "third_party/blink/renderer/modules/filesystem/async_callback_helper.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" #include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h" #include "third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h" @@ -17,25 +18,6 @@ namespace blink { -namespace { - -class OnDidCreateSnapshotFilePromise - : public SnapshotFileCallback::OnDidCreateSnapshotFileCallback { - public: - explicit OnDidCreateSnapshotFilePromise(ScriptPromiseResolver* resolver) - : resolver_(resolver) {} - void Trace(Visitor* visitor) override { - OnDidCreateSnapshotFileCallback::Trace(visitor); - visitor->Trace(resolver_); - } - void OnSuccess(File* file) override { resolver_->Resolve(file); } - - private: - Member<ScriptPromiseResolver> resolver_; -}; - -} // namespace - FileSystemFileHandle::FileSystemFileHandle(DOMFileSystemBase* file_system, const String& full_path) : FileSystemBaseHandle(file_system, full_path) {} @@ -65,14 +47,20 @@ auto* resolver = ScriptPromiseResolver::Create(script_state); ScriptPromise result = resolver->Promise(); KURL file_system_url = filesystem()->CreateFileSystemURL(this); + + auto success_callback_wrapper = + WTF::Bind([](ScriptPromiseResolver* resolver, + File* file) { resolver->Resolve(file); }, + WrapPersistentIfNeeded(resolver)); + auto error_callback_wrapper = AsyncCallbackHelper::ErrorPromise(resolver); + FileSystemDispatcher::From(ExecutionContext::From(script_state)) - .CreateSnapshotFile( - file_system_url, - std::make_unique<SnapshotFileCallback>( - filesystem(), name(), file_system_url, - MakeGarbageCollected<OnDidCreateSnapshotFilePromise>(resolver), - MakeGarbageCollected<PromiseErrorCallback>(resolver), - ExecutionContext::From(script_state))); + .CreateSnapshotFile(file_system_url, + std::make_unique<SnapshotFileCallback>( + filesystem(), name(), file_system_url, + std::move(success_callback_wrapper), + std::move(error_callback_wrapper), + ExecutionContext::From(script_state))); return result; }
diff --git a/third_party/blink/renderer/modules/filesystem/sync_callback_helper.h b/third_party/blink/renderer/modules/filesystem/sync_callback_helper.h index 5a94a76..d05ea919 100644 --- a/third_party/blink/renderer/modules/filesystem/sync_callback_helper.h +++ b/third_party/blink/renderer/modules/filesystem/sync_callback_helper.h
@@ -40,26 +40,14 @@ namespace blink { // Helper class to support DOMFileSystemSync implementation. -template <typename SuccessCallback, typename CallbackArg> +template <typename CallbackArg> class DOMFileSystemCallbacksSyncHelper final - : public GarbageCollected< - DOMFileSystemCallbacksSyncHelper<SuccessCallback, CallbackArg>> { + : public GarbageCollected<DOMFileSystemCallbacksSyncHelper<CallbackArg>> { public: DOMFileSystemCallbacksSyncHelper() = default; void Trace(blink::Visitor* visitor) { visitor->Trace(result_); } - // Deprecated success and error callback wrappers. - // - // NOTE: These will be removed when all wrapper callback classes switch to - // using the simple/new implementation (see below). - SuccessCallback* GetSuccessCallback() { - return MakeGarbageCollected<SuccessCallbackImpl>(this); - } - ErrorCallbackBase* GetErrorCallback() { - return MakeGarbageCollected<ErrorCallbackImpl>(this); - } - // Simple/new success and error callback wrappers. void OnSuccess(CallbackArg* arg) { DCHECK(arg); @@ -77,71 +65,22 @@ } private: - class SuccessCallbackImpl final : public SuccessCallback { - public: - explicit SuccessCallbackImpl(DOMFileSystemCallbacksSyncHelper* helper) - : helper_(helper) {} - - void Trace(blink::Visitor* visitor) override { - visitor->Trace(helper_); - SuccessCallback::Trace(visitor); - } - void OnSuccess(CallbackArg* arg) override { - DCHECK(arg); - helper_->result_ = arg; - } - - private: - Member<DOMFileSystemCallbacksSyncHelper> helper_; - - friend class DOMFileSystemCallbacksSyncHelper; - }; - - class ErrorCallbackImpl final : public ErrorCallbackBase { - public: - explicit ErrorCallbackImpl(DOMFileSystemCallbacksSyncHelper* helper) - : helper_(helper) {} - - void Trace(blink::Visitor* visitor) override { - visitor->Trace(helper_); - ErrorCallbackBase::Trace(visitor); - } - void Invoke(base::File::Error error_code) override { - DCHECK_NE(error_code, base::File::FILE_OK); - helper_->error_code_ = error_code; - } - - private: - Member<DOMFileSystemCallbacksSyncHelper> helper_; - - friend class DOMFileSystemCallbacksSyncHelper; - }; - Member<CallbackArg> result_; base::File::Error error_code_ = base::File::FILE_OK; - - friend class SuccessCallbackImpl; - friend class ErrorCallbackImpl; }; -using EntryCallbacksSyncHelper = - DOMFileSystemCallbacksSyncHelper<EntryCallbacks::OnDidGetEntryCallback, - Entry>; +using EntryCallbacksSyncHelper = DOMFileSystemCallbacksSyncHelper<Entry>; using FileSystemCallbacksSyncHelper = DOMFileSystemCallbacksSyncHelper< - FileSystemCallbacks::OnDidOpenFileSystemCallback, DOMFileSystem>; using FileWriterCallbacksSyncHelper = DOMFileSystemCallbacksSyncHelper< - FileWriterCallbacks::OnDidCreateFileWriterCallback, FileWriterBase>; using MetadataCallbacksSyncHelper = DOMFileSystemCallbacksSyncHelper< - MetadataCallbacks::OnDidReadMetadataCallback, Metadata>; using VoidCallbacksSyncHelper = DOMFileSystemCallbacksSyncHelper< - VoidCallbacks::OnDidSucceedCallback, ExecutionContext /* dummy_arg_for_sync_helper */>; } // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc b/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc index c3da5465..1e9bd9d0 100644 --- a/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc +++ b/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc
@@ -150,11 +150,16 @@ return; } + auto success_callback_wrapper = + AsyncCallbackHelper::SuccessCallback<Entry>(success_callback); + auto error_callback_wrapper = + AsyncCallbackHelper::ErrorCallback(error_callback); + LocalFileSystem::From(worker)->ResolveURL( &worker, completed_url, - std::make_unique<ResolveURICallbacks>( - ResolveURICallbacks::OnDidGetEntryV8Impl::Create(success_callback), - ScriptErrorCallback::Wrap(error_callback), &worker), + std::make_unique<ResolveURICallbacks>(std::move(success_callback_wrapper), + std::move(error_callback_wrapper), + &worker), LocalFileSystem::kAsynchronous); } @@ -179,9 +184,16 @@ } auto* sync_helper = MakeGarbageCollected<EntryCallbacksSyncHelper>(); + + auto success_callback_wrapper = + WTF::Bind(&EntryCallbacksSyncHelper::OnSuccess, + WrapPersistentIfNeeded(sync_helper)); + auto error_callback_wrapper = WTF::Bind(&EntryCallbacksSyncHelper::OnError, + WrapPersistentIfNeeded(sync_helper)); + std::unique_ptr<ResolveURICallbacks> callbacks = - std::make_unique<ResolveURICallbacks>(sync_helper->GetSuccessCallback(), - sync_helper->GetErrorCallback(), + std::make_unique<ResolveURICallbacks>(std::move(success_callback_wrapper), + std::move(error_callback_wrapper), &worker); LocalFileSystem::From(worker)->ResolveURL(&worker, completed_url,
diff --git a/third_party/blink/renderer/modules/idle/BUILD.gn b/third_party/blink/renderer/modules/idle/BUILD.gn index aaf0896b..1a8ae338 100644 --- a/third_party/blink/renderer/modules/idle/BUILD.gn +++ b/third_party/blink/renderer/modules/idle/BUILD.gn
@@ -6,13 +6,9 @@ blink_modules_sources("idle") { sources = [ - "idle_manager.cc", - "idle_manager.h", + "idle_detector.cc", + "idle_detector.h", "idle_state.cc", "idle_state.h", - "idle_status.cc", - "idle_status.h", - "navigator_idle.cc", - "navigator_idle.h", ] }
diff --git a/third_party/blink/renderer/modules/idle/idle_detector.cc b/third_party/blink/renderer/modules/idle/idle_detector.cc new file mode 100644 index 0000000..08da0712 --- /dev/null +++ b/third_party/blink/renderer/modules/idle/idle_detector.cc
@@ -0,0 +1,153 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "third_party/blink/renderer/modules/idle/idle_detector.h" + +#include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom-blink.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/modules/idle/idle_options.h" +#include "third_party/blink/renderer/modules/idle/idle_state.h" +#include "third_party/blink/renderer/platform/bindings/name_client.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" + +namespace blink { +namespace { + +const char kFeaturePolicyBlocked[] = + "Access to the feature \"idle-detection\" is disallowed by feature policy."; + +const uint32_t kDefaultThresholdSeconds = 60; + +} // namespace + +IdleDetector* IdleDetector::Create(ScriptState* script_state, + const IdleOptions* options, + ExceptionState& exception_state) { + int32_t threshold_seconds = + options->hasThreshold() ? options->threshold() : kDefaultThresholdSeconds; + + if (threshold_seconds <= 0) { + exception_state.ThrowTypeError("Invalid threshold"); + return nullptr; + } + + base::TimeDelta threshold = base::TimeDelta::FromSeconds(threshold_seconds); + + auto* detector = MakeGarbageCollected<IdleDetector>( + ExecutionContext::From(script_state), threshold); + return detector; +} + +// static +IdleDetector* IdleDetector::Create(ScriptState* script_state, + ExceptionState& exception_state) { + return Create(script_state, IdleOptions::Create(), exception_state); +} + +IdleDetector::IdleDetector(ExecutionContext* context, base::TimeDelta threshold) + : ContextClient(context), threshold_(threshold), binding_(this) {} + +void IdleDetector::Init(mojom::blink::IdleStatePtr state) { + state_ = MakeGarbageCollected<blink::IdleState>(std::move(state)); +} + +IdleDetector::~IdleDetector() = default; + +void IdleDetector::Dispose() { + StopMonitoring(); +} + +const AtomicString& IdleDetector::InterfaceName() const { + return event_target_names::kIdleDetector; +} + +ExecutionContext* IdleDetector::GetExecutionContext() const { + return ContextClient::GetExecutionContext(); +} + +bool IdleDetector::HasPendingActivity() const { + return binding_.is_bound(); +} + +ScriptPromise IdleDetector::start(ScriptState* script_state) { + // Validate options. + ExecutionContext* context = ExecutionContext::From(script_state); + DCHECK(context->IsContextThread()); + + if (!context->GetSecurityContext().IsFeatureEnabled( + mojom::FeaturePolicyFeature::kIdleDetection, + ReportOptions::kReportOnFailure)) { + return ScriptPromise::RejectWithDOMException( + script_state, DOMException::Create(DOMExceptionCode::kSecurityError, + kFeaturePolicyBlocked)); + } + + StartMonitoring(); + + return ScriptPromise::CastUndefined(script_state); +} + +void IdleDetector::stop() { + StopMonitoring(); +} + +void IdleDetector::StartMonitoring() { + if (binding_.is_bound()) { + return; + } + + // See https://bit.ly/2S0zRAS for task types. + scoped_refptr<base::SingleThreadTaskRunner> task_runner = + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); + + if (!service_) { + GetExecutionContext()->GetInterfaceProvider()->GetInterface( + mojo::MakeRequest(&service_, task_runner)); + } + + mojom::blink::IdleMonitorPtr monitor_ptr; + binding_.Bind(mojo::MakeRequest(&monitor_ptr, task_runner), task_runner); + + service_->AddMonitor( + threshold_, std::move(monitor_ptr), + WTF::Bind(&IdleDetector::OnAddMonitor, WrapPersistent(this))); +} + +void IdleDetector::StopMonitoring() { + binding_.Close(); +} + +void IdleDetector::OnAddMonitor(mojom::blink::IdleStatePtr state) { + Init(std::move(state)); + DispatchEvent(*Event::Create(event_type_names::kChange)); +} + +blink::IdleState* IdleDetector::state() const { + return state_; +} + +void IdleDetector::Update(mojom::blink::IdleStatePtr state) { + DCHECK(binding_.is_bound()); + if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed()) + return; + + if (state.get()->Equals(state_->state())) + return; + + Init(std::move(state)); + DispatchEvent(*Event::Create(event_type_names::kChange)); +} + +void IdleDetector::Trace(blink::Visitor* visitor) { + EventTargetWithInlineData::Trace(visitor); + ContextClient::Trace(visitor); + visitor->Trace(state_); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/idle/idle_detector.h b/third_party/blink/renderer/modules/idle/idle_detector.h new file mode 100644 index 0000000..d3ea129 --- /dev/null +++ b/third_party/blink/renderer/modules/idle/idle_detector.h
@@ -0,0 +1,87 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_DETECTOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_DETECTOR_H_ + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/core/dom/events/event_target.h" +#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/event_modules.h" +#include "third_party/blink/renderer/modules/event_target_modules.h" +#include "third_party/blink/renderer/modules/idle/idle_options.h" +#include "third_party/blink/renderer/modules/idle/idle_state.h" +#include "third_party/blink/renderer/platform/heap/heap_allocator.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" + +namespace blink { + +class IdleDetector final : public EventTargetWithInlineData, + public ActiveScriptWrappable<IdleDetector>, + public ContextClient, + public mojom::blink::IdleMonitor { + USING_GARBAGE_COLLECTED_MIXIN(IdleDetector); + DEFINE_WRAPPERTYPEINFO(); + USING_PRE_FINALIZER(IdleDetector, Dispose); + + public: + static IdleDetector* Create(ScriptState*, + const IdleOptions*, + ExceptionState&); + static IdleDetector* Create(ScriptState*, ExceptionState&); + + IdleDetector(ExecutionContext*, base::TimeDelta threshold); + + ~IdleDetector() override; + + void Dispose(); + + // Called when the service has returned an initial state. + void Init(mojom::blink::IdleStatePtr); + + // EventTarget implementation. + const AtomicString& InterfaceName() const override; + ExecutionContext* GetExecutionContext() const override; + + // ActiveScriptWrappable implementation. + bool HasPendingActivity() const final; + + // IdleDetector IDL interface. + ScriptPromise start(ScriptState*); + void stop(); + blink::IdleState* state() const; + DEFINE_ATTRIBUTE_EVENT_LISTENER(change, kChange) + + void OnAddMonitor(mojom::blink::IdleStatePtr); + + // mojom::blink::IdleMonitor implementation. Invoked on a state change, and + // causes an event to be dispatched. + void Update(mojom::blink::IdleStatePtr state) override; + + void Trace(blink::Visitor*) override; + + private: + Member<blink::IdleState> state_; + + const base::TimeDelta threshold_; + + // Holds a pipe which the service uses to notify this object + // when the idle state has changed. + mojo::Binding<mojom::blink::IdleMonitor> binding_; + + void StartMonitoring(); + void StopMonitoring(); + + mojom::blink::IdleManagerPtr service_; + + DISALLOW_COPY_AND_ASSIGN(IdleDetector); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_DETECTOR_H_
diff --git a/third_party/blink/renderer/modules/idle/idle_detector.idl b/third_party/blink/renderer/modules/idle/idle_detector.idl new file mode 100644 index 0000000..05926b0 --- /dev/null +++ b/third_party/blink/renderer/modules/idle/idle_detector.idl
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://github.com/samuelgoto/idle-detection + + +[ + SecureContext, + Exposed=(Window,DedicatedWorker), + ActiveScriptWrappable, + Constructor(optional IdleOptions options), + ConstructorCallWith=ScriptState, + RaisesException=Constructor, + RuntimeEnabled=IdleDetection +] interface IdleDetector : EventTarget { + readonly attribute IdleState state; + attribute EventHandler onchange; + [CallWith=ScriptState, MeasureAs=IdleDetectionStart] Promise<void> start(); + void stop(); +};
diff --git a/third_party/blink/renderer/modules/idle/idle_manager.cc b/third_party/blink/renderer/modules/idle/idle_manager.cc deleted file mode 100644 index d799df32..0000000 --- a/third_party/blink/renderer/modules/idle/idle_manager.cc +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "third_party/blink/renderer/modules/idle/idle_manager.h" - -#include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/core/dom/dom_exception.h" -#include "third_party/blink/renderer/modules/idle/idle_status.h" -#include "third_party/blink/renderer/platform/bindings/name_client.h" -#include "third_party/blink/renderer/platform/bindings/script_state.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" - -namespace blink { - -namespace { - -const char kFeaturePolicyBlocked[] = - "Access to the feature \"idle-detection\" is disallowed by feature policy."; - -const uint32_t kDefaultThresholdSeconds = 60; - -} // namespace - -IdleManager::IdleManager(ExecutionContext* context) {} - -ScriptPromise IdleManager::query(ScriptState* script_state, - const IdleOptions* options, - ExceptionState& exception_state) { - ExecutionContext* context = ExecutionContext::From(script_state); - DCHECK(context->IsContextThread()); - - // Validate options. - int32_t threshold_seconds = - options->hasThreshold() ? options->threshold() : kDefaultThresholdSeconds; - - if (threshold_seconds <= 0) { - exception_state.ThrowTypeError("Invalid threshold"); - return ScriptPromise(); - } - - base::TimeDelta threshold = base::TimeDelta::FromSeconds(threshold_seconds); - - if (!context->GetSecurityContext().IsFeatureEnabled( - mojom::FeaturePolicyFeature::kIdleDetection, - ReportOptions::kReportOnFailure)) { - return ScriptPromise::RejectWithDOMException( - script_state, DOMException::Create(DOMExceptionCode::kSecurityError, - kFeaturePolicyBlocked)); - } - - if (!service_) { - // NOTE(goto): what are the benefits of initializing this here - // as opposed to the constructor? lazy loading? - context->GetInterfaceProvider()->GetInterface(mojo::MakeRequest(&service_)); - service_.set_connection_error_handler(WTF::Bind( - &IdleManager::OnIdleManagerConnectionError, WrapWeakPersistent(this))); - } - - ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); - ScriptPromise promise = resolver->Promise(); - - mojom::blink::IdleMonitorPtr monitor_ptr; - IdleStatus* status = - IdleStatus::Create(ExecutionContext::From(script_state), threshold, - mojo::MakeRequest(&monitor_ptr)); - - requests_.insert(resolver); - service_->AddMonitor( - threshold, std::move(monitor_ptr), - WTF::Bind(&IdleManager::OnAddMonitor, WrapPersistent(this), - WrapPersistent(resolver), WrapPersistent(status))); - - return promise; -} - -IdleManager* IdleManager::Create(ExecutionContext* context) { - IdleManager* idle_manager = MakeGarbageCollected<IdleManager>(context); - return idle_manager; -} - -void IdleManager::OnAddMonitor(ScriptPromiseResolver* resolver, - IdleStatus* status, - mojom::blink::IdleStatePtr state) { - DCHECK(requests_.Contains(resolver)); - requests_.erase(resolver); - - status->Init(std::move(state)); - resolver->Resolve(status); -} - -void IdleManager::Trace(blink::Visitor* visitor) { - ScriptWrappable::Trace(visitor); - visitor->Trace(requests_); -} - -void IdleManager::OnIdleManagerConnectionError() { - for (const auto& request : requests_) { - request->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError, - "Idle detection not available")); - } - requests_.clear(); - service_.reset(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/idle/idle_manager.h b/third_party/blink/renderer/modules/idle/idle_manager.h deleted file mode 100644 index c19007cc..0000000 --- a/third_party/blink/renderer/modules/idle/idle_manager.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_MANAGER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_MANAGER_H_ - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/modules/idle/idle_options.h" -#include "third_party/blink/renderer/modules/idle/idle_status.h" -#include "third_party/blink/renderer/platform/bindings/exception_state.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/heap/heap_allocator.h" - -namespace blink { - -class IdleOptions; -class IdleStatus; -class ExecutionContext; -class ExceptionState; -class ScriptPromiseResolver; -class ScriptPromise; -class ScriptState; - -class IdleManager final : public ScriptWrappable { - DEFINE_WRAPPERTYPEINFO(); - - public: - explicit IdleManager(ExecutionContext*); - - // IdleManager IDL interface. - ScriptPromise query(ScriptState*, - const IdleOptions* options, - ExceptionState&); - - static IdleManager* Create(ExecutionContext* context); - void Trace(blink::Visitor*) override; - - private: - void OnIdleManagerConnectionError(); - void OnAddMonitor(ScriptPromiseResolver*, - IdleStatus*, - mojom::blink::IdleStatePtr); - - HeapHashSet<Member<ScriptPromiseResolver>> requests_; - mojom::blink::IdleManagerPtr service_; - - DISALLOW_COPY_AND_ASSIGN(IdleManager); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_MANAGER_H_
diff --git a/third_party/blink/renderer/modules/idle/idle_manager.idl b/third_party/blink/renderer/modules/idle/idle_manager.idl deleted file mode 100644 index e11d3b22..0000000 --- a/third_party/blink/renderer/modules/idle/idle_manager.idl +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/inexorabletash/idle-detection - -[ - SecureContext, - Exposed=(Window,DedicatedWorker), - RuntimeEnabled=IdleDetection -] interface IdleManager { - [CallWith=ScriptState, RaisesException, MeasureAs=IdleDetectionStart] - Promise<IdleStatus> query(optional IdleOptions options); -};
diff --git a/third_party/blink/renderer/modules/idle/idle_options.idl b/third_party/blink/renderer/modules/idle/idle_options.idl index f9cee74..b943c8eb 100644 --- a/third_party/blink/renderer/modules/idle/idle_options.idl +++ b/third_party/blink/renderer/modules/idle/idle_options.idl
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/inexorabletash/idle-detection +// https://github.com/samuelgoto/idle-detection dictionary IdleOptions { - unsigned long threshold; + unsigned long threshold = 60; /* seconds */ };
diff --git a/third_party/blink/renderer/modules/idle/idle_state.h b/third_party/blink/renderer/modules/idle/idle_state.h index 12c2f5c6..f5d7ad1 100644 --- a/third_party/blink/renderer/modules/idle/idle_state.h +++ b/third_party/blink/renderer/modules/idle/idle_state.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/idle/idle_manager.mojom-blink.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" namespace blink {
diff --git a/third_party/blink/renderer/modules/idle/idle_state.idl b/third_party/blink/renderer/modules/idle/idle_state.idl index 6926f5de..971c01f 100644 --- a/third_party/blink/renderer/modules/idle/idle_state.idl +++ b/third_party/blink/renderer/modules/idle/idle_state.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/inexorabletash/idle-detection +// https://github.com/samuelgoto/idle-detection enum UserIdleState { "active",
diff --git a/third_party/blink/renderer/modules/idle/idle_status.cc b/third_party/blink/renderer/modules/idle/idle_status.cc deleted file mode 100644 index 4a03dd3..0000000 --- a/third_party/blink/renderer/modules/idle/idle_status.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <utility> - -#include "third_party/blink/renderer/modules/idle/idle_status.h" - -#include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/modules/idle/idle_state.h" -#include "third_party/blink/renderer/platform/bindings/name_client.h" -#include "third_party/blink/renderer/platform/bindings/script_state.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" - -namespace blink { - -IdleStatus* IdleStatus::Create(ExecutionContext* context, - base::TimeDelta threshold, - mojom::blink::IdleMonitorRequest request) { - auto* status = - MakeGarbageCollected<IdleStatus>(context, threshold, std::move(request)); - status->UpdateStateIfNeeded(); - return status; -} - -IdleStatus::IdleStatus(ExecutionContext* context, - base::TimeDelta threshold, - mojom::blink::IdleMonitorRequest request) - : ContextLifecycleStateObserver(context), - threshold_(threshold), - // See https://bit.ly/2S0zRAS for task types. - binding_(this, - std::move(request), - context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {} - -void IdleStatus::Init(mojom::blink::IdleStatePtr state) { - state_ = MakeGarbageCollected<blink::IdleState>(std::move(state)); -} - -IdleStatus::~IdleStatus() = default; - -void IdleStatus::Dispose() { - StopMonitoring(); -} - -const AtomicString& IdleStatus::InterfaceName() const { - return event_target_names::kIdleStatus; -} - -ExecutionContext* IdleStatus::GetExecutionContext() const { - return ContextLifecycleObserver::GetExecutionContext(); -} - -bool IdleStatus::HasPendingActivity() const { - return binding_.is_bound(); -} - -void IdleStatus::ContextLifecycleStateChanged( - mojom::FrameLifecycleState state) { - if (state == mojom::FrameLifecycleState::kRunning) - StartMonitoring(); - else - StopMonitoring(); -} - -void IdleStatus::ContextDestroyed(ExecutionContext*) { - StopMonitoring(); -} - -void IdleStatus::StartMonitoring() { - DCHECK(!binding_.is_bound()); - - // See https://bit.ly/2S0zRAS for task types. - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); - - mojom::blink::IdleManagerPtr service; - GetExecutionContext()->GetInterfaceProvider()->GetInterface( - mojo::MakeRequest(&service, task_runner)); - - mojom::blink::IdleMonitorPtr monitor_ptr; - binding_.Bind(mojo::MakeRequest(&monitor_ptr, task_runner), task_runner); - - service->AddMonitor( - threshold_, std::move(monitor_ptr), - WTF::Bind( - [](IdleStatus* status, mojom::blink::IdleStatePtr state) { - if (state.get()->Equals(status->state_->state())) - status->Update(std::move(state)); - }, - WrapWeakPersistent(this))); -} - -void IdleStatus::StopMonitoring() { - binding_.Close(); -} - -blink::IdleState* IdleStatus::state() const { - return state_; -} - -void IdleStatus::Update(mojom::blink::IdleStatePtr state) { - DCHECK(binding_.is_bound()); - if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed()) - return; - - Init(std::move(state)); - - DispatchEvent(*Event::Create(event_type_names::kChange)); -} - -void IdleStatus::Trace(blink::Visitor* visitor) { - EventTargetWithInlineData::Trace(visitor); - ContextLifecycleStateObserver::Trace(visitor); - visitor->Trace(state_); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/idle/idle_status.h b/third_party/blink/renderer/modules/idle/idle_status.h deleted file mode 100644 index a680904..0000000 --- a/third_party/blink/renderer/modules/idle/idle_status.h +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_STATUS_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_STATUS_H_ - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/platform/modules/idle/idle_manager.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" -#include "third_party/blink/renderer/core/dom/events/event_target.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h" -#include "third_party/blink/renderer/modules/event_modules.h" -#include "third_party/blink/renderer/modules/event_target_modules.h" -#include "third_party/blink/renderer/modules/idle/idle_state.h" -#include "third_party/blink/renderer/platform/heap/heap_allocator.h" -#include "third_party/blink/renderer/platform/wtf/functional.h" - -namespace blink { - -class IdleStatus final : public EventTargetWithInlineData, - public ActiveScriptWrappable<IdleStatus>, - public ContextLifecycleStateObserver, - public mojom::blink::IdleMonitor { - USING_GARBAGE_COLLECTED_MIXIN(IdleStatus); - DEFINE_WRAPPERTYPEINFO(); - USING_PRE_FINALIZER(IdleStatus, Dispose); - - public: - // Constructed by the IdleManager when queried by script, but not returned - // to script until the monitor has been registered by the service and - // returned an initial state. - static IdleStatus* Create(ExecutionContext* context, - base::TimeDelta threshold, - mojom::blink::IdleMonitorRequest request); - - IdleStatus(ExecutionContext*, - base::TimeDelta threshold, - mojom::blink::IdleMonitorRequest); - ~IdleStatus() override; - void Dispose(); - - // Called when the service has returned an initial state. - void Init(mojom::blink::IdleStatePtr); - - // EventTarget implementation. - const AtomicString& InterfaceName() const override; - ExecutionContext* GetExecutionContext() const override; - - // ActiveScriptWrappable implementation. - bool HasPendingActivity() const final; - - // ContextLifecycleStateObserver implementation. - void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override; - void ContextDestroyed(ExecutionContext*) override; - - // IdleStatus IDL interface. - blink::IdleState* state() const; - DEFINE_ATTRIBUTE_EVENT_LISTENER(change, kChange) - - // mojom::blink::IdleMonitor implementation. Invoked on a state change, and - // causes an event to be dispatched. - void Update(mojom::blink::IdleStatePtr state) override; - - void Trace(blink::Visitor*) override; - - private: - // Called internally to re-start monitoring by establishing a new binding, - // after a previous call to StopMonitoring(). - void StartMonitoring(); - - // Close the binding, for example when paused or the context has been - // destroyed. - void StopMonitoring(); - - Member<blink::IdleState> state_; - - const base::TimeDelta threshold_; - - // Holds a pipe which the service uses to notify this object - // when the idle state has changed. - mojo::Binding<mojom::blink::IdleMonitor> binding_; - - DISALLOW_COPY_AND_ASSIGN(IdleStatus); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_IDLE_STATUS_H_
diff --git a/third_party/blink/renderer/modules/idle/idle_status.idl b/third_party/blink/renderer/modules/idle/idle_status.idl deleted file mode 100644 index 982884c..0000000 --- a/third_party/blink/renderer/modules/idle/idle_status.idl +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/inexorabletash/idle-detection - - -[ - SecureContext, - Exposed=(Window,DedicatedWorker), - ActiveScriptWrappable, - RuntimeEnabled=IdleDetection -] interface IdleStatus : EventTarget { - readonly attribute IdleState state; - attribute EventHandler onchange; -};
diff --git a/third_party/blink/renderer/modules/idle/navigator_idle.cc b/third_party/blink/renderer/modules/idle/navigator_idle.cc deleted file mode 100644 index e6bfeb25..0000000 --- a/third_party/blink/renderer/modules/idle/navigator_idle.cc +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/idle/navigator_idle.h" - -#include "third_party/blink/renderer/core/frame/navigator.h" -#include "third_party/blink/renderer/core/workers/worker_navigator.h" -#include "third_party/blink/renderer/modules/idle/idle_manager.h" -#include "third_party/blink/renderer/platform/bindings/name_client.h" -#include "third_party/blink/renderer/platform/bindings/script_state.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h" -#include "third_party/blink/renderer/platform/supplementable.h" - -namespace blink { - -namespace { - -template <typename T> -class NavigatorIdleImpl final : public GarbageCollected<NavigatorIdleImpl<T>>, - public Supplement<T> { - USING_GARBAGE_COLLECTED_MIXIN(NavigatorIdleImpl); - - public: - static const char kSupplementName[]; - - NavigatorIdleImpl(T& navigator) : Supplement<T>(navigator) {} - - static NavigatorIdleImpl& From(T& navigator) { - NavigatorIdleImpl* supplement = static_cast<NavigatorIdleImpl*>( - Supplement<T>::template From<NavigatorIdleImpl>(navigator)); - if (!supplement) { - supplement = MakeGarbageCollected<NavigatorIdleImpl>(navigator); - // MakeGarbageCollected seems appropriate, but why was the following - // working prior to my rebase? it doesn't seem like the new operator - // was deleted since my rebase from GarbageCollected. What changed? - // supplement = new NavigatorIdleImpl(navigator); - Supplement<T>::ProvideTo(navigator, supplement); - } - return *supplement; - } - - IdleManager* GetIdleManager(ExecutionContext* context) { - if (!idle_manager_ && context) { - // idle_manager_ = new IdleManager(context); - // Supplement<T>::GetSupplementable()->GetFrame()->GetDocument() - idle_manager_ = IdleManager::Create(context); - } - return idle_manager_.Get(); - } - - void Trace(blink::Visitor* visitor) override { - visitor->Trace(idle_manager_); - Supplement<T>::Trace(visitor); - } - - private: - mutable TraceWrapperMember<IdleManager> idle_manager_; -}; - -// static -template <typename T> -const char NavigatorIdleImpl<T>::kSupplementName[] = "NavigatorIdleImpl"; - -} // namespace - -IdleManager* NavigatorIdle::idle(ScriptState* script_state, - Navigator& navigator) { - return NavigatorIdleImpl<Navigator>::From(navigator).GetIdleManager( - ExecutionContext::From(script_state)); -} - -IdleManager* NavigatorIdle::idle(ScriptState* script_state, - WorkerNavigator& navigator) { - return NavigatorIdleImpl<WorkerNavigator>::From(navigator).GetIdleManager( - ExecutionContext::From(script_state)); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/idle/navigator_idle.h b/third_party/blink/renderer/modules/idle/navigator_idle.h deleted file mode 100644 index 1f7cb3f..0000000 --- a/third_party/blink/renderer/modules/idle/navigator_idle.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_NAVIGATOR_IDLE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_NAVIGATOR_IDLE_H_ - -#include "third_party/blink/renderer/platform/wtf/allocator.h" - -namespace blink { - -class IdleManager; -class Navigator; -class ScriptState; -class WorkerNavigator; - -class NavigatorIdle final { - STATIC_ONLY(NavigatorIdle); - - public: - static IdleManager* idle(ScriptState*, Navigator&); - static IdleManager* idle(ScriptState*, WorkerNavigator&); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_IDLE_NAVIGATOR_IDLE_H_
diff --git a/third_party/blink/renderer/modules/idle/navigator_idle.idl b/third_party/blink/renderer/modules/idle/navigator_idle.idl deleted file mode 100644 index d0d2bd83..0000000 --- a/third_party/blink/renderer/modules/idle/navigator_idle.idl +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/inexorabletash/idle-detection -[ - SecureContext, - Exposed=Window, - ImplementedAs=NavigatorIdle, - RuntimeEnabled=IdleDetection -] partial interface Navigator { - [CallWith=ScriptState] readonly attribute IdleManager idle; -};
diff --git a/third_party/blink/renderer/modules/idle/worker_navigator_idle.idl b/third_party/blink/renderer/modules/idle/worker_navigator_idle.idl deleted file mode 100644 index 136f21aa..0000000 --- a/third_party/blink/renderer/modules/idle/worker_navigator_idle.idl +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/inexorabletash/idle-detection -[ - SecureContext, - Exposed=DedicatedWorker, - ImplementedAs=NavigatorIdle, - RuntimeEnabled=IdleDetection -] partial interface WorkerNavigator { - [CallWith=ScriptState] readonly attribute IdleManager idle; -};
diff --git a/third_party/blink/renderer/modules/media_controls/BUILD.gn b/third_party/blink/renderer/modules/media_controls/BUILD.gn index f95ad65..fc2e78a 100644 --- a/third_party/blink/renderer/modules/media_controls/BUILD.gn +++ b/third_party/blink/renderer/modules/media_controls/BUILD.gn
@@ -88,6 +88,16 @@ "media_controls_resource_loader.h", "media_controls_rotate_to_fullscreen_delegate.cc", "media_controls_rotate_to_fullscreen_delegate.h", + "non_touch/elements/media_controls_non_touch_element.cc", + "non_touch/elements/media_controls_non_touch_element.h", + "non_touch/elements/media_controls_non_touch_overlay_element.cc", + "non_touch/elements/media_controls_non_touch_overlay_element.h", + "non_touch/elements/media_controls_non_touch_play_button_element.cc", + "non_touch/elements/media_controls_non_touch_play_button_element.h", + "non_touch/elements/media_controls_non_touch_seek_button_element.cc", + "non_touch/elements/media_controls_non_touch_seek_button_element.h", + "non_touch/elements/media_controls_non_touch_volume_button_element.cc", + "non_touch/elements/media_controls_non_touch_volume_button_element.h", "non_touch/media_controls_non_touch_impl.cc", "non_touch/media_controls_non_touch_impl.h", "non_touch/media_controls_non_touch_media_event_listener.cc", @@ -96,6 +106,7 @@ ] deps = [ + ":media_controls_non_touch_resources", ":media_controls_resources", "//services/service_manager/public/cpp", ] @@ -110,3 +121,12 @@ "media_controls_resources_200_percent.pak", ] } + +grit("media_controls_non_touch_resources") { + output_dir = "$blink_modules_output_dir/media_controls/non_touch/resources/" + source = "non_touch/resources/media_controls_non_touch_resources.grd" + outputs = [ + "grit/media_controls_non_touch_resources.h", + "media_controls_non_touch_resources.pak", + ] +}
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.cc b/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.cc index 1c263b2..247fd424 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.cc
@@ -6,6 +6,7 @@ #include "build/build_config.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/resources/grit/media_controls_non_touch_resources.h" #include "third_party/blink/renderer/modules/media_controls/resources/grit/media_controls_resources.h" #include "third_party/blink/renderer/platform/data_resource_helper.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -37,6 +38,10 @@ : IDR_UASTYLE_LEGACY_MEDIA_CONTROLS_CSS); } +String MediaControlsResourceLoader::GetNonTouchMediaControlsCSS() const { + return UncompressResourceAsString(IDR_UASTYLE_MEDIA_CONTROLS_NON_TOUCH_CSS); +} + String MediaControlsResourceLoader::GetMediaControlsAndroidCSS() const { if (RuntimeEnabledFeatures::ModernMediaControlsEnabled()) return String();
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h b/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h index 40d99ac..8e871613 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h +++ b/third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h
@@ -50,6 +50,7 @@ private: String GetMediaControlsCSS() const; + String GetNonTouchMediaControlsCSS() const; String GetMediaControlsAndroidCSS() const;
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.cc b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.cc new file mode 100644 index 0000000..b212737 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.cc
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h" + +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener.h" + +namespace blink { + +MediaControlsNonTouchElement::MediaControlsNonTouchElement( + MediaControlsNonTouchImpl& media_controls) + : media_controls_(media_controls) { + media_controls_->MediaEventListener().AddObserver(this); +} + +void MediaControlsNonTouchElement::Trace(blink::Visitor* visitor) { + visitor->Trace(media_controls_); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h new file mode 100644 index 0000000..9cce785 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h
@@ -0,0 +1,44 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_ELEMENT_H_ + +#include "base/macros.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h" +#include "third_party/blink/renderer/platform/heap/member.h" + +namespace blink { + +class MediaControlsNonTouchImpl; + +class MediaControlsNonTouchElement + : public MediaControlsNonTouchMediaEventListenerObserver { + public: + void Trace(blink::Visitor* visitor) override; + + // Non-touch media event listener observer implementation. + void OnFocusIn() override {} + void OnTimeUpdate() override {} + void OnDurationChange() override {} + void OnPlay() override {} + void OnPause() override {} + void OnError() override {} + void OnLoadedMetadata() override {} + void OnKeyPress(KeyboardEvent* event) override {} + void OnKeyDown(KeyboardEvent* event) override {} + void OnKeyUp(KeyboardEvent* event) override {} + + protected: + MediaControlsNonTouchElement(MediaControlsNonTouchImpl& media_controls); + + private: + Member<MediaControlsNonTouchImpl> media_controls_; + + DISALLOW_COPY_AND_ASSIGN(MediaControlsNonTouchElement); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.cc b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.cc new file mode 100644 index 0000000..7bc91cf8 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.cc
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.h" + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h" + +namespace blink { + +MediaControlsNonTouchOverlayElement::MediaControlsNonTouchOverlayElement( + MediaControlsNonTouchImpl& media_controls) + : HTMLDivElement(media_controls.GetDocument()), + MediaControlsNonTouchElement(media_controls) { + SetShadowPseudoId(AtomicString("-internal-media-controls-non-touch-overlay")); + + MediaControlsNonTouchPlayButtonElement* play_button = + MakeGarbageCollected<MediaControlsNonTouchPlayButtonElement>( + media_controls); + + MediaControlsNonTouchVolumeButtonElement* volume_up_button = + MakeGarbageCollected<MediaControlsNonTouchVolumeButtonElement>( + media_controls, true); + MediaControlsNonTouchVolumeButtonElement* volume_down_button = + MakeGarbageCollected<MediaControlsNonTouchVolumeButtonElement>( + media_controls, false); + + MediaControlsNonTouchSeekButtonElement* seek_forward_button = + MakeGarbageCollected<MediaControlsNonTouchSeekButtonElement>( + media_controls, true); + MediaControlsNonTouchSeekButtonElement* seek_backward_button = + MakeGarbageCollected<MediaControlsNonTouchSeekButtonElement>( + media_controls, false); + + ParserAppendChild(volume_up_button); + ParserAppendChild(seek_backward_button); + ParserAppendChild(play_button); + ParserAppendChild(seek_forward_button); + ParserAppendChild(volume_down_button); +} + +void MediaControlsNonTouchOverlayElement::Trace(blink::Visitor* visitor) { + HTMLDivElement::Trace(visitor); + MediaControlsNonTouchElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.h b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.h new file mode 100644 index 0000000..34c060cc --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.h
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_OVERLAY_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_OVERLAY_ELEMENT_H_ + +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h" + +namespace blink { + +class MediaControlsNonTouchImpl; + +class MediaControlsNonTouchOverlayElement + : public HTMLDivElement, + public MediaControlsNonTouchElement { + USING_GARBAGE_COLLECTED_MIXIN(MediaControlsNonTouchOverlayElement); + + public: + MediaControlsNonTouchOverlayElement(MediaControlsNonTouchImpl&); + void Trace(blink::Visitor*) override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_OVERLAY_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.cc b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.cc new file mode 100644 index 0000000..2b1344d4 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.cc
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.h" + +#include "third_party/blink/renderer/core/dom/dom_token_list.h" +#include "third_party/blink/renderer/core/html/media/html_media_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h" + +namespace blink { + +namespace { + +const char kPlayingCSSClass[] = "playing"; +const char kPausedCSSClass[] = "paused"; + +} // namespace + +MediaControlsNonTouchPlayButtonElement::MediaControlsNonTouchPlayButtonElement( + MediaControlsNonTouchImpl& controls) + : HTMLDivElement(controls.GetDocument()), + MediaControlsNonTouchElement(controls) { + SetShadowPseudoId( + AtomicString("-internal-media-controls-non-touch-play-button")); + + controls.MediaElement().paused() ? OnPause() : OnPlay(); +} + +void MediaControlsNonTouchPlayButtonElement::OnPlay() { + classList().setValue(kPlayingCSSClass); +} + +void MediaControlsNonTouchPlayButtonElement::OnPause() { + classList().setValue(kPausedCSSClass); +} + +void MediaControlsNonTouchPlayButtonElement::Trace(blink::Visitor* visitor) { + HTMLDivElement::Trace(visitor); + MediaControlsNonTouchElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.h b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.h new file mode 100644 index 0000000..cafaf48 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_play_button_element.h
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_PLAY_BUTTON_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_PLAY_BUTTON_ELEMENT_H_ + +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h" + +namespace blink { + +class MediaControlsNonTouchPlayButtonElement + : public HTMLDivElement, + public MediaControlsNonTouchElement { + USING_GARBAGE_COLLECTED_MIXIN(MediaControlsNonTouchPlayButtonElement); + + public: + MediaControlsNonTouchPlayButtonElement(MediaControlsNonTouchImpl&); + + // MediaControlsNonTouchMediaEventListenerObserver implementation. + void OnPlay() override; + void OnPause() override; + + void Trace(blink::Visitor*) override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_PLAY_BUTTON_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.cc b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.cc new file mode 100644 index 0000000..0ed638f --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.cc
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.h" + +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h" + +namespace blink { + +MediaControlsNonTouchSeekButtonElement::MediaControlsNonTouchSeekButtonElement( + MediaControlsNonTouchImpl& controls, + bool forward) + : HTMLDivElement(controls.GetDocument()), + MediaControlsNonTouchElement(controls) { + SetShadowPseudoId(AtomicString( + forward ? "-internal-media-controls-non-touch-seek-forward-button" + : "-internal-media-controls-non-touch-seek-backward-button")); +} + +void MediaControlsNonTouchSeekButtonElement::Trace(blink::Visitor* visitor) { + HTMLDivElement::Trace(visitor); + MediaControlsNonTouchElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.h b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.h new file mode 100644 index 0000000..c01aa335 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_seek_button_element.h
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_SEEK_BUTTON_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_SEEK_BUTTON_ELEMENT_H_ + +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h" + +namespace blink { + +class MediaControlsNonTouchSeekButtonElement + : public HTMLDivElement, + public MediaControlsNonTouchElement { + USING_GARBAGE_COLLECTED_MIXIN(MediaControlsNonTouchSeekButtonElement); + + public: + MediaControlsNonTouchSeekButtonElement( + MediaControlsNonTouchImpl&, + bool /** True if it is a seek forward button, false otherwise. */); + void Trace(blink::Visitor*) override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_SEEK_BUTTON_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.cc b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.cc new file mode 100644 index 0000000..a4a80cf --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.cc
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.h" + +#include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h" + +namespace blink { + +MediaControlsNonTouchVolumeButtonElement:: + MediaControlsNonTouchVolumeButtonElement( + MediaControlsNonTouchImpl& controls, + bool up) + : HTMLDivElement(controls.GetDocument()), + MediaControlsNonTouchElement(controls) { + SetShadowPseudoId(AtomicString( + up ? "-internal-media-controls-non-touch-volume-up-button" + : "-internal-media-controls-non-touch-volume-down-button")); +} + +void MediaControlsNonTouchVolumeButtonElement::Trace(blink::Visitor* visitor) { + HTMLDivElement::Trace(visitor); + MediaControlsNonTouchElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.h b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.h new file mode 100644 index 0000000..31318ae1 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_volume_button_element.h
@@ -0,0 +1,27 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_VOLUME_BUTTON_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_VOLUME_BUTTON_ELEMENT_H_ + +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_element.h" + +namespace blink { + +class MediaControlsNonTouchVolumeButtonElement + : public HTMLDivElement, + public MediaControlsNonTouchElement { + USING_GARBAGE_COLLECTED_MIXIN(MediaControlsNonTouchVolumeButtonElement); + + public: + MediaControlsNonTouchVolumeButtonElement( + MediaControlsNonTouchImpl&, + bool /** True if it is a volume up button, false otherwise. */); + void Trace(blink::Visitor*) override; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_ELEMENTS_MEDIA_CONTROLS_NON_TOUCH_VOLUME_BUTTON_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.cc b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.cc index d2d37b3b5..882f4f1 100644 --- a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.cc +++ b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.cc
@@ -7,12 +7,15 @@ #include <algorithm> #include "third_party/blink/public/platform/web_screen_info.h" +#include "third_party/blink/renderer/core/dom/dom_token_list.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/html/media/html_media_element.h" #include "third_party/blink/renderer/core/page/chrome_client.h" +#include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h" +#include "third_party/blink/renderer/modules/media_controls/non_touch/elements/media_controls_non_touch_overlay_element.h" #include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" @@ -26,6 +29,12 @@ // Amount of volume to change when press up/down arrow. constexpr double kVolumeToChangeForNonTouch = 0.05; +// Amount of time that media controls are visible. +constexpr WTF::TimeDelta kTimeToHideMediaControls = + TimeDelta::FromMilliseconds(3000); + +const char kTransparentCSSClass[] = "transparent"; + } // namespace enum class MediaControlsNonTouchImpl::ArrowDirection { @@ -41,7 +50,11 @@ MediaControls(media_element), media_event_listener_( MakeGarbageCollected<MediaControlsNonTouchMediaEventListener>( - media_element)) { + media_element)), + hide_media_controls_timer_( + media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia), + this, + &MediaControlsNonTouchImpl::HideMediaControlsTimerFired) { SetShadowPseudoId(AtomicString("-internal-media-controls-non-touch")); media_event_listener_->AddObserver(this); } @@ -51,6 +64,16 @@ ShadowRoot& shadow_root) { MediaControlsNonTouchImpl* controls = MakeGarbageCollected<MediaControlsNonTouchImpl>(media_element); + MediaControlsNonTouchOverlayElement* overlay_element = + MakeGarbageCollected<MediaControlsNonTouchOverlayElement>(*controls); + + controls->ParserAppendChild(overlay_element); + + // Controls start hidden. + controls->MakeTransparent(); + + MediaControlsResourceLoader::InjectMediaControlsUAStyleSheet(); + shadow_root.ParserAppendChild(controls); return controls; } @@ -67,23 +90,55 @@ media_event_listener_->Detach(); } -void MediaControlsNonTouchImpl::MaybeShow() { +void MediaControlsNonTouchImpl::MakeOpaque() { // show controls + classList().Remove(kTransparentCSSClass); + + if (hide_media_controls_timer_.IsActive()) + StopHideMediaControlsTimer(); + StartHideMediaControlsTimer(); +} + +void MediaControlsNonTouchImpl::MakeTransparent() { + // hide controls + classList().Add(kTransparentCSSClass); +} + +void MediaControlsNonTouchImpl::MaybeShow() { + RemoveInlineStyleProperty(CSSPropertyDisplay); } void MediaControlsNonTouchImpl::Hide() { - // hide controls + SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); +} + +MediaControlsNonTouchMediaEventListener& +MediaControlsNonTouchImpl::MediaEventListener() const { + return *media_event_listener_; +} + +void MediaControlsNonTouchImpl::HideMediaControlsTimerFired(TimerBase*) { + MakeTransparent(); +} + +void MediaControlsNonTouchImpl::StartHideMediaControlsTimer() { + hide_media_controls_timer_.StartOneShot(kTimeToHideMediaControls, FROM_HERE); +} + +void MediaControlsNonTouchImpl::StopHideMediaControlsTimer() { + hide_media_controls_timer_.Stop(); } void MediaControlsNonTouchImpl::OnFocusIn() { if (MediaElement().ShouldShowControls()) - MaybeShow(); + MakeOpaque(); } void MediaControlsNonTouchImpl::OnKeyDown(KeyboardEvent* event) { bool handled = true; switch (event->keyCode()) { case VKEY_RETURN: + MakeOpaque(); MediaElement().TogglePlayState(); break; case VKEY_LEFT:
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h index 00ba8c6..34f9bfb5 100644 --- a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h +++ b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl.h
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/html/media/media_controls.h" #include "third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h" #include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/timer.h" namespace blink { @@ -57,6 +58,8 @@ void OnKeyDown(KeyboardEvent* event) override; void OnKeyUp(KeyboardEvent* event) override {} + MediaControlsNonTouchMediaEventListener& MediaEventListener() const; + void Trace(blink::Visitor*) override; private: @@ -79,7 +82,14 @@ // Node bool IsMediaControls() const override { return true; } + void MakeOpaque(); + void MakeTransparent(); + void HideMediaControlsTimerFired(TimerBase*); + void StartHideMediaControlsTimer(); + void StopHideMediaControlsTimer(); + Member<MediaControlsNonTouchMediaEventListener> media_event_listener_; + TaskRunnerTimer<MediaControlsNonTouchImpl> hide_media_controls_timer_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl_test.cc b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl_test.cc index c8dfcea..0e644e33 100644 --- a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl_test.cc +++ b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_impl_test.cc
@@ -8,7 +8,9 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/dom_token_list.h" #include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/media/html_media_element.h" @@ -96,6 +98,18 @@ MediaElement().DurationChanged(duration, false /* requestSeek */); } + bool IsControlsVisible() { + return !MediaControls().classList().contains("transparent"); + } + + Element* GetControlByShadowPseudoId(const char* shadow_pseudo_id) { + for (Element& element : ElementTraversal::DescendantsOf(MediaControls())) { + if (element.ShadowPseudoId() == shadow_pseudo_id) + return &element; + } + return nullptr; + } + void SetScreenOrientation(WebScreenOrientationType orientation_type) { chrome_client_->SetOrientation(orientation_type); } @@ -129,6 +143,18 @@ Persistent<MockChromeClientForNonTouchImpl> chrome_client_; }; +class MediaControlsNonTouchImplTestWithMockScheduler + : public MediaControlsNonTouchImplTest { + public: + MediaControlsNonTouchImplTestWithMockScheduler() { EnablePlatform(); } + + protected: + void SetUp() override { + platform()->AdvanceClockSeconds(1); + MediaControlsNonTouchImplTest::SetUp(); + } +}; + TEST_F(MediaControlsNonTouchImplTest, PlayPause) { MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone); MediaElement().Play(); @@ -186,6 +212,59 @@ ASSERT_EQ(MediaElement().volume(), 1); } +TEST_F(MediaControlsNonTouchImplTest, PlayPauseIcon) { + MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone); + + Element* play_button = GetControlByShadowPseudoId( + "-internal-media-controls-non-touch-play-button"); + ASSERT_NE(nullptr, play_button); + + MediaElement().pause(); + + MediaElement().Play(); + test::RunPendingTasks(); + ASSERT_TRUE(play_button->classList().contains("playing")); + ASSERT_FALSE(play_button->classList().contains("paused")); + + MediaElement().pause(); + test::RunPendingTasks(); + ASSERT_TRUE(play_button->classList().contains("paused")); + ASSERT_FALSE(play_button->classList().contains("playing")); +} + +TEST_F(MediaControlsNonTouchImplTestWithMockScheduler, ControlsShowAndHide) { + // Controls should starts hidden. + ASSERT_FALSE(IsControlsVisible()); + + // Controls should show when focus in. + MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone); + MediaElement().DispatchEvent(*Event::Create(event_type_names::kFocusin)); + ASSERT_TRUE(IsControlsVisible()); + + // Controls should hide after 3 seconds. + platform()->RunForPeriodSeconds(2.99); + ASSERT_TRUE(IsControlsVisible()); + platform()->RunForPeriodSeconds(0.01); + ASSERT_FALSE(IsControlsVisible()); + + // Controls should show upon pressing return key. + SimulateKeydownEvent(MediaElement(), VKEY_RETURN); + ASSERT_TRUE(IsControlsVisible()); + + // Controls should not disappear after 2 seconds. + platform()->RunForPeriodSeconds(2); + ASSERT_TRUE(IsControlsVisible()); + + // Pressing return key again should reset hiding timer. + SimulateKeydownEvent(MediaElement(), VKEY_RETURN); + platform()->RunForPeriodSeconds(2); + ASSERT_TRUE(IsControlsVisible()); + + // Controls should hide 3 seconds after last key press. + platform()->RunForPeriodSeconds(1); + ASSERT_FALSE(IsControlsVisible()); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h index 3d7d55b..98883d9 100644 --- a/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h +++ b/third_party/blink/renderer/modules/media_controls/non_touch/media_controls_non_touch_media_event_listener_observer.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_MEDIA_CONTROLS_NON_TOUCH_MEDIA_EVENT_LISTENER_OBSERVER_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_NON_TOUCH_MEDIA_CONTROLS_NON_TOUCH_MEDIA_EVENT_LISTENER_OBSERVER_H_ +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" + namespace blink { class KeyboardEvent;
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_forward.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_forward.svg new file mode 100644 index 0000000..a286740d --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_forward.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> + <path d="M8 36l17-12L8 12v24zm18-24v24l17-12-17-12z"/> + <path d="M0 0h48v48H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_rewind.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_rewind.svg new file mode 100644 index 0000000..d012f4cb --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_fast_rewind.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> + <path d="M22 36V12L5 24l17 12zm1-12l17 12V12L23 24z"/> + <path d="M0 0h48v48H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_pause.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_pause.svg new file mode 100644 index 0000000..5ac5ff20 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_pause.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#FFFFFF"> + <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> + <path d="M0 0h24v24H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_play_arrow.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_play_arrow.svg new file mode 100644 index 0000000..80296d81 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_play_arrow.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#FFFFFF"> + <path d="M8 5v14l11-7z"/> + <path d="M0 0h24v24H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_down.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_down.svg new file mode 100644 index 0000000..156d652 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_down.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> + <path d="M37 24c0-3.53-2.04-6.58-5-8.05v16.11c2.96-1.48 5-4.53 5-8.06zm-27-6v12h8l10 10V8L18 18h-8z"/> + <path d="M0 0h48v48H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_up.svg b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_up.svg new file mode 100644 index 0000000..4187bafa --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/ic_volume_up.svg
@@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 48 48" fill="#FFFFFF"> + <path d="M6 18v12h8l10 10V8L14 18H6zm27 6c0-3.53-2.04-6.58-5-8.05v16.11c2.96-1.48 5-4.53 5-8.06zM28 6.46v4.13c5.78 1.72 10 7.07 10 13.41s-4.22 11.69-10 13.41v4.13c8.01-1.82 14-8.97 14-17.54S36.01 8.28 28 6.46z"/> + <path d="M0 0h48v48H0z" fill="none"/> +</svg>
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/mediaControlsNonTouch.css b/third_party/blink/renderer/modules/media_controls/non_touch/resources/mediaControlsNonTouch.css new file mode 100644 index 0000000..e9e0294 --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/mediaControlsNonTouch.css
@@ -0,0 +1,99 @@ +/* Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. */ + +video::-internal-media-controls-non-touch { + position: relative; + direction: ltr; + display: flex; + flex-direction: column; + opacity: 1; + + margin-top: env(safe-area-inset-top); + margin-left: env(safe-area-inset-left); + margin-right: env(safe-area-inset-right); + margin-bottom: env(safe-area-inset-bottom); +} + +video::-internal-media-controls-non-touch.transparent { + opacity: 0; + transition: opacity .5s; +} + +video::-internal-media-controls-non-touch-overlay { + width: 104px; + height: 104px; + background-color: rgba(32, 33, 36, .9); + position: absolute; + margin: auto; + top: 0; + left: 0; + bottom: 0; + right: 0; + border-radius: 24px; +} + +video::-internal-media-controls-non-touch-volume-up-button { + width: 30px; + height: 30px; + margin-left: 37px /* (overlay width -width) / 2 */; + background-image: -webkit-image-set(url(ic_volume_up.svg) 1x); + background-size: 20px; + background-position: center; + background-repeat: no-repeat; +} + + +video::-internal-media-controls-non-touch-seek-backward-button { + width: 30px; + height: 30px; + margin-top: 7px /* (play button height + (2*play button border) - height) / 2 */; + float: left; + background-image: -webkit-image-set(url(ic_fast_rewind.svg) 1x); + background-size: 20px; + background-position: center; + background-repeat: no-repeat; +} + + +video::-internal-media-controls-non-touch-play-button { + width: 40px; + height: 40px; + border: 2px solid white; + background-position: center; + background-size: 24px; + background-repeat: no-repeat; + border-radius: 16px; + float: left; +} + +video::-internal-media-controls-non-touch-play-button.playing { + background-image: -webkit-image-set(url(ic_pause.svg) 1x); +} + +video::-internal-media-controls-non-touch-play-button.paused { + background-image: -webkit-image-set(url(ic_play_arrow.svg) 1x); +} + +video::-internal-media-controls-non-touch-seek-forward-button { + width: 30px; + height: 30px; + margin-top: 7px /* (play button height + (2*play button border) - height) / 2 */; + float: left; + background-image: -webkit-image-set(url(ic_fast_forward.svg) 1x); + background-size: 20px; + background-position: center; + background-repeat: no-repeat; +} + +video::-internal-media-controls-non-touch-volume-down-button { + width: 30px; + height: 30px; + margin-left: 37px /* (overlay width -width) / 2 */; + position: absolute; + bottom: 0; + background-image: -webkit-image-set(url(ic_volume_down.svg) 1x); + background-size: 20px; + background-position: center; + background-repeat: no-repeat; +}
diff --git a/third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.grd b/third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.grd new file mode 100644 index 0000000..db6416a --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.grd
@@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/media_controls_non_touch_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="media_controls_non_touch_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <structures fallback_to_low_resolution="true"> + <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_CONTROLS_NON_TOUCH_CSS" file="mediaControlsNonTouch.css" flattenhtml="true" compress="gzip"/> + </structures> + </release> +</grit>
diff --git a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc index b637964..22bf16e 100644 --- a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
@@ -696,22 +696,6 @@ CopyStringConstraint(constraints_in->videoKind(), naked_treatment, constraint_buffer.video_kind); } - if (constraints_in->hasDepthNear()) { - CopyDoubleConstraint(constraints_in->depthNear(), naked_treatment, - constraint_buffer.depth_near); - } - if (constraints_in->hasDepthFar()) { - CopyDoubleConstraint(constraints_in->depthFar(), naked_treatment, - constraint_buffer.depth_far); - } - if (constraints_in->hasFocalLengthX()) { - CopyDoubleConstraint(constraints_in->focalLengthX(), naked_treatment, - constraint_buffer.focal_length_x); - } - if (constraints_in->hasFocalLengthY()) { - CopyDoubleConstraint(constraints_in->focalLengthY(), naked_treatment, - constraint_buffer.focal_length_y); - } } WebMediaConstraints ConvertConstraintsToWeb(
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc index 4c1c465..0a6caebc 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -84,18 +84,16 @@ bool ConstraintSetHasNonImageCapture( const MediaTrackConstraintSet* constraint_set) { return constraint_set->hasAspectRatio() || - constraint_set->hasChannelCount() || constraint_set->hasDepthFar() || - constraint_set->hasDepthNear() || constraint_set->hasDeviceId() || + constraint_set->hasChannelCount() || constraint_set->hasDeviceId() || constraint_set->hasEchoCancellation() || constraint_set->hasNoiseSuppression() || constraint_set->hasAutoGainControl() || constraint_set->hasFacingMode() || constraint_set->hasResizeMode() || - constraint_set->hasFocalLengthX() || - constraint_set->hasFocalLengthY() || constraint_set->hasFrameRate() || - constraint_set->hasGroupId() || constraint_set->hasHeight() || - constraint_set->hasLatency() || constraint_set->hasSampleRate() || - constraint_set->hasSampleSize() || constraint_set->hasVideoKind() || - constraint_set->hasVolume() || constraint_set->hasWidth(); + constraint_set->hasFrameRate() || constraint_set->hasGroupId() || + constraint_set->hasHeight() || constraint_set->hasLatency() || + constraint_set->hasSampleRate() || constraint_set->hasSampleSize() || + constraint_set->hasVideoKind() || constraint_set->hasVolume() || + constraint_set->hasWidth(); } bool ConstraintSetHasImageAndNonImageCapture( @@ -480,17 +478,6 @@ if (platform_settings.HasVideoKind()) settings->setVideoKind(platform_settings.video_kind); } - if (RuntimeEnabledFeatures::MediaCaptureDepthEnabled() && - component_->Source()->GetType() == MediaStreamSource::kTypeVideo) { - if (platform_settings.HasDepthNear()) - settings->setDepthNear(platform_settings.depth_near); - if (platform_settings.HasDepthFar()) - settings->setDepthFar(platform_settings.depth_far); - if (platform_settings.HasFocalLengthX()) - settings->setFocalLengthX(platform_settings.focal_length_x); - if (platform_settings.HasFocalLengthY()) - settings->setFocalLengthY(platform_settings.focal_length_y); - } settings->setDeviceId(platform_settings.device_id); if (!platform_settings.group_id.IsNull()) settings->setGroupId(platform_settings.group_id);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc index 49ab7d3..a5860f8 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -448,15 +448,6 @@ settings.resize_mode = WebString::FromASCII(std::string( adapter_settings().target_size() ? WebMediaStreamTrack::kResizeModeRescale : WebMediaStreamTrack::kResizeModeNone)); - - const base::Optional<CameraCalibration> calibration = - source_->device().camera_calibration; - if (calibration) { - settings.depth_near = calibration->depth_near; - settings.depth_far = calibration->depth_far; - settings.focal_length_x = calibration->focal_length_x; - settings.focal_length_y = calibration->focal_length_y; - } if (source_->device().display_media_info.has_value()) { const auto& info = source_->device().display_media_info.value(); settings.display_surface = ToWebDisplaySurface(info->display_surface);
diff --git a/third_party/blink/renderer/modules/mediastream/media_track_constraint_set.idl b/third_party/blink/renderer/modules/mediastream/media_track_constraint_set.idl index 1cb0515a..2c995f4 100644 --- a/third_party/blink/renderer/modules/mediastream/media_track_constraint_set.idl +++ b/third_party/blink/renderer/modules/mediastream/media_track_constraint_set.idl
@@ -31,14 +31,9 @@ ConstrainDOMString groupId; // Media Capture Depth Stream Extensions // https://w3c.github.io/mediacapture-depth/#mediatrackconstraints - // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar, - // focalLengthX and focalLengthY attributes should be declared as partial + // TODO(riju): videoKind attribute should be declared as partial // dictionary but IDL parser can't support it yet. http://crbug.com/579896. [RuntimeEnabled=MediaCaptureDepthVideoKind] ConstrainDOMString videoKind; - [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble depthNear; - [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble depthFar; - [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble focalLengthX; - [RuntimeEnabled=MediaCaptureDepth] ConstrainDouble focalLengthY; // W3C Image Capture API // https://w3c.github.io/mediacapture-image/#mediatrackconstraintset-section // TODO(mcasas) move out when partial dictionaries are supported
diff --git a/third_party/blink/renderer/modules/mediastream/media_track_settings.idl b/third_party/blink/renderer/modules/mediastream/media_track_settings.idl index d4fd9fdc..5964c04 100644 --- a/third_party/blink/renderer/modules/mediastream/media_track_settings.idl +++ b/third_party/blink/renderer/modules/mediastream/media_track_settings.idl
@@ -24,14 +24,10 @@ [OriginTrialEnabled=ExperimentalHardwareEchoCancellation] DOMString echoCancellationType; // Media Capture Depth Stream Extensions // https://w3c.github.io/mediacapture-depth/#mediatracksettings-dictionary - // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar, - // focalLengthX and focalLengthY attributes should be declared as partial + // TODO(riju): videoKind attribute should be declared as partial // dictionary but IDL parser can't support it yet. http://crbug.com/579896. [RuntimeEnabled=MediaCaptureDepthVideoKind] DOMString videoKind; - [RuntimeEnabled=MediaCaptureDepth] double depthNear; - [RuntimeEnabled=MediaCaptureDepth] double depthFar; - [RuntimeEnabled=MediaCaptureDepth] double focalLengthX; - [RuntimeEnabled=MediaCaptureDepth] double focalLengthY; + // W3C Image Capture API // https://w3c.github.io/mediacapture-image/#mediatracksettings-section // TODO(mcasas) move out when partial dictionaries are supported
diff --git a/third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.idl b/third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.idl index 6ca0f003a..7b02b8c6 100644 --- a/third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.idl +++ b/third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.idl
@@ -29,14 +29,9 @@ // Media Capture Depth Stream Extensions // https://w3c.github.io/mediacapture-depth - // TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar, - // focalLengthX and focalLengthY attributes should be declared as partial + // TODO(riju): videoKind attribute should be declared as partial // dictionary but IDL parser can't support it yet. http://crbug.com/579896. [RuntimeEnabled=MediaCaptureDepthVideoKind] boolean videoKind = true; - [RuntimeEnabled=MediaCaptureDepth] boolean depthNear = true; - [RuntimeEnabled=MediaCaptureDepth] boolean depthFar = true; - [RuntimeEnabled=MediaCaptureDepth] boolean focalLengthX = true; - [RuntimeEnabled=MediaCaptureDepth] boolean focalLengthY = true; // W3C Image Capture API // https://w3c.github.io/mediacapture-image/#mediatracksupportedconstraints-section
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc index a2aba69..ec6d7b6 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -255,22 +255,6 @@ &WebMediaTrackConstraintSet::video_kind)) { counter.Count(WebFeature::kMediaStreamConstraintsVideoKind); } - if (RequestUsesNumericConstraint(constraints, - &WebMediaTrackConstraintSet::depth_near)) { - counter.Count(WebFeature::kMediaStreamConstraintsDepthNear); - } - if (RequestUsesNumericConstraint(constraints, - &WebMediaTrackConstraintSet::depth_far)) { - counter.Count(WebFeature::kMediaStreamConstraintsDepthFar); - } - if (RequestUsesNumericConstraint( - constraints, &WebMediaTrackConstraintSet::focal_length_x)) { - counter.Count(WebFeature::kMediaStreamConstraintsFocalLengthX); - } - if (RequestUsesNumericConstraint( - constraints, &WebMediaTrackConstraintSet::focal_length_y)) { - counter.Count(WebFeature::kMediaStreamConstraintsFocalLengthY); - } if (RequestUsesDiscreteConstraint( constraints, &WebMediaTrackConstraintSet::media_stream_source)) { counter.Count(WebFeature::kMediaStreamConstraintsMediaStreamSourceVideo);
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 2be8d2d..50a82a8 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -167,9 +167,8 @@ "geolocation/position.idl", "geolocation/position_error.idl", "hid/hid.idl", - "idle/idle_manager.idl", + "idle/idle_detector.idl", "idle/idle_state.idl", - "idle/idle_status.idl", "imagecapture/image_capture.idl", "imagecapture/media_settings_range.idl", "imagecapture/photo_capabilities.idl", @@ -813,8 +812,6 @@ "gamepad/navigator_gamepad.idl", "geolocation/navigator_geolocation.idl", "hid/navigator_hid.idl", - "idle/navigator_idle.idl", - "idle/worker_navigator_idle.idl", "indexeddb/window_indexed_database.idl", "indexeddb/worker_global_scope_indexed_database.idl", "installedapp/navigator_installed_app.idl",
diff --git a/third_party/blink/renderer/platform/exported/web_media_constraints.cc b/third_party/blink/renderer/platform/exported/web_media_constraints.cc index 8f28f0d2..ee7fe633 100644 --- a/third_party/blink/renderer/platform/exported/web_media_constraints.cc +++ b/third_party/blink/renderer/platform/exported/web_media_constraints.cc
@@ -352,10 +352,6 @@ disable_local_echo("disableLocalEcho"), group_id("groupId"), video_kind("videoKind"), - depth_near("depthNear"), - depth_far("depthFar"), - focal_length_x("focalLengthX"), - focal_length_y("focalLengthY"), media_stream_source("mediaStreamSource"), render_to_associated_sink("chromeRenderToAssociatedSink"), goog_echo_cancellation("googEchoCancellation"), @@ -412,10 +408,6 @@ &device_id, &group_id, &video_kind, - &depth_near, - &depth_far, - &focal_length_x, - &focal_length_y, &media_stream_source, &disable_local_echo, &render_to_associated_sink,
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc index cc37b3b..e775de5 100644 --- a/third_party/blink/renderer/platform/exported/web_url_request.cc +++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -176,8 +176,8 @@ resource_request_->AddHTTPHeaderField(name, value); } -void WebURLRequest::ClearHTTPHeaderField(const WebString& name) { - resource_request_->ClearHTTPHeaderField(name); +void WebURLRequest::ClearHttpHeaderField(const WebString& name) { + resource_request_->ClearHttpHeaderField(name); } void WebURLRequest::VisitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const { @@ -214,10 +214,6 @@ return resource_request_->GetRequestContext(); } -network::mojom::RequestContextFrameType WebURLRequest::GetFrameType() const { - return resource_request_->GetFrameType(); -} - network::mojom::ReferrerPolicy WebURLRequest::GetReferrerPolicy() const { return resource_request_->GetReferrerPolicy(); }
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc index 7f66f2a..89042a62 100644 --- a/third_party/blink/renderer/platform/exported/web_url_response.cc +++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -182,8 +182,8 @@ resource_response_->AddHTTPHeaderField(name, value); } -void WebURLResponse::ClearHTTPHeaderField(const WebString& name) { - resource_response_->ClearHTTPHeaderField(name); +void WebURLResponse::ClearHttpHeaderField(const WebString& name) { + resource_response_->ClearHttpHeaderField(name); } void WebURLResponse::VisitHTTPHeaderFields(
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc index 8724a3f..a50636c3 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -1233,8 +1233,6 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) { auto color_params = CanvasColorParams(kSRGBCanvasColorSpace, kRGBA8CanvasPixelFormat, kOpaque); - ASSERT_TRUE(color_params.NeedsSkColorSpaceXformCanvas()); - std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration, color_params);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc index cdcba06e..83f5651 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -48,8 +48,8 @@ : CanvasColorParams(info.refColorSpace(), info.colorType()) {} bool CanvasColorParams::NeedsSkColorSpaceXformCanvas() const { - return color_space_ == kSRGBCanvasColorSpace && - pixel_format_ == kRGBA8CanvasPixelFormat; + // Part of larger effort to remove ColorSpaceXformCanvas (reed) + return false; } std::unique_ptr<cc::PaintCanvas> CanvasColorParams::WrapCanvas(
diff --git a/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc b/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc index b84a3ce..a2367811 100644 --- a/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc +++ b/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.cc
@@ -33,9 +33,12 @@ : response_url_(response.CurrentRequestUrl()), response_time_(response.ResponseTime()), code_cache_type_(code_cache_type) { - DCHECK(response.CacheStorageCacheName().IsNull()); + // WebAssembly always uses the site isolated code cache. + DCHECK(response.CacheStorageCacheName().IsNull() || + code_cache_type_ == blink::mojom::CodeCacheType::kWebAssembly); DCHECK(!response.WasFetchedViaServiceWorker() || - response.IsServiceWorkerPassThrough()); + response.IsServiceWorkerPassThrough() || + code_cache_type_ == blink::mojom::CodeCacheType::kWebAssembly); } void CachedMetadataSenderImpl::Send(const uint8_t* data, size_t size) { @@ -92,7 +95,9 @@ const ResourceResponse& response, blink::mojom::CodeCacheType code_cache_type, scoped_refptr<const SecurityOrigin> requestor_origin) { - if (!response.WasFetchedViaServiceWorker()) { + // Non-ServiceWorker scripts and WebAssembly use the site isolated code cache. + if (!response.WasFetchedViaServiceWorker() || + code_cache_type == blink::mojom::CodeCacheType::kWebAssembly) { return std::make_unique<CachedMetadataSenderImpl>(response, code_cache_type); } @@ -123,17 +128,25 @@ bool ShouldUseIsolatedCodeCache(mojom::RequestContextType request_context, const ResourceResponse& response) { - return RuntimeEnabledFeatures::IsolatedCodeCacheEnabled() && - // Service worker script has its own code cache. - request_context != mojom::RequestContextType::SERVICE_WORKER && - // Also, we only support code cache for other service worker provided - // resources when a direct pass-through fetch handler is used. If the - // service worker synthesizes a new Response or provides a Response - // fetched from a different URL, then do not use the code cache. - // Also, responses coming from cache storage use a separate code - // cache mechanism. - (!response.WasFetchedViaServiceWorker() || - response.IsServiceWorkerPassThrough()); + if (!RuntimeEnabledFeatures::IsolatedCodeCacheEnabled()) + return false; + + // WebAssembly always uses the site isolated code cache. + if (response.MimeType() == "application/wasm") + return true; + + // Service worker script has its own code cache. + if (request_context == mojom::RequestContextType::SERVICE_WORKER) + return false; + + // Also, we only support code cache for other service worker provided + // resources when a direct pass-through fetch handler is used. If the service + // worker synthesizes a new Response or provides a Response fetched from a + // different URL, then do not use the code cache. + // Also, responses coming from cache storage use a separate code cache + // mechanism. + return !response.WasFetchedViaServiceWorker() || + response.IsServiceWorkerPassThrough(); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc index 33fc681..8d04c950 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -54,8 +54,6 @@ RawResource* RawResource::FetchImport(FetchParameters& params, ResourceFetcher* fetcher, RawResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); params.SetRequestContext(mojom::RequestContextType::IMPORT); return ToRawResource(fetcher->RequestResource( params, RawResourceFactory(ResourceType::kImportResource), client)); @@ -64,8 +62,6 @@ RawResource* RawResource::Fetch(FetchParameters& params, ResourceFetcher* fetcher, RawResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); DCHECK_NE(params.GetResourceRequest().GetRequestContext(), mojom::RequestContextType::UNSPECIFIED); return ToRawResource(fetcher->RequestResource( @@ -75,8 +71,6 @@ RawResource* RawResource::FetchMedia(FetchParameters& params, ResourceFetcher* fetcher, RawResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); auto context = params.GetResourceRequest().GetRequestContext(); DCHECK(context == mojom::RequestContextType::AUDIO || context == mojom::RequestContextType::VIDEO); @@ -90,8 +84,6 @@ RawResource* RawResource::FetchTextTrack(FetchParameters& params, ResourceFetcher* fetcher, RawResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); params.SetRequestContext(mojom::RequestContextType::TRACK); return ToRawResource(fetcher->RequestResource( params, RawResourceFactory(ResourceType::kTextTrack), client)); @@ -100,8 +92,6 @@ RawResource* RawResource::FetchManifest(FetchParameters& params, ResourceFetcher* fetcher, RawResourceClient* client) { - DCHECK_EQ(params.GetResourceRequest().GetFrameType(), - network::mojom::RequestContextFrameType::kNone); DCHECK_EQ(params.GetResourceRequest().GetRequestContext(), mojom::RequestContextType::MANIFEST); return ToRawResource(fetcher->RequestResource(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index f60888c..ba52e0e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -939,7 +939,7 @@ } void Resource::ClearRangeRequestHeader() { - resource_request_.ClearHTTPHeaderField("range"); + resource_request_.ClearHttpHeaderField("range"); } void Resource::RevalidationSucceeded(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index f055cb38..1f5d8ce 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -139,25 +139,9 @@ if (request.GetRequestContext() == mojom::RequestContextType::OBJECT) return false; - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, - request.GetFrameType()); - // Optimize for the case where we can handle a data URL locally. We must - // skip this for data URLs targeted at frames since those could trigger a - // download. - // - // NOTE: We special case MIME types we can render both for performance - // reasons as well as to support unit tests. - if (request.GetFrameType() != - network::mojom::RequestContextFrameType::kTopLevel && - request.GetFrameType() != - network::mojom::RequestContextFrameType::kNested) { - return true; - } - - if (network_utils::IsDataURLMimeTypeSupported(request.Url())) - return true; - - return false; + // Main resources are handled in the browser, so we can handle data url + // subresources locally. + return true; } } // namespace @@ -692,9 +676,6 @@ // The following parameters never change during the lifetime of a request. mojom::RequestContextType request_context = initial_request.GetRequestContext(); - network::mojom::RequestContextFrameType frame_type = - initial_request.GetFrameType(); - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, frame_type); network::mojom::FetchRequestMode fetch_request_mode = initial_request.GetFetchRequestMode(); network::mojom::FetchCredentialsMode fetch_credentials_mode = @@ -816,7 +797,6 @@ // The following parameters never change during the lifetime of a request. DCHECK_EQ(new_request->GetRequestContext(), request_context); - DCHECK_EQ(new_request->GetFrameType(), frame_type); DCHECK_EQ(new_request->GetFetchRequestMode(), fetch_request_mode); DCHECK_EQ(new_request->GetFetchCredentialsMode(), fetch_credentials_mode);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc index f4e2b81..f10939d 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -69,7 +69,6 @@ app_cache_host_id_(0), previews_state_(WebURLRequest::kPreviewsUnspecified), request_context_(mojom::RequestContextType::UNSPECIFIED), - frame_type_(network::mojom::RequestContextFrameType::kNone), fetch_request_mode_(network::mojom::FetchRequestMode::kNoCors), fetch_importance_mode_(mojom::FetchImportanceMode::kImportanceAuto), fetch_credentials_mode_(network::mojom::FetchCredentialsMode::kInclude), @@ -302,7 +301,7 @@ AddHTTPHeaderField(it->key, it->value); } -void ResourceRequest::ClearHTTPHeaderField(const AtomicString& name) { +void ResourceRequest::ClearHttpHeaderField(const AtomicString& name) { http_header_fields_.Remove(name); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h index 9a7a5ca..6834b30 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -137,7 +137,7 @@ void SetHTTPHeaderField(const AtomicString& name, const AtomicString& value); void AddHTTPHeaderField(const AtomicString& name, const AtomicString& value); void AddHTTPHeaderFields(const HTTPHeaderMap& header_fields); - void ClearHTTPHeaderField(const AtomicString& name); + void ClearHttpHeaderField(const AtomicString& name); const AtomicString& HttpContentType() const { return HttpHeaderField(http_names::kContentType); @@ -288,12 +288,6 @@ request_context_ = context; } - network::mojom::RequestContextFrameType GetFrameType() const { - // TODO(dgozman): remove this getter. - DCHECK_EQ(network::mojom::RequestContextFrameType::kNone, frame_type_); - return frame_type_; - } - network::mojom::FetchRequestMode GetFetchRequestMode() const { return fetch_request_mode_; } @@ -467,7 +461,6 @@ WebURLRequest::PreviewsState previews_state_; scoped_refptr<SharableExtraData> sharable_extra_data_; mojom::RequestContextType request_context_; - network::mojom::RequestContextFrameType frame_type_; network::mojom::FetchRequestMode fetch_request_mode_; mojom::FetchImportanceMode fetch_importance_mode_; network::mojom::FetchCredentialsMode fetch_credentials_mode_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc index b954c46f..e7f0f96 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -253,7 +253,7 @@ result.stored_value->value = result.stored_value->value + ", " + value; } -void ResourceResponse::ClearHTTPHeaderField(const AtomicString& name) { +void ResourceResponse::ClearHttpHeaderField(const AtomicString& name) { http_header_fields_.Remove(name); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h index fd92f2e..29691fe 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -207,7 +207,7 @@ const AtomicString& HttpHeaderField(const AtomicString& name) const; void SetHTTPHeaderField(const AtomicString& name, const AtomicString& value); void AddHTTPHeaderField(const AtomicString& name, const AtomicString& value); - void ClearHTTPHeaderField(const AtomicString& name); + void ClearHttpHeaderField(const AtomicString& name); const HTTPHeaderMap& HttpHeaderFields() const; bool IsAttachment() const;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc index 9c6f4e0..9a220d1 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -187,7 +187,7 @@ response.SetHTTPHeaderField(http_names::kVary, http_names::kUserAgent); resource->SetResponse(response); EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request)); - new_request.ClearHTTPHeaderField(http_names::kUserAgent); + new_request.ClearHttpHeaderField(http_names::kUserAgent); ResourceRequest old_request(url); old_request.SetHTTPHeaderField(http_names::kUserAgent, "something"); @@ -197,7 +197,7 @@ resource->FinishForTest(); // Header present on old but not new - new_request.ClearHTTPHeaderField(http_names::kUserAgent); + new_request.ClearHttpHeaderField(http_names::kUserAgent); response.SetHTTPHeaderField(http_names::kVary, http_names::kUserAgent); resource->SetResponse(response); EXPECT_TRUE(resource->MustReloadDueToVaryHeader(new_request));
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc index 6cc666a..a9db7f0 100644 --- a/third_party/blink/renderer/platform/network/http_parsers.cc +++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -612,7 +612,7 @@ base::StringPiece header_string_piece(adaptor.AsStringPiece()); size_t iterator = 0; - response->ClearHTTPHeaderField(header); + response->ClearHttpHeaderField(header); while (response_headers->EnumerateHeader(&iterator, header_string_piece, &value)) { response->AddHTTPHeaderField(header, WebString::FromLatin1(value));
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index da8e5c6..6f1f4a3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -791,10 +791,6 @@ status: {"Android": "stable"}, }, { - name: "MediaCaptureDepth", - status: "experimental", - }, - { name: "MediaCaptureDepthVideoKind", status: "experimental", }, @@ -843,6 +839,11 @@ { name: "MergeBlockingNonBlockingPools", }, + // Support for META tag for setting supported-color-schemes used for opting + // into dark UA theming and opting out of forced dark mode. + { + name: "MetaSupportedColorSchemes", + }, // This is enabled by default on Windows only. The only part that's // "experimental" is the support on other platforms. {
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn index d99d4da..884a30d 100644 --- a/third_party/blink/renderer/platform/scheduler/BUILD.gn +++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -28,6 +28,7 @@ "common/scheduler_helper.cc", "common/scheduler_helper.h", "common/scheduling_lifecycle_state.cc", + "common/scheduling_policy.cc", "common/simple_thread_scheduler.cc", "common/simple_thread_scheduler.h", "common/single_thread_idle_task_runner.cc",
diff --git a/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc index a635738d..a23ec4f3 100644 --- a/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
@@ -51,9 +51,17 @@ FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle FrameOrWorkerScheduler::RegisterFeature(SchedulingPolicy::Feature feature, SchedulingPolicy policy) { + DCHECK(!SchedulingPolicy::IsFeatureSticky(feature)); return SchedulingAffectingFeatureHandle(feature, policy, GetWeakPtr()); } +void FrameOrWorkerScheduler::RegisterStickyFeature( + SchedulingPolicy::Feature feature, + SchedulingPolicy policy) { + DCHECK(SchedulingPolicy::IsFeatureSticky(feature)); + OnStartedUsingFeature(feature, policy); +} + std::unique_ptr<FrameOrWorkerScheduler::LifecycleObserverHandle> FrameOrWorkerScheduler::AddLifecycleObserver(ObserverType type, Observer* observer) {
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc new file mode 100644 index 0000000..8b8dae0 --- /dev/null +++ b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h" + +#include "base/logging.h" + +namespace blink { + +bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) { + switch (feature) { + case Feature::kWebSocket: + case Feature::kWebRTC: + return false; + case Feature::kStickyFeatureForTesting: + return true; + case Feature::kCount: + NOTREACHED(); + return false; + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h index 9aa1a6b..37c1849 100644 --- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -68,6 +68,8 @@ // Return nullptr. NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override; + void SetV8Isolate(v8::Isolate* isolate) override {} + private: DISALLOW_COPY_AND_ASSIGN(SimpleThreadScheduler); };
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h index 5943e5d..be744ad 100644 --- a/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h
@@ -9,6 +9,7 @@ #include <random> +#include "base/logging.h" #include "base/single_thread_task_runner.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/common/single_thread_idle_task_runner.h" @@ -22,6 +23,10 @@ } } // namespace base +namespace v8 { +class Isolate; +} + namespace blink { namespace scheduler { @@ -51,9 +56,14 @@ virtual const base::TickClock* GetTickClock() = 0; + void SetV8Isolate(v8::Isolate* isolate) override { isolate_ = isolate; } + v8::Isolate* isolate() const { return isolate_; } + protected: ThreadSchedulerImpl() {} ~ThreadSchedulerImpl() override = default; + + v8::Isolate* isolate_ = nullptr; }; } // namespace scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index a2e2d6e..6384ac0e 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -607,6 +607,8 @@ main_thread_scheduler_->DidCommitProvisionalLoad( is_web_history_inert_commit, navigation_type == NavigationType::kReload, is_main_frame); + if (navigation_type != NavigationType::kSameDocument) + ResetForNavigation(); } WebScopedVirtualTimePauser FrameSchedulerImpl::CreateWebScopedVirtualTimePauser( @@ -615,6 +617,20 @@ return WebScopedVirtualTimePauser(main_thread_scheduler_, duration, name); } +void FrameSchedulerImpl::ResetForNavigation() { + // Reset "sticky" features when the frame navigates. + for (auto it = back_forward_cache_opt_out_counts_.begin(); + it != back_forward_cache_opt_out_counts_.end();) { + if (SchedulingPolicy::IsFeatureSticky(it->first)) { + it = back_forward_cache_opt_out_counts_.erase(it); + } else { + ++it; + } + } + opted_out_from_back_forward_cache_ = + !back_forward_cache_opt_out_counts_.empty(); +} + void FrameSchedulerImpl::OnStartedUsingFeature( SchedulingPolicy::Feature feature, const SchedulingPolicy& policy) {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h index 76d49b6..b50b70f 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -163,10 +163,6 @@ WTF::HashSet<SchedulingPolicy::Feature> GetActiveFeaturesOptingOutFromBackForwardCache(); - // Expose for testing. - using FrameOrWorkerScheduler::OnStartedUsingFeature; - using FrameOrWorkerScheduler::OnStoppedUsingFeature; - protected: FrameSchedulerImpl(MainThreadSchedulerImpl* main_thread_scheduler, PageSchedulerImpl* parent_page_scheduler, @@ -248,6 +244,9 @@ static base::Optional<MainThreadTaskQueue::QueueTraits> CreateQueueTraitsForTaskType(TaskType); + // Reset the state which should not persist across navigations. + void ResetForNavigation(); + // Create QueueTraits for the default (non-finch) task queues. static MainThreadTaskQueue::QueueTraits ThrottleableTaskQueueTraits(); static MainThreadTaskQueue::QueueTraits DeferrableTaskQueueTraits();
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 35aae64..0589320 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -2529,19 +2529,9 @@ } } - if (!is_disjoint_window) + if (!is_disjoint_window || !ContainsLocalMainFrame()) return; - if (!ContainsLocalMainFrame()) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "RendererScheduler.ExpectedTaskQueueingDurationWithoutMainFrame", - base::saturated_cast<base::HistogramBase::Sample>( - queueing_time.InMicroseconds()), - kMinExpectedQueueingTimeBucket, kMaxExpectedQueueingTimeBucket, - kNumberExpectedQueueingTimeBuckets); - return; - } - UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration", queueing_time); UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.ExpectedTaskQueueingDuration3",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc index 95ffa36a..0905b1f 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
@@ -7,8 +7,11 @@ #include "base/feature_list.h" #include "base/memory/memory_pressure_listener.h" #include "base/metrics/field_trial_params.h" +#include "base/rand_util.h" +#include "build/build_config.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/page/launching_process_state.h" +#include "third_party/blink/public/platform/platform.h" namespace blink { @@ -24,10 +27,29 @@ kFreezePurgeMemoryAllPagesFrozenDelayInMinutes.Get()); } +int MinTimeToPurgeAfterBackgroundedInSeconds() { + static const base::FeatureParam<int> + kMinTimeToPurgeAfterBackgroundedInMinutes{ + &blink::features::kPurgeRendererMemoryWhenBackgrounded, + "min-delay-in-minutes", + MemoryPurgeManager::kDefaultMinTimeToPurgeAfterBackgrounded}; + return kMinTimeToPurgeAfterBackgroundedInMinutes.Get() * 60; +} + +int MaxTimeToPurgeAfterBackgroundedInSeconds() { + static const base::FeatureParam<int> + kMaxTimeToPurgeAfterBackgroundedInMinutes{ + &blink::features::kPurgeRendererMemoryWhenBackgrounded, + "max-delay-in-minutes", + MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded}; + return kMaxTimeToPurgeAfterBackgroundedInMinutes.Get() * 60; +} + } // namespace MemoryPurgeManager::MemoryPurgeManager() : renderer_backgrounded_(kLaunchingProcessIsBackgrounded), + backgrounded_purge_pending_(false), total_page_count_(0), frozen_page_count_(0) {} @@ -58,24 +80,52 @@ DCHECK_LT(frozen_page_count_, total_page_count_); frozen_page_count_++; - if (purge_timer_.IsRunning()) - return; - - if (!CanPurge()) - return; - - purge_timer_.Start(FROM_HERE, FreezePurgeMemoryAllPagesFrozenDelay(), this, - &MemoryPurgeManager::PerformMemoryPurge); + if (CanPurge()) + RequestMemoryPurgeWithDelay(FreezePurgeMemoryAllPagesFrozenDelay()); } void MemoryPurgeManager::OnPageResumed() { DCHECK_GT(frozen_page_count_, 0); frozen_page_count_--; + if (!CanPurge()) purge_timer_.Stop(); + base::MemoryPressureListener::SetNotificationsSuppressed(false); } +void MemoryPurgeManager::SetRendererBackgrounded(bool backgrounded) { + renderer_backgrounded_ = backgrounded; + if (backgrounded) { + OnRendererBackgrounded(); + } else { + OnRendererForegrounded(); + } +} + +void MemoryPurgeManager::OnRendererBackgrounded() { + if (!base::FeatureList::IsEnabled( + features::kPurgeRendererMemoryWhenBackgrounded)) + return; + + backgrounded_purge_pending_ = true; + RequestMemoryPurgeWithDelay(GetTimeToPurgeAfterBackgrounded()); +} + +void MemoryPurgeManager::OnRendererForegrounded() { + backgrounded_purge_pending_ = false; + purge_timer_.Stop(); +} + +void MemoryPurgeManager::RequestMemoryPurgeWithDelay(base::TimeDelta delay) { + if (purge_timer_.IsRunning() && + (purge_timer_.desired_run_time() - base::TimeTicks::Now()) < delay) + return; + + purge_timer_.Start(FROM_HERE, delay, this, + &MemoryPurgeManager::PerformMemoryPurge); +} + void MemoryPurgeManager::PerformMemoryPurge() { DCHECK(CanPurge()); @@ -84,15 +134,17 @@ if (AreAllPagesFrozen()) base::MemoryPressureListener::SetNotificationsSuppressed(true); -} -void MemoryPurgeManager::SetRendererBackgrounded(bool backgrounded) { - if (!backgrounded) - purge_timer_.Stop(); - renderer_backgrounded_ = backgrounded; + if (backgrounded_purge_pending_) { + Platform::Current()->RecordMetricsForBackgroundedRendererPurge(); + backgrounded_purge_pending_ = false; + } } bool MemoryPurgeManager::CanPurge() const { + if (backgrounded_purge_pending_) + return true; + if (!renderer_backgrounded_) return false; @@ -108,4 +160,11 @@ return total_page_count_ == frozen_page_count_; } +base::TimeDelta MemoryPurgeManager::GetTimeToPurgeAfterBackgrounded() const { + int min_time_in_seconds = MinTimeToPurgeAfterBackgroundedInSeconds(); + int max_time_in_seconds = MaxTimeToPurgeAfterBackgroundedInSeconds(); + return base::TimeDelta::FromSeconds( + base::RandInt(min_time_in_seconds, max_time_in_seconds)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h index 907145f..834e75b 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
@@ -12,7 +12,7 @@ namespace blink { -// Manages the process-wide memory purging associated with freezing. +// Manages process-wide proactive memory purging. class PLATFORM_EXPORT MemoryPurgeManager { public: MemoryPurgeManager(); @@ -25,7 +25,8 @@ // Called when a page is frozen. If all pages are frozen or // |kFreezePurgeMemoryAllPagesFrozen| is disabled, and the renderer is - // backgrounded, ensures that a delayed memory purge is scheduled. + // backgrounded, ensures that a delayed memory purge is scheduled. If the + // timer is already running, uses the smallest requested delay. void OnPageFrozen(); // Called when a page is resumed (unfrozen). Has the effect of unsuppressing @@ -35,16 +36,46 @@ // Called when the renderer's process priority changes. void SetRendererBackgrounded(bool backgrounded); + // Called when the renderer is backgrounded. Starts a timer responsible for + // performing a memory purge upon expiry, if the + // kPurgeRendererMemoryWhenBackgrounded feature is enabled. If the timer is + // already running, uses the smallest requested delay. + void OnRendererBackgrounded(); + + // Called when the renderer is foregrounded. Has the effect of cancelling a + // queued memory purge. + void OnRendererForegrounded(); + // The time of purging after all pages have been frozen. static constexpr int kDefaultTimeToPurgeAfterFreezing = 0; + // The time of first purging after a renderer is backgrounded. The value was + // initially set to 30 minutes, but it was reduced to 1 minute because this + // reduced the memory usage of a renderer 15 minutes after it was + // backgrounded. + // + // Experiment results: + // https://docs.google.com/document/d/1E88EYNlZE1DhmlgmjUnGnCAASm8-tWCAWXy8p53vmwc/edit?usp=sharing + static constexpr int kDefaultMinTimeToPurgeAfterBackgrounded = 1; + static constexpr int kDefaultMaxTimeToPurgeAfterBackgrounded = 4; + private: + // Starts |purge_timer_| to trigger a delayed memory purge. If the timer is + // already running, starts the timer with the smaller of the requested delay + // and the remaining delay. + void RequestMemoryPurgeWithDelay(base::TimeDelta delay); + // Called when the timer expires. Simulates a critical memory pressure signal // to purge memory. Suppresses memory pressure notifications if all pages // are frozen. void PerformMemoryPurge(); - // Returns true if all of the following are true: + // Returns true if: + // - The kPurgeRendererMemoryWhenBackgrounded feature is enabled, and the + // renderer is awaiting a purge after being backgrounded. + // + // or if all of the following are true: + // // - The renderer is backgrounded. // - All pages are frozen or kFreezePurgeMemoryAllPagesFrozen is disabled. bool CanPurge() const; @@ -52,8 +83,17 @@ // Returns true if |total_page_count_| == |frozen_page_count_| bool AreAllPagesFrozen() const; + base::TimeDelta GetTimeToPurgeAfterBackgrounded() const; + bool renderer_backgrounded_; + // Keeps track of whether a memory purge was requested as a consequence of the + // renderer transitioning to a backgrounded state. Prevents purges from being + // cancelled if a purge was requested upon backgrounding the renderer and the + // renderer is still backgrounded. Supports the metrics collection associated + // with the PurgeAndSuspend experiment. + bool backgrounded_purge_pending_; + int total_page_count_; int frozen_page_count_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc index 624111b..ea61636 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
@@ -47,10 +47,11 @@ protected: void SetupDelayedPurgeAfterFreezeExperiment() { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - features::kFreezePurgeMemoryAllPagesFrozen, - {{"delay-in-minutes", - base::IntToString(kDelayForPurgeAfterFreeze.InMinutes())}}); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kFreezePurgeMemoryAllPagesFrozen, + {{"delay-in-minutes", + base::IntToString(kDelayForPurgeAfterFreeze.InMinutes())}}}}, + {features::kPurgeRendererMemoryWhenBackgrounded}); } void ExpectMemoryPressure( @@ -89,6 +90,10 @@ // Verify that OnPageFrozen() triggers a memory pressure notification in a // backgrounded renderer. TEST_F(MemoryPurgeManagerTest, PageFrozenInBackgroundedRenderer) { + scoped_feature_list_.InitWithFeatures( + {} /* enabled */, + {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(true); memory_purge_manager_.OnPageFrozen(); @@ -98,6 +103,10 @@ // Verify that OnPageFrozen() does not trigger a memory pressure notification in // a foregrounded renderer. TEST_F(MemoryPurgeManagerTest, PageFrozenInForegroundedRenderer) { + scoped_feature_list_.InitWithFeatures( + {} /* enabled */, + {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(false); memory_purge_manager_.OnPageFrozen(); @@ -105,6 +114,10 @@ } TEST_F(MemoryPurgeManagerTest, PageResumedUndoMemoryPressureSuppression) { + scoped_feature_list_.InitWithFeatures( + {} /* enabled */, + {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); memory_purge_manager_.SetRendererBackgrounded(true); @@ -121,7 +134,8 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures( {} /* enabled */, - {features::kFreezePurgeMemoryAllPagesFrozen} /* disabled */); + {features::kFreezePurgeMemoryAllPagesFrozen, + features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); memory_purge_manager_.SetRendererBackgrounded(true); @@ -159,7 +173,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures( {features::kFreezePurgeMemoryAllPagesFrozen} /* enabled */, - {} /* disabled */); + {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); memory_purge_manager_.SetRendererBackgrounded(true); @@ -264,6 +278,120 @@ memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); } +TEST_F(MemoryPurgeManagerTest, PurgeRendererMemoryWhenBackgroundedEnabled) { + scoped_feature_list_.InitWithFeatures( + {features::kPurgeRendererMemoryWhenBackgrounded} /* enabled */, + {} /* disabled */); + + memory_purge_manager_.SetRendererBackgrounded(true); + FastForwardBy(base::TimeDelta::FromMinutes( + MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded)); + ExpectMemoryPressure(); +} + +TEST_F(MemoryPurgeManagerTest, PurgeRendererMemoryWhenBackgroundedDisabled) { + scoped_feature_list_.InitWithFeatures( + {} /* enabled */, + {features::kPurgeRendererMemoryWhenBackgrounded} /* disabled */); + + memory_purge_manager_.SetRendererBackgrounded(true); + FastForwardBy(base::TimeDelta::Max()); + ExpectNoMemoryPressure(); +} + +TEST_F(MemoryPurgeManagerTest, + PurgeRendererMemoryWhenBackgroundedEnabledForegroundedBeforePurge) { + scoped_feature_list_.InitWithFeatures( + {features::kPurgeRendererMemoryWhenBackgrounded} /* enabled */, + {} /* disabled */); + + memory_purge_manager_.SetRendererBackgrounded(true); + FastForwardBy(base::TimeDelta::FromSeconds(30)); + ExpectNoMemoryPressure(); + + memory_purge_manager_.SetRendererBackgrounded(false); + FastForwardBy(base::TimeDelta::Max()); + ExpectNoMemoryPressure(); +} + +TEST_F(MemoryPurgeManagerTest, PageFrozenAndResumedWhileBackgrounded) { + constexpr base::TimeDelta kFreezePurgeDelay = + base::TimeDelta::FromMinutes(10); + constexpr base::TimeDelta kBeforeBackgroundPurgeDelay = + base::TimeDelta::FromMinutes( + MemoryPurgeManager::kDefaultMinTimeToPurgeAfterBackgrounded) / + 2; + + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kFreezePurgeMemoryAllPagesFrozen, + {{"delay-in-minutes", + base::IntToString(kFreezePurgeDelay.InMinutes())}}}, + {features::kPurgeRendererMemoryWhenBackgrounded, {}}}, + {}); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + FastForwardBy(kBeforeBackgroundPurgeDelay); + ExpectNoMemoryPressure(); + memory_purge_manager_.OnPageResumed(); + FastForwardBy( + base::TimeDelta::FromMinutes( + MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded) - + kBeforeBackgroundPurgeDelay); + // Since the renderer is still backgrounded, the memory purge should happen + // even though there are no frozen pages. + ExpectMemoryPressure(); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kActive); +} + +TEST_F(MemoryPurgeManagerTest, + PageFrozenAndRendererBackgroundedShorterBackgroundedDelay) { + constexpr base::TimeDelta kFreezePurgeDelay = + base::TimeDelta::FromMinutes(10); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kFreezePurgeMemoryAllPagesFrozen, + {{"delay-in-minutes", + base::IntToString(kFreezePurgeDelay.InMinutes())}}}, + {features::kPurgeRendererMemoryWhenBackgrounded, {}}}, + {}); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(base::TimeDelta::FromMinutes( + MemoryPurgeManager::kDefaultMaxTimeToPurgeAfterBackgrounded)); + FastForwardBy(kFreezePurgeDelay); + ExpectNoMemoryPressure(); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); +} + +TEST_F(MemoryPurgeManagerTest, + PageFrozenAndRendererBackgroundedShorterFreezeDelay) { + constexpr base::TimeDelta kFreezePurgeDelay = base::TimeDelta::FromMinutes( + MemoryPurgeManager::kDefaultMinTimeToPurgeAfterBackgrounded); + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kFreezePurgeMemoryAllPagesFrozen, + {{"delay-in-minutes", + base::IntToString(kFreezePurgeDelay.InMinutes())}}}, + {features::kPurgeRendererMemoryWhenBackgrounded, {}}}, + {}); + + memory_purge_manager_.OnPageCreated(PageLifecycleState::kActive); + + memory_purge_manager_.SetRendererBackgrounded(true); + memory_purge_manager_.OnPageFrozen(); + ExpectMemoryPressure(kFreezePurgeDelay); + FastForwardBy(base::TimeDelta::Max()); + ExpectNoMemoryPressure(); + + memory_purge_manager_.OnPageDestroyed(PageLifecycleState::kFrozen); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc index 9642ce0..95ae58e 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -1602,7 +1602,7 @@ EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), testing::UnorderedElementsAre()); - frame_scheduler_->OnStartedUsingFeature( + auto feature_handle1 = frame_scheduler_->RegisterFeature( SchedulingPolicy::Feature::kWebSocket, {SchedulingPolicy::DisableBackForwardCache()}); @@ -1610,7 +1610,7 @@ page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebSocket)); - frame_scheduler_->OnStartedUsingFeature( + auto feature_handle2 = frame_scheduler_->RegisterFeature( SchedulingPolicy::Feature::kWebRTC, {SchedulingPolicy::DisableBackForwardCache()}); @@ -1619,18 +1619,74 @@ testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebSocket, SchedulingPolicy::Feature::kWebRTC)); - frame_scheduler_->OnStoppedUsingFeature( - SchedulingPolicy::Feature::kWebSocket, - {SchedulingPolicy::DisableBackForwardCache()}); + feature_handle1.reset(); EXPECT_THAT( page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebRTC)); - frame_scheduler_->OnStoppedUsingFeature( - SchedulingPolicy::Feature::kWebRTC, + feature_handle2.reset(); + + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre()); +} + +TEST_F(PageSchedulerImplTest, BackForwardCacheOptOut_FrameDeleted) { + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre()); + + auto feature_handle = frame_scheduler_->RegisterFeature( + SchedulingPolicy::Feature::kWebSocket, {SchedulingPolicy::DisableBackForwardCache()}); + EXPECT_THAT( + page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebSocket)); + + frame_scheduler_.reset(); + + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre()); +} + +TEST_F(PageSchedulerImplTest, BackForwardCacheOptOut_FrameNavigated) { + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre()); + + auto feature_handle = frame_scheduler_->RegisterFeature( + SchedulingPolicy::Feature::kWebSocket, + {SchedulingPolicy::DisableBackForwardCache()}); + + EXPECT_THAT( + page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebSocket)); + + frame_scheduler_->RegisterStickyFeature( + SchedulingPolicy::Feature::kStickyFeatureForTesting, + {SchedulingPolicy::DisableBackForwardCache()}); + + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre( + SchedulingPolicy::Feature::kWebSocket, + SchedulingPolicy::Feature::kStickyFeatureForTesting)); + + // Same document navigations don't affect anything. + frame_scheduler_->DidCommitProvisionalLoad( + false, FrameScheduler::NavigationType::kSameDocument); + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre( + SchedulingPolicy::Feature::kWebSocket, + SchedulingPolicy::Feature::kStickyFeatureForTesting)); + + // Regular navigations reset sticky features. + frame_scheduler_->DidCommitProvisionalLoad( + false, FrameScheduler::NavigationType::kOther); + EXPECT_THAT( + page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), + testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebSocket)); + + feature_handle.reset(); + EXPECT_THAT(page_scheduler_->GetActiveFeaturesOptingOutFromBackForwardCache(), testing::UnorderedElementsAre()); }
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h index f9eeaa4..ef19a2d 100644 --- a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
@@ -92,6 +92,13 @@ SchedulingPolicy::Feature feature, SchedulingPolicy policy) WARN_UNUSED_RESULT; + // Register a feature which is used for the rest of the lifetime of + // the document and can't be unregistered. + // The policy is reset when the main frame navigates away from the current + // document. + void RegisterStickyFeature(SchedulingPolicy::Feature feature, + SchedulingPolicy policy); + // Adds an Observer instance to be notified on scheduling policy changed. // When an Observer is added, the initial state will be notified synchronously // through the Observer interface.
diff --git a/third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h b/third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h index 64d8d6d..d7f77ed5d 100644 --- a/third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h +++ b/third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h
@@ -19,9 +19,17 @@ kWebSocket = 0, kWebRTC = 1, - kCount = 2 + // TODO(altimin): This is a temporary placeholder for testing the + // sticky behaviour. Delete when we add real ones. + kStickyFeatureForTesting = 2, + + kCount = 3 }; + // Sticky features can't be unregistered and remain active for the rest + // of the lifetime of the document. + static bool IsFeatureSticky(Feature feature); + // List of opt-outs which form a policy. struct DisableAggressiveThrottling {}; struct DisableBackForwardCache {};
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h index 075c0647..4681105 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -16,6 +16,10 @@ #include "third_party/blink/renderer/platform/scheduler/public/pending_user_input_type.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" +namespace v8 { +class Isolate; +} + namespace blink { namespace scheduler { class NonMainThreadSchedulerImpl; @@ -117,6 +121,9 @@ return scheduler::PendingUserInputInfo(); } + // Associates |isolate| to the scheduler. + virtual void SetV8Isolate(v8::Isolate* isolate) = 0; + // Test helpers. // Return a reference to an underlying main thread WebThreadScheduler object.
diff --git a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc index 2f91a86e..d50ed9a8 100644 --- a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc +++ b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
@@ -187,6 +187,7 @@ NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override { return nullptr; } + void SetV8Isolate(v8::Isolate* isolate) override {} }; class SimpleMainThreadScheduler : public WebThreadScheduler,
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 7030038..03894041 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -365,6 +365,16 @@ 'allowed': ['gin::.+'], }, { + 'paths': ['third_party/blink/renderer/bindings/core/v8/script_streamer.cc'], + 'allowed': [ + # For the script streaming to be able to block when reading from a + # mojo datapipe. + 'base::ScopedAllowBaseSyncPrimitives', + 'base::ScopedBlockingCall', + 'base::BlockingType', + ], + }, + { 'paths': ['third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc'], 'allowed': [ # For memory reduction histogram.
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index a98e429..999b8067 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -378,6 +378,11 @@ Bug(none) paint/float/float-under-inline-self-painting-change.html [ Failure ] Bug(none) compositing/overflow/overlap-testing-ancestor-scroller-high-dpi.html [ Failure ] +# Extra raster invalidation on start/end of animation. Caused by animation +# element id namespaces +crbug.com/900241 paint/invalidation/animation/opacity-animation.html [ Failure ] +crbug.com/900241 paint/invalidation/animation/transform-animation.html [ Failure ] + # These tests have additional hit test rects. These may correct and simply due # to different layerization decisions, but this needs investigation. crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-global.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index 3305c3f5e..e797ce4 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -465,7 +465,6 @@ crbug.com/591099 fast/multicol/border-radius-clipped-layer.html [ Pass ] crbug.com/591099 fast/peerconnection/RTCPeerConnection-many.html [ Pass ] crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure ] -crbug.com/591099 fast/spatial-navigation/snav-keyboard-scrollers-search-origin-bug.html [ Crash ] crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Pass ] crbug.com/591099 fast/text/emoji-vertical-origin-visual.html [ Failure ] crbug.com/591099 fast/text/font-format-support-color-cff2-vertical.html [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 67ac126..1ffedcd 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1982,21 +1982,21 @@ external/wpt/offscreen-canvas/text/2d.text.draw.fill.rtl-manual.worker.js [ WontFix ] external/wpt/offscreen-canvas/text/2d.text.draw.kern.consistent-manual.worker.js [ WontFix ] external/wpt/offscreen-canvas/text/2d.text.draw.stroke.basic-manual.worker.js [ WontFix ] -external/wpt/orientation-event/free-fall-manual.html [ WontFix ] -external/wpt/orientation-event/screen-upmost-manual.html [ WontFix ] -external/wpt/orientation-event/screen-upright-manual.html [ WontFix ] -external/wpt/orientation-event/t001-manual.html [ WontFix ] -external/wpt/orientation-event/t002-manual.html [ WontFix ] -external/wpt/orientation-event/t003-manual.html [ WontFix ] -external/wpt/orientation-event/t006-manual.html [ WontFix ] -external/wpt/orientation-event/t009-manual.html [ WontFix ] -external/wpt/orientation-event/t010-manual.html [ WontFix ] -external/wpt/orientation-event/t012-manual.html [ WontFix ] -external/wpt/orientation-event/t021-manual.html [ WontFix ] -external/wpt/orientation-event/t022-manual.html [ WontFix ] -external/wpt/orientation-event/t023-manual.html [ WontFix ] -external/wpt/orientation-event/t025-manual.html [ WontFix ] -external/wpt/orientation-event/t028-manual.html [ WontFix ] +external/wpt/orientation-event/free-fall-manual.https.html [ WontFix ] +external/wpt/orientation-event/screen-upmost-manual.https.html [ WontFix ] +external/wpt/orientation-event/screen-upright-manual.https.html [ WontFix ] +external/wpt/orientation-event/t001-manual.https.html [ WontFix ] +external/wpt/orientation-event/t002-manual.https.html [ WontFix ] +external/wpt/orientation-event/t003-manual.https.html [ WontFix ] +external/wpt/orientation-event/t006-manual.https.html [ WontFix ] +external/wpt/orientation-event/t009-manual.https.html [ WontFix ] +external/wpt/orientation-event/t010-manual.https.html [ WontFix ] +external/wpt/orientation-event/t012-manual.https.html [ WontFix ] +external/wpt/orientation-event/t021-manual.https.html [ WontFix ] +external/wpt/orientation-event/t022-manual.https.html [ WontFix ] +external/wpt/orientation-event/t023-manual.https.html [ WontFix ] +external/wpt/orientation-event/t025-manual.https.html [ WontFix ] +external/wpt/orientation-event/t028-manual.https.html [ WontFix ] external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https.html [ WontFix ] external/wpt/page-visibility/test_minimize-manual.html [ WontFix ] external/wpt/page-visibility/test_tab_state_change-manual.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 239399aa..8abd6f0 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -335,6 +335,12 @@ crbug.com/857490 virtual/user-activation-v2/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Skip ] crbug.com/857490 virtual/user-activation-v2/fast/events/wheel/wheel-fling-cancel.html [ Skip ] +# Currently on main thread scrolling path, scrollend gets fired without waiting for scroll/fling snap animation. (The virtual/threaded version of the test passes.) +crbug.com/907601 fast/scrolling/events/scrollend-event-fired-after-snap.html [ Skip ] +crbug.com/907601 virtual/fractional_scrolling/fast/scrolling/events/scrollend-event-fired-after-snap.html [ Skip ] +crbug.com/907601 virtual/fractional_scrolling_threaded/fast/scrolling/events/scrollend-event-fired-after-snap.html [ Skip ] +crbug.com/907601 virtual/scroll_customization/fast/scrolling/events/scrollend-event-fired-after-snap.html [ Skip ] + # Tests not yet passing with Blink FractionalScrollOffsets enabled. crbug.com/414283 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ] crbug.com/414283 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure Pass ] @@ -394,9 +400,6 @@ crbug.com/921105 virtual/disable-blink-gen-property-trees/animations/skew-notsequential-compositor.html [ Skip ] # Occasionally timeout, but the test coverage is still good crbug.com/919789 paint/invalidation/window-resize/ [ Timeout Pass ] -# Extra raster invalidation on start/end of animation. -crbug.com/942681 paint/invalidation/animation/opacity-animation.html [ Failure ] -crbug.com/942681 paint/invalidation/animation/transform-animation.html [ Failure ] # ====== Paint team owned tests to here ====== @@ -5930,9 +5933,6 @@ # Sheriff 2019-01-18 crbug.com/922970 external/wpt/css/css-transitions/CSSTransition-startTime.tentative.html [ Failure Pass ] -crbug.com/v8/8319 external/wpt/wasm/jsapi/memory/grow.any.html [ Pass Failure ] -crbug.com/v8/8319 external/wpt/wasm/jsapi/memory/grow.any.worker.html [ Pass Failure ] - crbug.com/910979 http/tests/html/validation-bubble-oopif-clip.html [ Failure Pass ] # Sheriff 2019-01-22
diff --git a/third_party/blink/web_tests/accessibility/image-inside-link.html b/third_party/blink/web_tests/accessibility/image-inside-link.html index 5d2e34a0..b778902 100644 --- a/third_party/blink/web_tests/accessibility/image-inside-link.html +++ b/third_party/blink/web_tests/accessibility/image-inside-link.html
@@ -12,10 +12,8 @@ { var axImg = accessibilityController.accessibleElementById("img1"); axImg.addNotificationListener(function(notification) { - if (notification == 'Clicked') { - document.getElementById("wrapper1").style.display = "none"; + if (notification == 'Clicked') t.done(); - } }); var img = document.getElementById("img1"); @@ -47,10 +45,8 @@ domEvent = true; } - if (axEvent && domEvent) { - document.getElementById("wrapper2").style.display = "none"; + if (axEvent && domEvent) t.done(); - } }; var axImg = accessibilityController.accessibleElementById("img2"); @@ -60,4 +56,3 @@ axImg.press(); }, "clicking an image via accessibility sends both an accessible and a DOM click event"); </script> -
diff --git a/third_party/blink/web_tests/accessibility/multiselect-list-reports-active-option.html b/third_party/blink/web_tests/accessibility/multiselect-list-reports-active-option.html index 61e516d0..df0967f 100644 --- a/third_party/blink/web_tests/accessibility/multiselect-list-reports-active-option.html +++ b/third_party/blink/web_tests/accessibility/multiselect-list-reports-active-option.html
@@ -7,6 +7,7 @@ async_test_after_layout_and_paint((testCase) => { const expectedNotifications = [ 'ActiveDescendantChanged', + 'Focus', 'SelectedChildrenChanged', 'SelectedChildrenChanged', 'ActiveDescendantChanged',
diff --git a/third_party/blink/web_tests/accessibility/notification-listeners.html b/third_party/blink/web_tests/accessibility/notification-listeners.html index c0c9b08d..390f61a3 100644 --- a/third_party/blink/web_tests/accessibility/notification-listeners.html +++ b/third_party/blink/web_tests/accessibility/notification-listeners.html
@@ -15,7 +15,16 @@ window.select = accessibilityController.accessibleElementById("select"); window.slider = accessibilityController.accessibleElementById("slider"); let expected_notifications = [ + [select, "Focus"], + ["global", "Focus", "AXRole: AXPopUpButton"], [select, "Blur"], + ["global", "Blur", "AXRole: AXPopUpButton"], + [slider, "Focus"], + ["global", "Focus", "AXRole: AXSlider"], + [select, "TextChanged"], + ["global", "TextChanged", "AXRole: AXPopUpButton"], + [select, "TextChanged"], + ["global", "TextChanged", "AXRole: AXPopUpButton"], [select, "InvalidStatusChanged"], ["global", "InvalidStatusChanged", "AXRole: AXPopUpButton"], [slider, "ValueChanged"], @@ -51,9 +60,9 @@ assert_equals(element.role, expected_notification[2]); } if (expected_notifications.length === 0) { - assert_equals(selectNotificationCount, 2); - assert_equals(sliderNotificationCount, 1); - assert_equals(globalNotificationCount, 2); + assert_equals(selectNotificationCount, 5); + assert_equals(sliderNotificationCount, 2); + assert_equals(globalNotificationCount, 7); accessibilityController.removeNotificationListener(); select.removeNotificationListener(); slider.removeNotificationListener();
diff --git a/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification-expected.txt b/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification-expected.txt deleted file mode 100644 index 3e9953a..0000000 --- a/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -One Two Three - -This test ensures that scrolling the window sends a notification. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -Got notification on container div -PASS container.scrollLeft is 500 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification.html b/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification.html index a8added..144b5b2f 100644 --- a/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification.html +++ b/third_party/blink/web_tests/accessibility/scroll-div-horiz-sends-notification.html
@@ -1,7 +1,9 @@ <!DOCTYPE HTML> <html> <head> -<script src="../resources/js-test.js"></script> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="../resources/run-after-layout-and-paint.js"></script> <style> .container { padding: 100px; @@ -30,30 +32,24 @@ </div> </div> -<div id="console"></div> <script> -description("This test ensures that scrolling the window sends a notification."); -window.jsTestIsAsync = true; - -if (window.testRunner && window.accessibilityController) { - testRunner.dumpAsText(); - +async_test_after_layout_and_paint((t) => { var container = document.getElementById('container'); accessibilityController.addNotificationListener(function (target, notification) { if (target.role == 'AXRole: AXGenericContainer') { - debug('Got notification on container div'); - shouldBe("container.scrollLeft", "500"); - accessibilityController.removeNotificationListener(); - finishJSTest(); + console.log('Got notification on container div'); + assert_equals(container.scrollLeft, 500); + t.done(); } }); window.setTimeout(function() { container.scrollLeft = 500; }, 0); -} +}, "This test ensures that scrolling the window sends a notification."); + </script>
diff --git a/third_party/blink/web_tests/accessibility/scroll-div-sends-notification-expected.txt b/third_party/blink/web_tests/accessibility/scroll-div-sends-notification-expected.txt deleted file mode 100644 index e7a0c6e..0000000 --- a/third_party/blink/web_tests/accessibility/scroll-div-sends-notification-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -One -Two -Three - -This test ensures that scrolling the window sends a notification. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -Got notification on container div -PASS container.scrollTop is 500 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/accessibility/scroll-div-sends-notification.html b/third_party/blink/web_tests/accessibility/scroll-div-sends-notification.html index 37dee5a..30ed8c2 100644 --- a/third_party/blink/web_tests/accessibility/scroll-div-sends-notification.html +++ b/third_party/blink/web_tests/accessibility/scroll-div-sends-notification.html
@@ -1,7 +1,9 @@ <!DOCTYPE HTML> <html> <head> -<script src="../resources/js-test.js"></script> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="../resources/run-after-layout-and-paint.js"></script> <style> .container { padding: 100px; @@ -25,30 +27,24 @@ <button class="bigbutton">Three</button> </div> -<div id="console"></div> <script> -description("This test ensures that scrolling the window sends a notification."); -window.jsTestIsAsync = true; - -if (window.testRunner && window.accessibilityController) { - testRunner.dumpAsText(); - +async_test_after_layout_and_paint((t) => { var container = document.getElementById('container'); accessibilityController.addNotificationListener(function (target, notification) { if (target.role == 'AXRole: AXGenericContainer') { - debug('Got notification on container div'); - shouldBe("container.scrollTop", "500"); - accessibilityController.removeNotificationListener(); - finishJSTest(); + console.log('Got notification on container div'); + assert_equals(container.scrollTop, 500); + t.done(); } }); window.setTimeout(function() { container.scrollTop = 500; }, 0); -} +}, "This test ensures that scrolling the window sends a notification."); + </script>
diff --git a/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification-expected.txt b/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification-expected.txt deleted file mode 100644 index 0b84dc1e..0000000 --- a/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -One -Two -Three - -This test ensures that scrolling the window sends a notification. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS window.pageXOffset is 0 -Got notification on web area -PASS window.pageXOffset is 500 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification.html b/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification.html index 4b1e5c7a..6fd610d9 100644 --- a/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification.html +++ b/third_party/blink/web_tests/accessibility/scroll-window-horiz-sends-notification.html
@@ -1,7 +1,9 @@ <!DOCTYPE HTML> <html> <head> -<script src="../resources/js-test.js"></script> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="../resources/run-after-layout-and-paint.js"></script> <style> .bigbutton { display:block; @@ -16,31 +18,25 @@ <button class="bigbutton">Two</button> <button class="bigbutton">Three</button> -<div id="console"></div> <script> -description("This test ensures that scrolling the window sends a notification."); -window.jsTestIsAsync = true; - -if (window.testRunner && window.accessibilityController) { - testRunner.dumpAsText(); +async_test_after_layout_and_paint((t) => { window.scrollTo(0, 0); - shouldBe("window.pageXOffset", "0"); + assert_equals(window.pageXOffset, 0); accessibilityController.addNotificationListener(function (target, notification) { if (target.role == 'AXRole: AXWebArea' && notification == 'ScrollPositionChanged') { - debug('Got notification on web area'); - accessibilityController.removeNotificationListener(); - shouldBe("window.pageXOffset", "500"); - finishJSTest(); + console.log('Got notification on web area'); + assert_equals(window.pageXOffset, 500); + t.done()(); } }); window.setTimeout(function() { window.scrollTo(500, 0); }, 0); -} +}, "This test ensures that scrolling the window sends a notification."); </script>
diff --git a/third_party/blink/web_tests/accessibility/scroll-window-sends-notification-expected.txt b/third_party/blink/web_tests/accessibility/scroll-window-sends-notification-expected.txt deleted file mode 100644 index 2ab16ef..0000000 --- a/third_party/blink/web_tests/accessibility/scroll-window-sends-notification-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -One -Two -Three - -This test ensures that scrolling the window sends a notification. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS window.pageYOffset is 0 -Got notification on web area -PASS window.pageYOffset is 500 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/accessibility/scroll-window-sends-notification.html b/third_party/blink/web_tests/accessibility/scroll-window-sends-notification.html index 7ff4cf6..4a21da6 100644 --- a/third_party/blink/web_tests/accessibility/scroll-window-sends-notification.html +++ b/third_party/blink/web_tests/accessibility/scroll-window-sends-notification.html
@@ -1,7 +1,9 @@ <!DOCTYPE HTML> <html> <head> -<script src="../resources/js-test.js"></script> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="../resources/run-after-layout-and-paint.js"></script> <style> .bigbutton { display:block; @@ -19,28 +21,23 @@ <div id="console"></div> <script> -description("This test ensures that scrolling the window sends a notification."); -window.jsTestIsAsync = true; - -if (window.testRunner && window.accessibilityController) { - testRunner.dumpAsText(); - +async_test_after_layout_and_paint((t) => { window.scrollTo(0, 0); - shouldBe("window.pageYOffset", "0"); + assert_equals(window.pageYOffset, 0); accessibilityController.addNotificationListener(function (target, notification) { if (target.role == 'AXRole: AXWebArea' && notification == 'ScrollPositionChanged') { - debug('Got notification on web area'); - accessibilityController.removeNotificationListener(); - shouldBe("window.pageYOffset", "500"); - finishJSTest(); + console.log('Got notification on web area'); + assert_equals(window.pageYOffset, 500); + t.done() } }); window.setTimeout(function() { window.scrollTo(0, 500); }, 0); -} +}, "This test ensures that scrolling the window sends a notification."); + </script>
diff --git a/third_party/blink/web_tests/accessibility/selection-change-notification-aria-textbox.html b/third_party/blink/web_tests/accessibility/selection-change-notification-aria-textbox.html index d72fd8e1..89f26ded 100644 --- a/third_party/blink/web_tests/accessibility/selection-change-notification-aria-textbox.html +++ b/third_party/blink/web_tests/accessibility/selection-change-notification-aria-textbox.html
@@ -21,10 +21,14 @@ accessibilityController.accessibleElementById('dummy'); var element = document.getElementById('ariaTextbox'); - var axElement = accessibilityController.accessibleElementById('ariaTextbox'); element.focus(); + var axElement = accessibilityController.accessibleElementById('ariaTextbox'); axElement.addNotificationListener(t.step_func((notification) => { + // Focus notification will come asynchronously after layout + if (notification == 'Focus') + return; + if (notification == 'SelectedTextChanged') { axElement.removeNotificationListener(); t.done();
diff --git a/third_party/blink/web_tests/accessibility/selection-change-notification-contenteditable.html b/third_party/blink/web_tests/accessibility/selection-change-notification-contenteditable.html index 7701d4d..831ad710 100644 --- a/third_party/blink/web_tests/accessibility/selection-change-notification-contenteditable.html +++ b/third_party/blink/web_tests/accessibility/selection-change-notification-contenteditable.html
@@ -16,10 +16,14 @@ <script> async_test_after_layout_and_paint((t) => { var element = document.getElementById('contentEditable'); - var axElement = accessibilityController.accessibleElementById('contentEditable'); element.focus(); + var axElement = accessibilityController.accessibleElementById('contentEditable'); axElement.addNotificationListener(t.step_func((notification) => { + // Focus notification will come asynchronously after layout + if (notification == 'Focus') + return; + if (notification == 'SelectedTextChanged') { axElement.removeNotificationListener(); t.done();
diff --git a/third_party/blink/web_tests/battery-status/no-leak-on-detached-use.html b/third_party/blink/web_tests/battery-status/no-leak-on-detached-use.html index 62e4e47..fb9b1af 100644 --- a/third_party/blink/web_tests/battery-status/no-leak-on-detached-use.html +++ b/third_party/blink/web_tests/battery-status/no-leak-on-detached-use.html
@@ -20,6 +20,6 @@ } </script> <!-- iframe with some contents --> -<iframe src="data:text/html,<html></html>" id="subframe"></iframe> +<iframe srcdoc="<html></html>" id="subframe"></iframe> </body> </html>
diff --git a/third_party/blink/web_tests/compositing/iframes/iframe-in-composited-layer.html b/third_party/blink/web_tests/compositing/iframes/iframe-in-composited-layer.html index e711777..917603c 100644 --- a/third_party/blink/web_tests/compositing/iframes/iframe-in-composited-layer.html +++ b/third_party/blink/web_tests/compositing/iframes/iframe-in-composited-layer.html
@@ -15,7 +15,7 @@ </script> <div style="transform: translateZ(0); width: 400px; height: 400px; background-color: lightyellow;"> - <iframe id="frame" onload="runTest()" style="width: 380px; height: 380px; border: solid; margin: 7px" src="data:text/html, + <iframe id="frame" onload="runTest()" style="width: 380px; height: 380px; border: solid; margin: 7px" srcdoc=" <html style='height: 900px; width: 900px; position: relative;'> <body> <div style='position: absolute; width: 100px; height: 100px; background-color: red; left: 0; top: 0;'></div>
diff --git a/third_party/blink/web_tests/editing/selection/cleared-by-relayout.html b/third_party/blink/web_tests/editing/selection/cleared-by-relayout.html index aa4f932..36ce319 100644 --- a/third_party/blink/web_tests/editing/selection/cleared-by-relayout.html +++ b/third_party/blink/web_tests/editing/selection/cleared-by-relayout.html
@@ -23,5 +23,5 @@ } </script> <p> - <iframe onload="prepare()" id="target" src="data:text/html,<body contenteditable>"></iframe> + <iframe onload="prepare()" id="target" srcdoc="<body contenteditable>"></iframe> </p>
diff --git a/third_party/blink/web_tests/editing/selection/drag-in-iframe.html b/third_party/blink/web_tests/editing/selection/drag-in-iframe.html index 88428df..392717f1 100644 --- a/third_party/blink/web_tests/editing/selection/drag-in-iframe.html +++ b/third_party/blink/web_tests/editing/selection/drag-in-iframe.html
@@ -5,7 +5,7 @@ below and verify that a drag caret appears inside the frame. </p> <iframe id="subframe" style="border: 1px solid black;" - src="data:text/html,<body contenteditable><span id='target'>There</span> should be a caret here --> <br>See it?</body>"></iframe> + srcdoc="<body contenteditable><span id='target'>There</span> should be a caret here --> <br>See it?</body>"></iframe> <script> function dragAndDrop() {
diff --git a/third_party/blink/web_tests/editing/selection/inactive-selection.html b/third_party/blink/web_tests/editing/selection/inactive-selection.html index c4caaf1..8ef6429 100644 --- a/third_party/blink/web_tests/editing/selection/inactive-selection.html +++ b/third_party/blink/web_tests/editing/selection/inactive-selection.html
@@ -3,7 +3,7 @@ <hr> <pre id="console"></pre> -<iframe src="data:text/html, <div id='input' contenteditable='true'>should be an inactive selection</div>"></iframe> +<iframe srcdoc="<div id='input' contenteditable='true'>should be an inactive selection</div>"></iframe> <br> <input id='input' type="text" value="random text"> <div>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index e2c35e4e..69bc6e8 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -5443,99 +5443,99 @@ {} ] ], - "orientation-event/free-fall-manual.html": [ + "orientation-event/free-fall-manual.https.html": [ [ - "/orientation-event/free-fall-manual.html", + "/orientation-event/free-fall-manual.https.html", {} ] ], - "orientation-event/horizontal-surface-manual.html": [ + "orientation-event/horizontal-surface-manual.https.html": [ [ - "/orientation-event/horizontal-surface-manual.html", + "/orientation-event/horizontal-surface-manual.https.html", {} ] ], - "orientation-event/screen-upmost-manual.html": [ + "orientation-event/screen-upmost-manual.https.html": [ [ - "/orientation-event/screen-upmost-manual.html", + "/orientation-event/screen-upmost-manual.https.html", {} ] ], - "orientation-event/screen-upright-manual.html": [ + "orientation-event/screen-upright-manual.https.html": [ [ - "/orientation-event/screen-upright-manual.html", + "/orientation-event/screen-upright-manual.https.html", {} ] ], - "orientation-event/t001-manual.html": [ + "orientation-event/t001-manual.https.html": [ [ - "/orientation-event/t001-manual.html", + "/orientation-event/t001-manual.https.html", {} ] ], - "orientation-event/t002-manual.html": [ + "orientation-event/t002-manual.https.html": [ [ - "/orientation-event/t002-manual.html", + "/orientation-event/t002-manual.https.html", {} ] ], - "orientation-event/t003-manual.html": [ + "orientation-event/t003-manual.https.html": [ [ - "/orientation-event/t003-manual.html", + "/orientation-event/t003-manual.https.html", {} ] ], - "orientation-event/t006-manual.html": [ + "orientation-event/t006-manual.https.html": [ [ - "/orientation-event/t006-manual.html", + "/orientation-event/t006-manual.https.html", {} ] ], - "orientation-event/t009-manual.html": [ + "orientation-event/t009-manual.https.html": [ [ - "/orientation-event/t009-manual.html", + "/orientation-event/t009-manual.https.html", {} ] ], - "orientation-event/t010-manual.html": [ + "orientation-event/t010-manual.https.html": [ [ - "/orientation-event/t010-manual.html", + "/orientation-event/t010-manual.https.html", {} ] ], - "orientation-event/t012-manual.html": [ + "orientation-event/t012-manual.https.html": [ [ - "/orientation-event/t012-manual.html", + "/orientation-event/t012-manual.https.html", {} ] ], - "orientation-event/t021-manual.html": [ + "orientation-event/t021-manual.https.html": [ [ - "/orientation-event/t021-manual.html", + "/orientation-event/t021-manual.https.html", {} ] ], - "orientation-event/t022-manual.html": [ + "orientation-event/t022-manual.https.html": [ [ - "/orientation-event/t022-manual.html", + "/orientation-event/t022-manual.https.html", {} ] ], - "orientation-event/t023-manual.html": [ + "orientation-event/t023-manual.https.html": [ [ - "/orientation-event/t023-manual.html", + "/orientation-event/t023-manual.https.html", {} ] ], - "orientation-event/t025-manual.html": [ + "orientation-event/t025-manual.https.html": [ [ - "/orientation-event/t025-manual.html", + "/orientation-event/t025-manual.https.html", {} ] ], - "orientation-event/t028-manual.html": [ + "orientation-event/t028-manual.https.html": [ [ - "/orientation-event/t028-manual.html", + "/orientation-event/t028-manual.https.html", {} ] ], @@ -5857,12 +5857,6 @@ {} ] ], - "pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html": [ - [ - "/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_disabled_form_control-manual.html": [ [ "/pointerevents/pointerevent_disabled_form_control-manual.html", @@ -5881,36 +5875,18 @@ {} ] ], - "pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html": [ - [ - "/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_pointerleave_pen-manual.html": [ [ "/pointerevents/pointerevent_pointerleave_pen-manual.html", {} ] ], - "pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html": [ - [ - "/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html": [ [ "/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html", {} ] ], - "pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html": [ - [ - "/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual.html": [ [ "/pointerevents/pointerevent_sequence_at_implicit_release_on_click-manual.html", @@ -5923,12 +5899,6 @@ {} ] ], - "pointerevents/pointerevent_touch-action-auto-css_touch-manual.html": [ - [ - "/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_touch-action-button-test_touch-manual.html": [ [ "/pointerevents/pointerevent_touch-action-button-test_touch-manual.html", @@ -5959,12 +5929,6 @@ {} ] ], - "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html": [ - [ - "/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html": [ [ "/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html", @@ -6001,12 +5965,6 @@ {} ] ], - "pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html": [ - [ - "/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html", - {} - ] - ], "pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html": [ [ "/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html", @@ -57225,6 +57183,18 @@ {} ] ], + "css/css-position/position-sticky-scroll-with-clip-and-abspos.html": [ + [ + "/css/css-position/position-sticky-scroll-with-clip-and-abspos.html", + [ + [ + "/css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-position/position-sticky-stacking-context.html": [ [ "/css/css-position/position-sticky-stacking-context.html", @@ -109141,6 +109111,18 @@ {} ] ], + "mathml/presentation-markup/operators/mo-paint-lspace-rspace.html": [ + [ + "/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html", + [ + [ + "/mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html", + "==" + ] + ], + {} + ] + ], "mathml/presentation-markup/spaces/space-2.html": [ [ "/mathml/presentation-markup/spaces/space-2.html", @@ -143004,6 +142986,11 @@ {} ] ], + "css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html": [ + [ + {} + ] + ], "css/css-position/position-sticky-stacking-context-ref.html": [ [ {} @@ -177859,6 +177846,11 @@ {} ] ], + "mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html": [ + [ + {} + ] + ], "mathml/presentation-markup/spaces/space-2-ref.html": [ [ {} @@ -180359,6 +180351,11 @@ {} ] ], + "orientation-event/horizontal-surface-manual.https-expected.txt": [ + [ + {} + ] + ], "orientation-event/idlharness-expected.txt": [ [ {} @@ -188514,6 +188511,41 @@ {} ] ], + "signed-exchange/appcache/appcache.manifest": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/appcached-url-in-sxg.html": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/appcached-url.html": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/inner-url.html": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/sxg/__dir__.headers": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/sxg/sxg-appcached.sxg": [ + [ + {} + ] + ], + "signed-exchange/appcache/resources/sxg/sxg-location.sxg": [ + [ + {} + ] + ], "signed-exchange/resources/127.0.0.1.sxg.ext": [ [ {} @@ -197224,16 +197256,6 @@ {} ] ], - "wasm/jsapi/memory/grow.any-expected.txt": [ - [ - {} - ] - ], - "wasm/jsapi/memory/grow.any.worker-expected.txt": [ - [ - {} - ] - ], "wasm/jsapi/table/assertions.js": [ [ {} @@ -260633,6 +260655,48 @@ {} ] ], + "import-maps/csp/applied-to-target-dynamic.sub.tentative.html": [ + [ + "/import-maps/csp/applied-to-target-dynamic.sub.tentative.html", + {} + ] + ], + "import-maps/csp/applied-to-target.sub.tentative.html": [ + [ + "/import-maps/csp/applied-to-target.sub.tentative.html", + {} + ] + ], + "import-maps/csp/hash-failure.tentative.html": [ + [ + "/import-maps/csp/hash-failure.tentative.html", + {} + ] + ], + "import-maps/csp/hash.tentative.html": [ + [ + "/import-maps/csp/hash.tentative.html", + {} + ] + ], + "import-maps/csp/nonce-failure.tentative.html": [ + [ + "/import-maps/csp/nonce-failure.tentative.html", + {} + ] + ], + "import-maps/csp/nonce.tentative.html": [ + [ + "/import-maps/csp/nonce.tentative.html", + {} + ] + ], + "import-maps/csp/unsafe-inline.tentative.html": [ + [ + "/import-maps/csp/unsafe-inline.tentative.html", + {} + ] + ], "import-maps/data.sub.tentative.html": [ [ "/import-maps/data.sub.tentative.html", @@ -276079,6 +276143,14 @@ } ] ], + "pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html": [ + [ + "/pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_click_during_capture.html": [ [ "/pointerevents/pointerevent_click_during_capture.html", @@ -276155,6 +276227,14 @@ } ] ], + "pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html": [ + [ + "/pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_pointerleave_descendant_over.html": [ [ "/pointerevents/pointerevent_pointerleave_descendant_over.html", @@ -276203,6 +276283,14 @@ } ] ], + "pointerevents/pointerevent_pointerout_after_pointercancel_touch.html": [ + [ + "/pointerevents/pointerevent_pointerout_after_pointercancel_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_pointerout_pen.html": [ [ "/pointerevents/pointerevent_pointerout_pen.html", @@ -276227,6 +276315,14 @@ } ] ], + "pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html": [ + [ + "/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_releasepointercapture_onpointerup_mouse.html": [ [ "/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse.html", @@ -276295,18 +276391,50 @@ } ] ], + "pointerevents/pointerevent_touch-action-auto-css_touch.html": [ + [ + "/pointerevents/pointerevent_touch-action-auto-css_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_touch-action-illegal.html": [ [ "/pointerevents/pointerevent_touch-action-illegal.html", {} ] ], + "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html": [ + [ + "/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html", + { + "testdriver": true + } + ] + ], + "pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html": [ + [ + "/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html", + { + "testdriver": true + } + ] + ], "pointerevents/pointerevent_touch-action-verification.html": [ [ "/pointerevents/pointerevent_touch-action-verification.html", {} ] ], + "pointerevents/pointerlock/pointerevent_coordinates_when_locked.html": [ + [ + "/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html", + { + "testdriver": true + } + ] + ], "pointerlock/constructor.html": [ [ "/pointerlock/constructor.html", @@ -289824,6 +289952,18 @@ {} ] ], + "signed-exchange/appcache/sxg-inner-resp-over-appcache.tentative.https.html": [ + [ + "/signed-exchange/appcache/sxg-inner-resp-over-appcache.tentative.https.html", + {} + ] + ], + "signed-exchange/appcache/sxg-served-from-appcache.tentative.https.html": [ + [ + "/signed-exchange/appcache/sxg-served-from-appcache.tentative.https.html", + {} + ] + ], "signed-exchange/check-cert-request.tentative.html": [ [ "/signed-exchange/check-cert-request.tentative.html", @@ -367749,6 +367889,14 @@ "596fd9b24054bc0c3f0579146834d6fef674d6cf", "testharness" ], + "css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html": [ + "a36934e38079cfc8fd6e9d36524968675235983e", + "support" + ], + "css/css-position/position-sticky-scroll-with-clip-and-abspos.html": [ + "46085b49b4c405bdc1d0a05eafda3faca8ecf74a", + "reftest" + ], "css/css-position/position-sticky-stacking-context-ref.html": [ "0fe20bd3c339a1a92a3481653d6ea6d85ec054df", "support" @@ -395770,7 +395918,7 @@ "testharness" ], "css/cssom/CSSStyleSheet-constructable.html": [ - "5ee86ae4a6775abb47abff558b292b2303e2ef27", + "c7ae5f27b8bfb4220d7e9b2c956d2360f335c12a", "testharness" ], "css/cssom/CSSStyleSheet.html": [ @@ -411114,11 +411262,11 @@ "support" ], "feature-policy/resources/feature-policy-idle-detection-worker.js": [ - "c6b8a7c88729c4106db162a9850b92e74b92d6ed", + "2e4e3cdc727613bbecf51465a0f3802781cf847b", "support" ], "feature-policy/resources/feature-policy-idle-detection.html": [ - "e542e3b8912228e87bf6265bbab803dfe2756b1e", + "65a578181b9ac433961416759195402343c57c6a", "support" ], "feature-policy/resources/feature-policy-nested-subframe-policy.https.sub.html": [ @@ -424218,7 +424366,7 @@ "support" ], "html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html": [ - "ac0f56f7d5482b67f8893d6e1e5bf51901cacaa8", + "7a57826f3090a75d1a8878b1ed518526bc9c2e88", "testharness" ], "html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html": [ @@ -425150,7 +425298,7 @@ "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html": [ - "970666793a73614563daa66fe515037513c51ec2", + "707240415dd5c95622481719cac2299cd1171ad4", "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html": [ @@ -433646,19 +433794,19 @@ "support" ], "idle-detection/basics.tentative.https.any.js": [ - "ef5de2164ed8d58fd27bcbd92eb891892ad28e25", + "df547570a78c31686d56065edfb7af243afde635", "testharness" ], "idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ - "f8f57348dfa10cf671f82902f4ec7d4ca5fcd7c6", + "6129ba12fa45090a8da80b27cecd3bd28232547c", "testharness" ], "idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html": [ - "422c45c3de6a74134be261142d455a2003a30999", + "b19cd241bf4673dfc7cb9995c0071f2f6cc969b2", "testharness" ], "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html": [ - "3c019b7e0e476b82e812a3821119c0365eee2fd2", + "cafe96f5c898b6d21f0d1398361d9ef2f17f02fb", "testharness" ], "idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html.headers": [ @@ -433666,11 +433814,11 @@ "support" ], "idle-detection/idle-detection-default-feature-policy.https.sub.html": [ - "7ecf7a4f67700fa86fea55d744656875f1960820", + "59eeae00bc4fcd33c4b41dcaf1bf9161508437fc", "testharness" ], "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html": [ - "cb455f40bab08010511f17eea4b764872bfbf9b1", + "2814a2263db71658ac9104974147b543929c25e4", "testharness" ], "idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html.headers": [ @@ -433678,15 +433826,15 @@ "support" ], "idle-detection/idle-detection.idl": [ - "4b502c975ce3b25a94518ce5d98c842b57c6a70d", + "1fd4d451be98c7fb12bb1734d8bfcb57ad60bfbd", "support" ], "idle-detection/idlharness.https.any.js": [ - "4bda5c1a85b71e8fcb1c050710279bfec2919b68", + "482e2f4d40088a33809e8629051194605b0627cd", "testharness" ], "idle-detection/interceptor.https.html": [ - "03595afccdcd224f918f6e8baaf21c2419c24062", + "465607d33481a00ae3c0309d41d19e7c1e05a827", "testharness" ], "idle-detection/mock.js": [ @@ -433694,11 +433842,11 @@ "support" ], "idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js": [ - "103ce5e9bdb0fae14cd88b4f760c93afce47ae2b", + "e643414f750897516db0576cd02262c3d571d4c1", "support" ], "idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js": [ - "66218a5c4420b5644ddefa276fb52f2718907525", + "138b29173f73eaed62dc57f4c912d15c174f9a5f", "support" ], "imagebitmap-renderingcontext/META.yml": [ @@ -434045,6 +434193,34 @@ "e85289e4d884d49bb4520154cecdd2826a07b333", "testharness" ], + "import-maps/csp/applied-to-target-dynamic.sub.tentative.html": [ + "cef80bfcda72956fe7acc59788d984370f25a62f", + "testharness" + ], + "import-maps/csp/applied-to-target.sub.tentative.html": [ + "e6bbfecd0d9a62b5d4262c3cdbc7f97c301aa686", + "testharness" + ], + "import-maps/csp/hash-failure.tentative.html": [ + "4bab1ed91731a362d02602a4e5a58e6272a3fd66", + "testharness" + ], + "import-maps/csp/hash.tentative.html": [ + "868c5beb81b45dbf2ce07548427f8547accaeec4", + "testharness" + ], + "import-maps/csp/nonce-failure.tentative.html": [ + "a1661a432ab57534fee650b4b15009ea1c8a13cd", + "testharness" + ], + "import-maps/csp/nonce.tentative.html": [ + "858c572214fb482398707a7b7bd45cf7021a8d94", + "testharness" + ], + "import-maps/csp/unsafe-inline.tentative.html": [ + "101c33cf84e9fb5e68cf8d5910f4ffbe7949e9d7", + "testharness" + ], "import-maps/data.sub.tentative.html": [ "1c7172bf7c6f21aeb22948f9d3eb05d9b3c11b86", "testharness" @@ -434866,7 +435042,7 @@ "support" ], "interfaces/image-capture.idl": [ - "424e44773ad6ca30636591c56dfe19c6e88d1729", + "e9016a1f9bab87e9ed62a4bc99e7bcd0d958abf4", "support" ], "interfaces/input-events.idl": [ @@ -435018,7 +435194,7 @@ "support" ], "interfaces/resize-observer.idl": [ - "fc56faf4f93ba59cdbf52d54fb39e5427549120e", + "d96a348a721a62516a451c2bb58618fe48035178", "support" ], "interfaces/resource-timing.idl": [ @@ -435150,7 +435326,7 @@ "support" ], "interfaces/webrtc-stats.idl": [ - "e5289283615c49145b69f718e45747b62e7031fa", + "b6b30e88268d27dd6e9a902768521fcf74c3a514", "support" ], "interfaces/webrtc.idl": [ @@ -435166,7 +435342,7 @@ "support" ], "interfaces/webxr.idl": [ - "1bbe7efd2da4c5f17967257cb52d1c6139624ddf", + "7594489a36d130864e553a3c8125aa2488895b2e", "support" ], "interfaces/worklets.idl": [ @@ -435574,7 +435750,7 @@ "support" ], "lint.whitelist": [ - "fd4d4049d6d2bd5dd68b1a72864fb63496ec1bea", + "96fd7ed0c2939411333b4b204687e68f61001fc8", "support" ], "loading/preloader-css-import-no-quote.tentative.html": [ @@ -435881,6 +436057,14 @@ "c88484b9d59a7811f6cfde7065de4facbdf1f74a", "testharness" ], + "mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html": [ + "da0b79ff9a67cbe53daeb141aaa2efd4f2eb96ad", + "support" + ], + "mathml/presentation-markup/operators/mo-paint-lspace-rspace.html": [ + "66df88264d191d91234364aebaa33c849e0217b5", + "reftest" + ], "mathml/presentation-markup/radicals/root-parameters-1.html": [ "51d4713d4ea1c429e018c6a0914b130bc6dc1cd5", "testharness" @@ -447121,7 +447305,7 @@ "b6485f696b446c83389518b9aaead9f1cb74884a", "testharness" ], - "orientation-event/free-fall-manual.html": [ + "orientation-event/free-fall-manual.https.html": [ "c71f61fa696050da421e7c3311716bf63b978c71", "manual" ], @@ -447129,7 +447313,11 @@ "55c8f99b9249b47d68d88fd7d82e88932b885264", "support" ], - "orientation-event/horizontal-surface-manual.html": [ + "orientation-event/horizontal-surface-manual.https-expected.txt": [ + "55c8f99b9249b47d68d88fd7d82e88932b885264", + "support" + ], + "orientation-event/horizontal-surface-manual.https.html": [ "0b7302e704018f2b412c0565b7f134bb08c0b9df", "manual" ], @@ -447145,59 +447333,59 @@ "73ce97ab5c1fd7220fb65e53fb51e0bfa86beb28", "testharness" ], - "orientation-event/screen-upmost-manual.html": [ + "orientation-event/screen-upmost-manual.https.html": [ "560c3e3a1f6bde251197585843263dcd1fc8ed6d", "manual" ], - "orientation-event/screen-upright-manual.html": [ + "orientation-event/screen-upright-manual.https.html": [ "8a1b6d27da83cab9c734f78bff11985127a5e48c", "manual" ], - "orientation-event/t001-manual.html": [ + "orientation-event/t001-manual.https.html": [ "a38d3fd5398f5c49da5034e5a357d908ee0e6dc3", "manual" ], - "orientation-event/t002-manual.html": [ + "orientation-event/t002-manual.https.html": [ "13acb46838a85292ee9b679391d49c8bf191050d", "manual" ], - "orientation-event/t003-manual.html": [ + "orientation-event/t003-manual.https.html": [ "328132d08e8c06f9979f66dc5c46ddf6d465fdd5", "manual" ], - "orientation-event/t006-manual.html": [ + "orientation-event/t006-manual.https.html": [ "e41f4634e8bc3d26b9a69d86b6794b922cd5df53", "manual" ], - "orientation-event/t009-manual.html": [ + "orientation-event/t009-manual.https.html": [ "d00f7e71b01a9486f138f01dcb0b3cb635a60906", "manual" ], - "orientation-event/t010-manual.html": [ + "orientation-event/t010-manual.https.html": [ "9a6e00e1f739c9d6d045e20730472602cb015852", "manual" ], - "orientation-event/t012-manual.html": [ + "orientation-event/t012-manual.https.html": [ "e5ac1c98b476840b286bc219cc01f6e6dbd81f2b", "manual" ], - "orientation-event/t021-manual.html": [ + "orientation-event/t021-manual.https.html": [ "449d6100f10b141044ae9802a3121a72c115c109", "manual" ], - "orientation-event/t022-manual.html": [ + "orientation-event/t022-manual.https.html": [ "45e9e7e83e46f6aed982d15933245af750fb54be", "manual" ], - "orientation-event/t023-manual.html": [ + "orientation-event/t023-manual.https.html": [ "7606e52327d17c7b5f10f780272fd977e80840f4", "manual" ], - "orientation-event/t025-manual.html": [ + "orientation-event/t025-manual.https.html": [ "9489855fcddfc8dcfb0deb2aa032f38c87a62ce4", "manual" ], - "orientation-event/t028-manual.html": [ + "orientation-event/t028-manual.https.html": [ "669c4e47e0f18ff6a008cc60a1cef022fbc57a1a", "manual" ], @@ -448377,9 +448565,9 @@ "127b07a9ee0c36004e2a5c1113b01c18633672d4", "manual" ], - "pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html": [ - "04d56cb7a51db2be25972c181cf60cf69ba39591", - "manual" + "pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html": [ + "7b09a17bb484d5996253447984679296085e3b0e", + "testharness" ], "pointerevents/pointerevent_click_during_capture.html": [ "7f63283b61a4bedac614914b3fda14364abd14ad", @@ -448433,9 +448621,9 @@ "7d38de7446938de3715b19f4585d747a18912d77", "testharness" ], - "pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html": [ - "56be26549f8fc9bed9836114569261f7252b3799", - "manual" + "pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html": [ + "555e5feb010aa3277c454e8396d2b976f552dbb8", + "testharness" ], "pointerevents/pointerevent_pointerleave_descendant_over.html": [ "ccc5f37477cc8eabc3effa75d45f2f45d7ea31f5", @@ -448465,9 +448653,9 @@ "f65512832c8fa78a461562a41755e617159dc521", "testharness" ], - "pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html": [ - "1888591a7c2b2d18bbfff9395845426e3a5baffb", - "manual" + "pointerevents/pointerevent_pointerout_after_pointercancel_touch.html": [ + "13e7ffaebc1a80ba7bef12d32088aca1c250cde2", + "testharness" ], "pointerevents/pointerevent_pointerout_pen.html": [ "972f99d95080ab702da79f8125119a2b27778a84", @@ -448485,9 +448673,9 @@ "75351dfb0689418537e6b20d92ac60feae0da2fb", "testharness" ], - "pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html": [ - "497840041f6b6f67326bede1fbfef442f403f7b7", - "manual" + "pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html": [ + "493236150dd32d0c6713b5b2dff123d1eefd5f7b", + "testharness" ], "pointerevents/pointerevent_releasepointercapture_onpointerup_mouse.html": [ "23c28b4bf755e493d747f7814a21aa598f4f0d8c", @@ -448541,9 +448729,9 @@ "5bab6e66121cebc47213914fb07f7995d8b0722d", "testharness" ], - "pointerevents/pointerevent_touch-action-auto-css_touch-manual.html": [ - "f5e9d12c353902852670524181df5bbdf48425df", - "manual" + "pointerevents/pointerevent_touch-action-auto-css_touch.html": [ + "e995ccd5d6e1d4c23a3df075208d794f2b66edbe", + "testharness" ], "pointerevents/pointerevent_touch-action-button-test_touch-manual.html": [ "c7c5d9a44080863f69afda3c1a94f268e7d90096", @@ -448569,9 +448757,9 @@ "d420cc56c77b6910ee96d875ee24eb0b9b0a4c71", "manual" ], - "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html": [ - "d87d2b3a34decc5a4633c5facf8b231dcbb6036a", - "manual" + "pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html": [ + "a1fefe16982316546b2cb0a7bf14362fe21f7145", + "testharness" ], "pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html": [ "5e674a14da550fb63bfe53859a8e4db529f559e8", @@ -448597,9 +448785,9 @@ "e2a4386b27abcd29be0563a8537653bec0206ccd", "manual" ], - "pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html": [ - "0c900ff7407fbccf652975d7d7c84187817a6cc8", - "manual" + "pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html": [ + "0c88054379538b4287c9157124f68b9cbff82234", + "testharness" ], "pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html": [ "4ad39ecc8386688a6ac0f10014dc55bd77289ae8", @@ -448625,6 +448813,10 @@ "f42d9f6bd6703b962058b79faae413fbed0757cc", "testharness" ], + "pointerevents/pointerlock/pointerevent_coordinates_when_locked.html": [ + "2556e83da10d9b8ee36b8ebbe67d513597d2fe77", + "testharness" + ], "pointerevents/pointerlock/pointerevent_movementxy-manual.html": [ "5b0edd3c61da0bf817cf2e53bab2a564013872fa", "manual" @@ -448754,7 +448946,7 @@ "support" ], "portals/portal-activate-data.html": [ - "e2417cb7332010cccd66435743f300313614c0e6", + "0d8ec33cae787ddd0ed22284ed0a955e312d505d", "testharness" ], "portals/portal-activate-event.html": [ @@ -458546,7 +458738,7 @@ "support" ], "resize-observer/idlharness.window-expected.txt": [ - "45105ba57ad928ff2f592a0c7f6893ac6096bd21", + "b65533505eba0a76545c64b0fde4a5c4327d31a8", "support" ], "resize-observer/idlharness.window.js": [ @@ -464025,6 +464217,42 @@ "f1dbfe6d1adbe7ef7663c5298692872897ce3e0c", "support" ], + "signed-exchange/appcache/appcache.manifest": [ + "adc0409be92a30565f31bb323e001ecae95ed5fe", + "support" + ], + "signed-exchange/appcache/resources/appcached-url-in-sxg.html": [ + "5f5defbedf025e399ffb69df45ffafbc6fe32938", + "support" + ], + "signed-exchange/appcache/resources/appcached-url.html": [ + "d58617b64eb038e6b16653c63bace22844a5aac0", + "support" + ], + "signed-exchange/appcache/resources/inner-url.html": [ + "5b247bbfe99a5e502f8d775c37c5d543dfea3fe3", + "support" + ], + "signed-exchange/appcache/resources/sxg/__dir__.headers": [ + "83a3c128cfe36a3c50eca2fae6ac866e1bd339c5", + "support" + ], + "signed-exchange/appcache/resources/sxg/sxg-appcached.sxg": [ + "673adc20926479486821fdf6fbe1c11cde119b64", + "support" + ], + "signed-exchange/appcache/resources/sxg/sxg-location.sxg": [ + "624e67362c50f083483597b4968e668d1424356b", + "support" + ], + "signed-exchange/appcache/sxg-inner-resp-over-appcache.tentative.https.html": [ + "68edbede31f0be0e095ce110af0970ca4535d304", + "testharness" + ], + "signed-exchange/appcache/sxg-served-from-appcache.tentative.https.html": [ + "b9ca0ff61e59991853de4abc0eb99a445045859c", + "testharness" + ], "signed-exchange/check-cert-request.tentative.html": [ "b1418e929083bf1cd8c591bb42e13a35b0b47a6f", "testharness" @@ -464182,7 +464410,7 @@ "support" ], "signed-exchange/resources/generate-test-sxgs.sh": [ - "e76286be991ca3d3832f767a5ab7aab172157184", + "64c28325d3a98e330dafc0a5567f4681b812ff55", "support" ], "signed-exchange/resources/inner-url.html": [ @@ -466346,7 +466574,7 @@ "reftest" ], "svg/pservers/reftests/radialgradient-fully-overlapping.svg": [ - "e16bb4ab917178b7a17bcb82b74046a457e9c03f", + "5b5f7bd4c836efc57f72064b9b1a46b8c2bc79e4", "reftest" ], "svg/pservers/reftests/reference/green-100x100.svg": [ @@ -467190,7 +467418,7 @@ "support" ], "tools/ci/azure/affected_tests.yml": [ - "17fca51d50cbd4f1986c63f3383b18dbdbe9c6fe", + "8076bc386986ed48a7af50fd48a59a544bf8c3bc", "support" ], "tools/ci/azure/checkout.yml": [ @@ -467394,7 +467622,7 @@ "support" ], "tools/manifest/manifest.py": [ - "e2e35d7ff992f944e983a727cd6acc574fbaf6fc", + "90655daca22406f99cf92295413894d0f8d9291b", "support" ], "tools/manifest/sourcefile.py": [ @@ -469762,11 +469990,11 @@ "support" ], "tools/third_party/py/doc/announce/release-1.4.0.txt": [ - "6f9a7714d9f16c169a3ace131783ebc298936d39", + "abaa830459951e563f8b56cfad0a0684236dd183", "support" ], "tools/third_party/py/doc/announce/release-1.4.1.txt": [ - "a5aa76b1438eb7288c580ba2b50dda96503198fb", + "b37a148af59a1af7d46028fb1f1dcb2597f3ed76", "support" ], "tools/third_party/py/doc/announce/releases.txt": [ @@ -473721,18 +473949,10 @@ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "support" ], - "wasm/jsapi/memory/grow.any-expected.txt": [ - "6f066d25dc2b20f11d589cd2d683d722a138b432", - "support" - ], "wasm/jsapi/memory/grow.any.js": [ "11c41942510b65b62b63468cc332b803445321de", "testharness" ], - "wasm/jsapi/memory/grow.any.worker-expected.txt": [ - "6f066d25dc2b20f11d589cd2d683d722a138b432", - "support" - ], "wasm/jsapi/memory/toString.any.js": [ "4e15d75ea20f1ebfeba5dc7c8a9a52c253dd01bf", "testharness" @@ -482698,7 +482918,7 @@ "support" ], "webxr/idlharness.https.window-expected.txt": [ - "1e7eedfb9bddd96261ad6d18846be5f143839b08", + "e15f9c4f30f66871b2f5d1411f991ba582bdad4c", "support" ], "webxr/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html new file mode 100644 index 0000000..a36934e38 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>position:sticky should operate correctly</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> + + + + +<div style="position: fixed;">There should be text visible below.</div> +<div style="height: 200px;width:600px;position: fixed;top: 0px;"> + <div style="position: relative;top: 100px;"> + <div style="height: 150px;width: 500px;position: absolute;backface-visibility: hidden;background: white;"> + </div> + <div style="overflow: hidden;"> + <a style="position: relative;">THIS SHOULD STAY VISIBLE<BR>IF YOU SCROLL DOWN</a> + </div> + </div> +</div> +<div style="height: 2200px;"> +</div> +<script> + window.onload = function() { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + window.scrollTo(0,300); + document.documentElement.classList.remove("reftest-wait"); + }); + }); + }; +</script> +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos.html b/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos.html new file mode 100644 index 0000000..46085b4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/position-sticky-scroll-with-clip-and-abspos.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<meta charset="utf-8"> +<title>position:sticky should operate correctly</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" /> +<meta name="assert" content="This test checks that the combination of position:sticky, overflow clip, and out-of-flow descendants are properly displayed when scrolled" /> +<link rel="match" href="position-sticky-scroll-with-clip-and-abspos-ref.html"> + +<div style="position: fixed;">There should be text visible below.</div> +<div style="height: 200px;width:600px;position: sticky;top: 0px;"> + <div style="position: relative;top: 100px;"> + <div style="height: 150px;width: 500px;position: absolute;backface-visibility: hidden;background: white;"> + </div> + <div style="overflow: hidden;"> + <a style="position: relative;">THIS SHOULD STAY VISIBLE<BR>IF YOU SCROLL DOWN</a> + </div> + </div> +</div> +<div style="height: 2000px;"> +</div> +<script> + window.onload = function() { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + window.scrollTo(0,300); + document.documentElement.classList.remove("reftest-wait"); + }); + }); + }; +</script> +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html index 5ee86ae..c7ae5f2 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
@@ -568,5 +568,11 @@ assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)"); }, 'Adopting a shadow host will empty adoptedStyleSheets if adopting to a different document'); -</script> +test(() => { + const host = document.createElement("div"); + const root = host.attachShadow({mode: "open"}); + root.adoptedStyleSheets = [new CSSStyleSheet()]; + document.body.offsetTop; +}, 'Forcing a style update after adding an adopted stylesheet on a disconnected shadow root should not crash.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection-worker.js b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection-worker.js index c6b8a7c..2e4e3cd 100644 --- a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection-worker.js +++ b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection-worker.js
@@ -5,9 +5,11 @@ onmessage = event => { switch(event.data.type) { case 'ready': - navigator.idle.query().then( - () => postMessage({ enabled: true }), - error => postMessage ({ enabled: false })); + new IdleDetector().start().then(() => { + postMessage({ enabled: true }); + }, error => { + postMessage ({ enabled: false }); + }); break; } };
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection.html b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection.html index e542e3b..65a57818 100644 --- a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection.html +++ b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-idle-detection.html
@@ -1,9 +1,10 @@ <script> 'use strict'; -navigator.idle.query().then(status => { +new IdleDetector().start().then(() => { window.parent.postMessage({ enabled: true }, '*'); }, error => { window.parent.postMessage({ enabled: false }, '*'); }); + </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html index ac0f56f..7a57826 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html
@@ -77,11 +77,8 @@ test3.step(function(){ var c3 = new VTTCue(0, 2, "text3"); t1.addCue(c3); - assert_equals(t1.activeCues.length, 1, "t1.activeCues.length after adding a cue in the same script"); - test3.step_timeout(function(){ - assert_equals(t1.activeCues.length, 2, "t1.activeCues.length after the event loop has spun"); - test3.done(); - }, 0); + assert_equals(t1.activeCues.length, 2, "t1.activeCues.length should be changed immediately"); + test3.done(); }); test2.done(); });
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html index 9706667..70724041 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-enter-exit.html
@@ -25,7 +25,7 @@ } var cueCount = 0; - function cueEntered() { + function cueEntered(event) { var currentCue = event.target; // This cue is the currently active cue.
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/basics.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/idle-detection/basics.tentative.https.any.js index ef5de216..df54757 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/basics.tentative.https.any.js +++ b/third_party/blink/web_tests/external/wpt/idle-detection/basics.tentative.https.any.js
@@ -3,70 +3,76 @@ 'use strict'; promise_test(async t => { - let promise = navigator.idle.query(); - assert_equals(promise.constructor, Promise, - 'query() returns a promise'); + let status = new IdleDetector(); - let status = await promise; - assert_true(status instanceof IdleStatus, - 'query() promise resolves to an IdleStatus'); + let watcher = new EventWatcher(t, status, ["change"]); + + await status.start(); + + await watcher.wait_for("change"); assert_true(['active', 'idle'].includes(status.state.user), 'status has a valid user state'); assert_true(['locked', 'unlocked'].includes(status.state.screen), 'status has a valid screen state'); -}, 'query() basics'); +}, 'start() basics'); promise_test(async t => { let used = false; - await navigator.idle.query({ + new IdleDetector({ get threshold() { used = true; return 1; } }); - assert_true(used, 'query() options "threshold" member was used'); -}, 'query() uses threshold property'); + assert_true(used, 'constructor options "threshold" member was used'); +}, 'constructor uses threshold property'); promise_test(async t => { - return promise_rejects( - t, - new TypeError, - navigator.idle.query({threshold: 0}), - 'Threshold of 0 should reject'); -}, 'query() throws with invalid threshold (0)'); + try { + new IdleDetector({threshold: 0}); + assert_unreached('Threshold of 0 should reject'); + } catch (error) { + assert_equals(error.name, 'TypeError'); + } +}, 'constructor throws with invalid threshold (0)'); promise_test(async t => { - return promise_rejects( - t, - new TypeError, - navigator.idle.query({threshold: null}), - 'Threshold of null should reject'); -}, 'query() throws with invalid threshold (null)'); + try { + new IdleDetector({threshold: null}); + assert_unreached('Threshold of null should reject'); + } catch (error) { + assert_equals(error.name, 'TypeError'); + } +}, 'constructor throws with invalid threshold (null)'); promise_test(async t => { - return promise_rejects( - t, - new TypeError, - navigator.idle.query({threshold: -1}), - 'Threshold of negative numbers should reject'); -}, 'query() throws with invalid threshold (-1)'); + try { + new IdleDetector({threshold: -1}); + assert_unreached('Threshold of negative numbers should reject'); + } catch (error) { + assert_equals(error.name, 'TypeError'); + } +}, 'constructor throws with invalid threshold (-1)'); promise_test(async t => { - return promise_rejects( - t, - new TypeError, - navigator.idle.query({threshold: NaN}), - 'Threshold of NaN should reject'); -}, 'query() throws with invalid threshold (NaN)'); + try { + new IdleDetector({threshold: NaN}); + assert_unreached('Threshold of NaN should reject'); + } catch (error) { + assert_equals(error.name, 'TypeError'); + } +}, 'constructor throws with invalid threshold (NaN)'); promise_test(async t => { - return navigator.idle.query(); -}, 'query() uses a default value for the threshold when none is passed'); + new IdleDetector(); +}, 'constructor uses a default value for the threshold when none is passed'); promise_test(async t => { - return navigator.idle.query({threshold: undefined}); -}, 'query() uses a default value for the threshold'); + new IdleDetector({threshold: undefined}); +}, 'constructor uses a default value for the threshold'); + +
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html index f8f5734..6129ba1 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -19,25 +19,25 @@ relative_worker_frame_path; async_test(t => { - test_feature_availability('idle.query()', t, same_origin_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame ' + 'allows same-origin relocation.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame ' + 'allows workers in same-origin relocation.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, expect_feature_unavailable_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame ' + 'disallows cross-origin relocation.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, expect_feature_unavailable_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame ' + 'disallows workers in cross-origin relocation.');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html index 422c45c3..b19cd241 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy-attribute.https.sub.html
@@ -15,25 +15,25 @@ const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; async_test(t => { - test_feature_availability('idle.query()', t, same_origin_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + 'in same-origin iframe using Feature policy "idle-detection".'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + 'in a worker in same-origin iframe using Feature policy "idle-detection".'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + 'in cross-origin iframe using Feature policy "idle-detection".'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, expect_feature_available_default, 'idle-detection'); }, 'Attribute allow="idle-detection" in top-level frame can be enabled ' + 'in a worker in cross-origin iframe using Feature policy "idle-detection".');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html index 3c019b7..cafe96f 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-feature-policy.https.sub.html
@@ -14,31 +14,32 @@ const cross_origin_src = sub + same_origin_src; const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; -promise_test( - () => navigator.idle.query(), +promise_test(async () => { + await new IdleDetector().start(); +}, 'Feature-Policy {"idle-detection" : ["*"]} explicity set by top-level ' + 'frame allows the top-level document.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_src, expect_feature_available_default); }, 'Feature-Policy {"idle-detection" : ["*"]} explicity set by top-level ' + 'frame allows same-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, expect_feature_available_default); }, 'Feature-Policy {"idle-detection" : ["*"]} explicity set by top-level ' + 'frame allows workers in same-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, expect_feature_available_default); }, 'Feature-Policy {"idle-detection" : ["*"]} explicity set by top-level ' + 'frame allows cross-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, expect_feature_available_default); }, 'Feature-Policy {"idle-detection" : ["*"]} explicity set by top-level ' + 'frame allows workers in cross-origin iframes.');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-default-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-default-feature-policy.https.sub.html index 7ecf7a4..59eeae0 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-default-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-default-feature-policy.https.sub.html
@@ -11,19 +11,20 @@ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' + same_origin_src; -promise_test( - () => navigator.idle.query(), +promise_test(async () => { + await new IdleDetector().start() +}, 'Default "idle-detection" feature policy ["self"] ' + 'allows the top-level document.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_src, expect_feature_available_default); }, 'Default "idle-detection" feature policy ["self"] ' + 'allows same-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, expect_feature_unavailable_default); }, 'Default "idle-detection" feature policy ["self"] ' + 'disallows cross-origin iframes.');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html index cb455f40b..2814a22 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-disabled-by-feature-policy.https.sub.html
@@ -14,35 +14,37 @@ const cross_origin_src = sub + same_origin_src; const cross_origin_worker_frame_src = sub + same_origin_worker_frame_src; -promise_test(() => { - return navigator.idle.query().then(() => { +promise_test(async () => { + try { + let idleDetector = new IdleDetector(); + await idleDetector.start(); assert_unreached('expected promise to reject with SecurityError'); - }, error => { + } catch (error) { assert_equals(error.name, 'SecurityError'); - }); + } }, 'Feature-Policy {"idle-detection" : []} explicitly set by top-level frame ' + 'disallows query in the top-level document.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_src, expect_feature_unavailable_default); }, 'Feature-Policy {"idle-detection" : []} explicitly set by top-level frame ' + 'disallows same-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, same_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, same_origin_worker_frame_src, expect_feature_unavailable_default); }, 'Feature-Policy {"idle-detection" : []} explicitly set by top-level frame ' + 'disallows workers in same-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_src, expect_feature_unavailable_default); }, 'Feature-Policy {"idle-detection" : []} explicitly set by top-level frame ' + 'disallows cross-origin iframes.'); async_test(t => { - test_feature_availability('idle.query()', t, cross_origin_worker_frame_src, + test_feature_availability('new IdleDetector().start()', t, cross_origin_worker_frame_src, expect_feature_unavailable_default); }, 'Feature-Policy {"idle-detection" : []} explicitly set by top-level frame ' + 'disallows workers in cross-origin iframes.');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection.idl b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection.idl index 4b502c9..1fd4d45 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection.idl +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection.idl
@@ -1,28 +1,16 @@ -[SecureContext] -interface mixin NavigatorIdle { - readonly attribute IdleManager idle; -}; - -Navigator includes NavigatorIdle; -WorkerNavigator includes NavigatorIdle; - -[ - SecureContext, - Exposed=(Window,Worker) -] interface IdleManager { - Promise<IdleStatus> query(optional IdleOptions options); -}; - dictionary IdleOptions { unsigned long threshold; }; [ SecureContext, + Constructor(optional IdleOptions options), Exposed=(Window,Worker) -] interface IdleStatus : EventTarget { +] interface IdleDetector : EventTarget { readonly attribute IdleState state; attribute EventHandler onchange; + Promise<any> start(); + void stop(); }; [
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/idle-detection/idlharness.https.any.js index 4bda5c1..482e2f4d 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/idlharness.https.any.js +++ b/third_party/blink/web_tests/external/wpt/idle-detection/idlharness.https.any.js
@@ -1,34 +1,36 @@ // META: script=/resources/WebIDLParser.js // META: script=/resources/idlharness.js -// https://github.com/inexorabletash/idle-detection +// https://github.com/samuelgoto/idle-detection 'use strict'; -promise_test(async () => { +promise_test(async (t) => { const srcs = ['./idle-detection.idl', '/interfaces/dom.idl', '/interfaces/html.idl']; + const [idle, dom, html] = await Promise.all( - srcs.map(i => fetch(i).then(r => r.text()))); + srcs.map(i => fetch(i).then(r => r.text())) + ); const idl_array = new IdlArray(); idl_array.add_idls(idle); idl_array.add_dependency_idls(dom); idl_array.add_dependency_idls(html); - self.idle = await navigator.idle.query(); + self.idle = new IdleDetector({threshold: 1}); + + let watcher = new EventWatcher(t, self.idle, ["change"]); + + self.idle.start(); + + await watcher.wait_for("change"); idl_array.add_objects({ - IdleManager: ['navigator.idle'], - IdleStatus: ['idle'], + IdleDetector: ['idle'], IdleState: ['idle.state'] }); - if (self.Window) { - idl_array.add_objects({ Navigator: ['navigator'] }); - } else { - idl_array.add_objects({ WorkerNavigator: ['navigator'] }); - } idl_array.test(); }, 'Test IDL implementation of Idle Detection API');
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/interceptor.https.html b/third_party/blink/web_tests/external/wpt/idle-detection/interceptor.https.html index 03595afc..37922c8 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/interceptor.https.html +++ b/third_party/blink/web_tests/external/wpt/idle-detection/interceptor.https.html
@@ -1,19 +1,19 @@ <!DOCTYPE html> -<link rel="help" href="https://github.com/inexorabletash/idle-detection"> +<link rel="help" href="https://github.com/samuelgoto/idle-detection"> <title>Tests the Idle Detection API</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/mojo/public/mojom/base/string16.mojom.js"></script> <script src="/gen/mojo/public/mojom/base/time.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/idle/idle_manager.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/idle/idle_manager.mojom.js"></script> <script src="mock.js"></script> <script> 'use strict'; promise_test(async t => { - // Basic test that expects navigator.idle.query() to call internally - // addMonitor, which in turn will return an ACTIVE state. + // Basic test that expects start() to call internally + // addMonitor, which in turn return an ACTIVE state. expect(addMonitor).andReturn((threshold, monitorPtr) => { return Promise.resolve({ state: { @@ -23,36 +23,58 @@ }); }); - let status = await navigator.idle.query({threshold: 10}); + let detector = new IdleDetector({threshold: 10}); - assert_equals(status.state.user, "active"); - assert_equals(status.state.screen, "locked"); + let watcher = new EventWatcher(t, detector, ["change"]); + + await detector.start(); + + // Waits for the first event. + await watcher.wait_for("change"); + + assert_equals(detector.state.user, "active"); + assert_equals(detector.state.screen, "locked"); + + detector.stop(); }, 'query()'); promise_test(async t => { // Verifies that an event is thrown when a change of state from IDLE to ACTIVE // is detected. expect(addMonitor).andReturn((threshold, monitorPtr) => { + let first = Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.UNLOCKED + } + }); + t.step_timeout(() => { monitorPtr.update({ user: UserIdleState.IDLE, screen: ScreenIdleState.UNLOCKED }); }, 0); - return Promise.resolve({ - state: { - user: UserIdleState.ACTIVE, - screen: ScreenIdleState.UNLOCKED - } - }); + + return first; }); - let monitor = await navigator.idle.query({threshold: 10}); + let detector = new IdleDetector({threshold: 10}); - await new EventWatcher(t, monitor, ["change"]).wait_for("change"); + let watcher = new EventWatcher(t, detector, ["change"]); - assert_equals(monitor.state.user, "idle"); - assert_equals(monitor.state.screen, "unlocked"); + await detector.start(); + + // Wait for the initial state. + await watcher.wait_for("change"); + + // Wait for the first change in state. + await watcher.wait_for("change"); + + assert_equals(detector.state.user, "idle"); + assert_equals(detector.state.screen, "unlocked"); + + detector.stop(); }, 'updates once'); @@ -60,6 +82,13 @@ // Simulates the user being active, going idle and then going back active // again. expect(addMonitor).andReturn((threshold, monitorPtr) => { + let first = Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.UNLOCKED + } + }); + // Updates the client once with the user idle. t.step_timeout(() => { monitorPtr.update({ @@ -74,25 +103,27 @@ screen: ScreenIdleState.UNLOCKED }); }, 1); - return Promise.resolve({ - state: { - user: UserIdleState.ACTIVE, - screen: ScreenIdleState.UNLOCKED - } - }); + return first; }); - let monitor = await navigator.idle.query({threshold: 10}); + let detector = new IdleDetector({threshold: 10}); - let watcher = new EventWatcher(t, monitor, ["change"]); + let watcher = new EventWatcher(t, detector, ["change"]); - // waits for the first event. + await detector.start(); + + // Waits for the initial state. await watcher.wait_for("change"); - assert_equals(monitor.state.user, "idle"); - // waits for the second event. + // Waits for the first event. await watcher.wait_for("change"); - assert_equals(monitor.state.user, "active"); + assert_equals(detector.state.user, "idle"); + + // Waits for the second event. + await watcher.wait_for("change"); + assert_equals(detector.state.user, "active"); + + detector.stop(); }, 'updates twice'); promise_test(async t => { @@ -106,28 +137,140 @@ }); }); - let monitor = await navigator.idle.query({threshold: 10}); + let detector = new IdleDetector({threshold: 10}); - assert_equals(monitor.state.screen, "locked"); + let watcher = new EventWatcher(t, detector, ["change"]); + + await detector.start(); + + // waits for the initial state. + await watcher.wait_for("change"); + + assert_equals(detector.state.screen, "locked"); + + detector.stop(); }, 'locked screen'); promise_test(async t => { - // Simulates the service becoming unavailable. expect(addMonitor).andReturn((threshold, monitorPtr) => { - return new Promise((resolve, reject) => { - // leave the renderer deliberately hanging by not resolve()-ing. + return Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.LOCKED + } + }); + }); + + let detector = new IdleDetector({threshold: 10}); + + let event = new Promise((resolve, reject) => { + detector.onchange = resolve; + }); + + await detector.start(); + + // Waits for the first event. + await event; + + assert_equals(detector.state.user, "active"); + assert_equals(detector.state.screen, "locked"); + + detector.stop(); +}, 'IdleDetector.onchange'); + +promise_test(async t => { + expect(addMonitor).andReturn((threshold, monitorPtr) => { + return Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.UNLOCKED + } }); }); - let error = new Promise((resolve, reject) => { - navigator.idle.query({threshold: 10}) - .then((e) => {reject("unexpected response :(")}) - .catch((e) => {resolve(e.message)}); - }); + let detector = new IdleDetector({threshold: 10}); - // simulates what happens when the service is unavailable. - close(); + let watcher = new EventWatcher(t, detector, ["change"]); - assert_equals(await error, "Idle detection not available"); -}, "service unavailable"); -</script> \ No newline at end of file + // Calling start() multiple times should be safe. + await detector.start(); + await detector.start(); + await detector.start(); + await detector.start(); + + // waits for the initial state. + await watcher.wait_for("change"); + assert_equals(detector.state.user, "active"); + assert_equals(detector.state.screen, "unlocked"); + + // Calling stop() multiple times should be safe. + detector.stop(); + detector.stop(); + detector.stop(); + detector.stop(); +}, 'Safe to call start() or stop() multiple times'); + +promise_test(async t => { + expect(addMonitor).andReturn((threshold, monitorPtr) => { + return Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.UNLOCKED + } + }); + }); + + let detector = new IdleDetector({threshold: 10}); + + // Calling stop() before start() is a no-op. + detector.stop(); + + let watcher = new EventWatcher(t, detector, ["change"]); + + await detector.start(); + + // waits for the initial state. + await watcher.wait_for("change"); + assert_equals(detector.state.user, "active"); + assert_equals(detector.state.screen, "unlocked"); + + detector.stop(); +}, 'Calling stop() after start() is a no-op'); + +promise_test(async t => { + expect(addMonitor).andReturn((threshold, monitorPtr) => { + return Promise.resolve({ + state: { + user: UserIdleState.ACTIVE, + screen: ScreenIdleState.UNLOCKED + } + }); + }); + + let detector = new IdleDetector({threshold: 10}); + + let watcher = new EventWatcher(t, detector, ["change"]); + + await detector.start(); + await watcher.wait_for("change"); + detector.stop(); + + expect(addMonitor).andReturn((threshold, monitorPtr) => { + return Promise.resolve({ + state: { + user: UserIdleState.IDLE, + screen: ScreenIdleState.LOCKED + } + }); + }); + + // Restarting the monitor. + await detector.start(); + await watcher.wait_for("change"); + assert_equals(detector.state.user, "idle"); + assert_equals(detector.state.screen, "locked"); + + detector.stop(); +}, 'Calling start() after stop(): re-starting monitor.'); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js b/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js index 103ce5e9..e643414f 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js +++ b/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-allowed-by-feature-policy-worker.js
@@ -8,7 +8,9 @@ workerType = 'dedicated'; } -promise_test(() => navigator.idle.query(), +promise_test(async () => { + await new IdleDetector().start() +}, `Inherited header feature policy allows ${workerType} workers.`) done();
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js b/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js index 66218a5..138b2917 100644 --- a/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js +++ b/third_party/blink/web_tests/external/wpt/idle-detection/resources/idle-detection-disabled-by-feature-policy-worker.js
@@ -9,9 +9,14 @@ workerType = 'dedicated'; } -promise_test(() => navigator.idle.query().then( - () => assert_unreached('expected promise to reject with SecurityError'), - error => assert_equals(error.name, 'SecurityError')), - `Inherited ${header} disallows ${workerType} workers.`); +promise_test(async () => { + try { + await new IdleDetector().start(); + assert_unreached('expected start() to throw with SecurityError'); + } catch (error) { + assert_equals(error.name, 'SecurityError'); + } +}, +`Inherited ${header} disallows ${workerType} workers.`); done();
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target-dynamic.sub.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target-dynamic.sub.tentative.html new file mode 100644 index 0000000..cef80bf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target-dynamic.sub.tentative.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/test-helper.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=B", + "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=C": "../resources/log.js?pipe=sub&name=D" + } +} +</script> +<script> +promise_test(t => { + return promise_rejects(t, TypeError(), + import('../resources/log.js?pipe=sub&name=A'), + 'Dynamic import should fail'); + }, 'The URL after mapping violates CSP (but not the URL before mapping)'); + +promise_test(t => { + return import('https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=C') + .then(() => assert_array_equals(log, ["log:D"])); + }, 'The URL before mapping violates CSP (but not the URL after mapping)'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target.sub.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target.sub.tentative.html new file mode 100644 index 0000000..e6bbfecd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/applied-to-target.sub.tentative.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/test-helper.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=B", + "https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=C": "../resources/log.js?pipe=sub&name=D" + } +} +</script> +<script type="module"> +import '../resources/log.js?pipe=sub&name=A'; +</script> +<script type="module"> +test(t => { + assert_array_equals(log, []); + }, 'The URL after mapping violates CSP (but not the URL before mapping)'); +</script> + +<script type="module"> +import 'https://{{domains[www1]}}:{{ports[https][0]}}/import-maps/resources/log.js?pipe=sub&name=C'; +</script> +<script type="module"> +test(t => { + assert_array_equals(log, ["log:D"]); + }, 'The URL before mapping violates CSP (but not the URL after mapping)'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/hash-failure.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/hash-failure.tentative.html new file mode 100644 index 0000000..4bab1ed --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/hash-failure.tentative.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'sha256-wrong9e+pZbSYIkpB8BIE0Hs7yHajJDiX5mnT/wrong=' 'sha256-RAsyam34o4peVe9sCebtaZWRVhqAhudem+NlcnP2Kp8=';"> + +<!-- 'sha256-P5xqp9e+pZbSYIkpB8BIE0Hs7yHajJDiX5mnT/1PO1I=' --> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> + +<!-- 'sha256-RAsyam34o4peVe9sCebtaZWRVhqAhudem+NlcnP2Kp8=' --> +<script> +const log = []; +promise_test(() => { + return import("../resources/log.js?pipe=sub&name=A") + .then(() => assert_array_equals(log, ["log:A"])) + }, + 'Importmap should not be accepted due to wrong hash'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/hash.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/hash.tentative.html new file mode 100644 index 0000000..868c5beb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/hash.tentative.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'sha256-P5xqp9e+pZbSYIkpB8BIE0Hs7yHajJDiX5mnT/1PO1I=' 'sha256-Ciqph+wQDoB2suzqZVHOD0iw99WqaTUwZXRl7ATzBxc=';"> + +<!-- 'sha256-P5xqp9e+pZbSYIkpB8BIE0Hs7yHajJDiX5mnT/1PO1I=' --> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> + +<!-- 'sha256-Ciqph+wQDoB2suzqZVHOD0iw99WqaTUwZXRl7ATzBxc=' --> +<script> +const log = []; +promise_test(() => { + return import("../resources/log.js?pipe=sub&name=A") + .then(() => assert_array_equals(log, ["log:B"])) + }, + 'Importmap should be accepted due to hash'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce-failure.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce-failure.tentative.html new file mode 100644 index 0000000..a1661a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce-failure.tentative.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abc';"> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> +<script type="importmap" nonce="wrong"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> +<script nonce="abc"> +const log = []; +promise_test(() => { + return import("../resources/log.js?pipe=sub&name=A") + .then(() => assert_array_equals(log, ["log:A"])) + }, + 'Importmap should be rejected due to nonce'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce.tentative.html new file mode 100644 index 0000000..858c5722 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/nonce.tentative.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abc';"> +<script type="importmap" nonce="abc"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> +<script nonce="abc"> +const log = []; +promise_test(() => { + return import("../resources/log.js?pipe=sub&name=A") + .then(() => assert_array_equals(log, ["log:B"])) + }, + 'Importmap should be accepted according to its correct nonce'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/csp/unsafe-inline.tentative.html b/third_party/blink/web_tests/external/wpt/import-maps/csp/unsafe-inline.tentative.html new file mode 100644 index 0000000..101c33c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/import-maps/csp/unsafe-inline.tentative.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> +<script type="importmap"> +{ + "imports": { + "../resources/log.js?pipe=sub&name=A": "../resources/log.js?pipe=sub&name=B" + } +} +</script> +<script> +const log = []; +promise_test(() => { + return import("../resources/log.js?pipe=sub&name=A") + .then(() => assert_array_equals(log, ["log:B"])) + }, + 'Importmap should be accepted due to unsafe-inline'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/image-capture.idl b/third_party/blink/web_tests/external/wpt/interfaces/image-capture.idl index 424e447..e9016a1f 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/image-capture.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/image-capture.idl
@@ -59,9 +59,11 @@ boolean brightness = true; boolean contrast = true; + boolean pan = true; boolean saturation = true; boolean sharpness = true; boolean focusDistance = true; + boolean tilt = true; boolean zoom = true; boolean torch = true; }; @@ -82,6 +84,8 @@ MediaSettingsRange sharpness; MediaSettingsRange focusDistance; + MediaSettingsRange pan; + MediaSettingsRange tilt; MediaSettingsRange zoom; boolean torch; @@ -104,6 +108,8 @@ ConstrainDouble sharpness; ConstrainDouble focusDistance; + ConstrainDouble pan; + ConstrainDouble tilt; ConstrainDouble zoom; ConstrainBoolean torch; @@ -126,6 +132,8 @@ double sharpness; double focusDistance; + double pan; + double tilt; double zoom; boolean torch;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/resize-observer.idl b/third_party/blink/web_tests/external/wpt/interfaces/resize-observer.idl index fc56faf4..d96a348a 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/resize-observer.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/resize-observer.idl
@@ -1,30 +1,43 @@ // GENERATED CONTENT - DO NOT EDIT // Content was automatically extracted by Reffy into reffy-reports // (https://github.com/tidoust/reffy-reports) -// Source: Resize Observer 1 (https://wicg.github.io/ResizeObserver/) +// Source: Resize Observer (https://drafts.csswg.org/resize-observer/) -[Constructor(ResizeObserverCallback callback), - Exposed=Window] +enum ResizeObserverBoxOptions { + "border-box", "content-box" +}; + +dictionary ResizeObserverOptions { + ResizeObserverBoxOptions box = "content-box"; +}; + +[Exposed=(Window), + Constructor(ResizeObserverCallback callback)] interface ResizeObserver { - void observe(Element target); + void observe(Element target, optional ResizeObserverOptions options); void unobserve(Element target); void disconnect(); }; callback ResizeObserverCallback = void (sequence<ResizeObserverEntry> entries, ResizeObserver observer); -[Constructor(Element target) -] +[Exposed=Window, Constructor(Element target)] interface ResizeObserverEntry { readonly attribute Element target; readonly attribute DOMRectReadOnly contentRect; + readonly attribute ResizeObserverSize borderBoxSize; + readonly attribute ResizeObserverSize contentBoxSize; +}; + +interface ResizeObserverSize { + readonly attribute unrestricted double inlineSize; + readonly attribute unrestricted double blockSize; }; [Constructor(Element target) ] interface ResizeObservation { readonly attribute Element target; - readonly attribute float broadcastWidth; - readonly attribute float broadcastHeight; - boolean isActive(); + readonly attribute ResizeObserverBoxOptions observedBox; + readonly attribute ResizeObserverSize lastReportedSize; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl index e528928..b6b30e88 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl
@@ -72,6 +72,7 @@ DOMHighResTimeStamp lastPacketReceivedTimestamp; double averageRtcpInterval; unsigned long fecPacketsReceived; + unsigned long fecPacketsDiscarded; unsigned long long bytesReceived; unsigned long packetsFailedDecryption; unsigned long packetsDuplicated; @@ -204,6 +205,7 @@ unsigned long long jitterBufferEmittedCount; unsigned long long totalSamplesReceived; unsigned long long concealedSamples; + unsigned long long silentConcealedSamples; unsigned long long concealmentEvents; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl index 1bbe7efd..7594489 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
@@ -25,7 +25,6 @@ [SecureContext, Exposed=Window] interface XRSession : EventTarget { // Attributes readonly attribute XRSessionMode mode; - readonly attribute XRPresentationContext? outputContext; readonly attribute XREnvironmentBlendMode environmentBlendMode; readonly attribute XRRenderState renderState; readonly attribute XRSpace viewerSpace; @@ -59,19 +58,20 @@ dictionary XRSessionCreationOptions { XRSessionMode mode = "inline"; - XRPresentationContext? outputContext = null; }; dictionary XRRenderStateInit { double depthNear; double depthFar; XRLayer? baseLayer; + XRPresentationContext? outputContext; }; [SecureContext, Exposed=Window] interface XRRenderState { readonly attribute double depthNear; readonly attribute double depthFar; readonly attribute XRLayer? baseLayer; + readonly attribute XRPresentationContext? outputContext; }; callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRFrame frame);
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html new file mode 100644 index 0000000..da0b79ff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace-ref.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<html> + <head> + <title><mo> paint lspace rspace</title> + <meta charset="utf-8"> + </head> + <body> + <h1>LTR case</h1> + + <p>The test passes if the arrow has a leading space of 100px, which is as wide as the black block to the left, + and a trailing space of 200px, which is as wide as the black block to the right.</p> + + <math> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="100px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="200px"></mspace> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 150px, which is as wide as the black block to the left, + and a trailing space of 150px, which is as wide as the black block to the right.</p> + + <math> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="150px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="150px"></mspace> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 200px, which is as wide as the black block to the left, + and a trailing space of 100px, which is as wide as the black block to the right.</p> + + <math> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="200px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="100px"></mspace> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <h1>RTL case</h1> + + <p>The test passes if the arrow has a leading space of 100px, which is as wide as the black block to the right, + and a trailing space of 200px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="100px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="200px"></mspace> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 150px, which is as wide as the black block to the right, + and a trailing space of 150px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="150px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="150px"></mspace> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 200px, which is as wide as the black block to the right, + and a trailing space of 100px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + <mspace width="200px"></mspace> + <mo lspace="0px" rspace="0px">→</mo> + <mspace width="100px"></mspace> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html new file mode 100644 index 0000000..66df8826 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html
@@ -0,0 +1,69 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title><mo> paint lspace rspace</title> + <link rel="help" href="https://mathml-refresh.github.io/mathml-core/#tokenmo"> + <meta name="assert" content="Verifies values for lspace and rspace for element mo in LTR and RTL modes."> + <link rel="match" href="mo-paint-lspace-rspace-ref.html"> + </head> + <body> + <h1>LTR case</h1> + + <p>The test passes if the arrow has a leading space of 100px, which is as wide as the black block to the left, + and a trailing space of 200px, which is as wide as the black block to the right.</p> + + <mth> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="100px" rspace="200px">→</mo> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 150px, which is as wide as the black block to the left, + and a trailing space of 150px, which is as wide as the black block to the right.</p> + + <math> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="150px" rspace="150px">→</mo> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 200px, which is as wide as the black block to the left, + and a trailing space of 100px, which is as wide as the black block to the right.</p> + + <math> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="200px" rspace="100px">→</mo> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <h1>RTL case</h1> + + <p>The test passes if the arrow has a leading space of 100px, which is as wide as the black block to the right, + and a trailing space of 200px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="100px" rspace="200px">→</mo> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 150px, which is as wide as the black block to the right, + and a trailing space of 150px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="150px" rspace="150px">→</mo> + <mspace width="150px" height="10px" depth="10px" style="background: black"></mspace> + </math> + + <p>The test passes if the arrow has a leading space of 200px, which is as wide as the black block to the right, + and a trailing space of 100px, which is as wide as the black block to the left.</p> + + <math dir="rtl"> + <mspace width="200px" height="10px" depth="10px" style="background: black"></mspace> + <mo lspace="200px" rspace="100px">→</mo> + <mspace width="100px" height="10px" depth="10px" style="background: black"></mspace> + </math> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https-expected.txt index 6f8a33ad..2b6107c 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https-expected.txt
@@ -1,10 +1,10 @@ This is a testharness.js-based test. -FAIL MediaTrackSupportedConstraints dictionary include attributes are correct assert_equals: Expect default value of dictionary.focalLengthX to be false expected false but got true +PASS MediaTrackSupportedConstraints dictionary include attributes are correct FAIL MediaTrackCapabilities dictionary of depth include attributes are correct assert_equals: Expect dictionary.videoKind to be string expected "string" but got "undefined" -FAIL MediaTrackConstraintSet dictionary of depth include attributes are correct assert_equals: Expect dictionary.focalLengthX to be number expected "number" but got "undefined" -FAIL MediaTrackSettings dictionary of depth include attributes are correct assert_equals: Expect dictionary.focalLengthX to be number expected "number" but got "undefined" +PASS MediaTrackConstraintSet dictionary of depth include attributes are correct +PASS MediaTrackSettings dictionary of depth include attributes are correct FAIL MediaTrackCapabilities dictionary of color include attributes are correct assert_equals: Expect dictionary.videoKind to be string expected "string" but got "undefined" -FAIL MediaTrackConstraintSet dictionary of color include attributes are correct assert_equals: Expect dictionary.focalLengthX to be number expected "number" but got "undefined" -FAIL MediaTrackSettings dictionary of color include attributes are correct assert_equals: Expect dictionary.focalLengthX to be number expected "number" but got "undefined" +PASS MediaTrackConstraintSet dictionary of color include attributes are correct +PASS MediaTrackSettings dictionary of color include attributes are correct Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https.html index e464f29..0a5b824 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-depth/dictionary-manual.https.html
@@ -24,220 +24,28 @@ let advanced_constraints_depth = [{ videoKind: "depth", - focalLengthX: 0.5, - focalLengthY: 0.5, - principalPointX: 0.1, - principalPointY: 0.1, - deprojectionDistortionCoefficients: true, - projectionDistortionCoefficients: true, - depthNear: 0.5, - depthFar: 1, - depthToVideoTransform: true }]; let advanced_constraints_color = [{ videoKind: "color", - focalLengthX: 0.5, - focalLengthY: 0.5, - principalPointX: 0.1, - principalPointY: 0.1, - deprojectionDistortionCoefficients: true, - projectionDistortionCoefficients: true -}]; - -/* - partial dictionary MediaTrackCapabilities { - // Apply to both depth stream track and color stream track: - DOMString videoKind; - (double or DoubleRange) focalLengthX; - (double or DoubleRange) focalLengthY; - (double or DoubleRange) principalPointX; - (double or DoubleRange) principalPointY; - boolean deprojectionDistortionCoefficients; - boolean projectionDistortionCoefficients; - // Apply to depth stream track: - (double or DoubleRange) depthNear; - (double or DoubleRange) depthFar; - boolean depthToVideoTransform; - }; - - dictionary DoubleRange { - double max; - double min; - }; -*/ + }]; function validateMediaTrackCapabilities(capabilities, type) { assert_string_field(capabilities, 'videoKind'); - assert_number_or_number_range_field(capabilities, 'focalLengthX'); - assert_number_or_number_range_field(capabilities, 'focalLengthY'); - assert_number_or_number_range_field(capabilities, 'principalPointX'); - assert_number_or_number_range_field(capabilities, 'principalPointY'); - assert_boolean_field(capabilities, 'deprojectionDistortionCoefficients'); - assert_boolean_field(capabilities, 'projectionDistortionCoefficients'); - if (type == "depth") { - assert_number_or_number_range_field(capabilities, 'depthNear'); - assert_number_or_number_range_field(capabilities, 'depthFar'); - assert_boolean_field(capabilities, 'depthToVideoTransform'); - } } -/* - partial dictionary MediaTrackConstraintSet { - // Apply to both depth stream track and color stream track: - ConstrainDOMString videoKind; - ConstrainDouble focalLengthX; - ConstrainDouble focalLengthY; - ConstrainDouble principalPointX; - ConstrainDouble principalPointY; - ConstrainBoolean deprojectionDistortionCoefficients; - ConstrainBoolean projectionDistortionCoefficients; - // Apply to depth stream track: - ConstrainDouble depthNear; - ConstrainDouble depthFar; - ConstrainBoolean depthToVideoTransform; - }; - - typedef (DOMString or sequence<DOMString> or ConstrainDOMStringParameters) ConstrainDOMString; - - dictionary ConstrainDOMStringParameters { - (DOMString or sequence<DOMString>) exact; - (DOMString or sequence<DOMString>) ideal; - }; - - typedef (double or ConstrainDoubleRange) ConstrainDouble; - - dictionary DoubleRange { - double max; - double min; - }; - - dictionary ConstrainDoubleRange : DoubleRange { - double exact; - double ideal; - }; - - typedef (boolean or ConstrainBooleanParameters) ConstrainBoolean; - - dictionary ConstrainBooleanParameters { - boolean exact; - boolean ideal; - }; -*/ function validateMediaTrackConstraintSet(constraints, type) { assert_constrain_string_field(constraints, 'videoKind'); - assert_constrain_number_field(constraints, 'focalLengthX'); - assert_constrain_number_field(constraints, 'focalLengthY'); - assert_constrain_number_field(constraints, 'principalPointX'); - assert_constrain_number_field(constraints, 'principalPointY'); - assert_constrain_boolean_field(constraints, 'deprojectionDistortionCoefficients'); - assert_constrain_boolean_field(constraints, 'projectionDistortionCoefficients'); - if (type == "depth") { - assert_constrain_number_field(constraints, 'depthNear'); - assert_constrain_number_field(constraints, 'depthFar'); - assert_constrain_boolean_field(constraints, 'depthToVideoTransform'); - } -} - -/* - partial dictionary MediaTrackSettings { - // Apply to both depth stream track and color stream track: - DOMString videoKind; - double focalLengthX; - double focalLengthY; - double principalPointX; - double principalPointY; - DistortionCoefficients deprojectionDistortionCoefficients; - DistortionCoefficients projectionDistortionCoefficients; - // Apply to depth stream track: - double depthNear; - double depthFar; - Transformation depthToVideoTransform; - }; - - dictionary DistortionCoefficients { - double k1; - double k2; - double p1; - double p2; - double k3; - }; - - dictionary Transformation { - Float32Array transformationMatrix; - DOMString videoDeviceId; - }; - - enum VideoKindEnum { - "color", - "depth" - }; -*/ - -function validateDistortionCoefficients(coefficients) { - assert_number_field(coefficients, 'k1'); - assert_number_field(coefficients, 'k2'); - assert_number_field(coefficients, 'p1'); - assert_number_field(coefficients, 'p2'); - assert_number_field(coefficients, 'k3'); -} - -function validateTransformation(depthToVideoTransform) { - assert_array_field(depthToVideoTransform, 'transformationMatrix'); - assert_string_field(depthToVideoTransform, 'videoDeviceId'); } function validateMediaTrackSettings(settings, type) { assert_string_field(settings, 'videoKind'); assert_enum_field(settings, 'videoKind', ['color', 'depth']) - assert_number_field(settings, 'focalLengthX'); - assert_number_field(settings, 'focalLengthY'); - assert_number_field(settings, 'principalPointX'); - assert_number_field(settings, 'principalPointY'); - if (settings.deprojectionDistortionCoefficients) { - validateDistortionCoefficients(settings.deprojectionDistortionCoefficients); - } - if (settings.projectionDistortionCoefficients) { - validateDistortionCoefficients(settings.projectionDistortionCoefficients); - } - if (type == "depth") { - assert_number_field(settings, 'depthNear'); - assert_number_field(settings, 'depthFar'); - if (settings.depthToVideoTransform) { - validateTransformation(settings.depthToVideoTransform); - } - } } -/* - partial dictionary MediaTrackSupportedConstraints { - // Apply to both depth stream track and color stream track: - boolean videoKind = true; - boolean focalLengthX = false; - boolean focalLengthY = false; - boolean principalPointX = false; - boolean principalPointY = false; - boolean deprojectionDistortionCoefficients = false; - boolean projectionDistortionCoefficients = false; - // Apply to depth stream track: - boolean depthNear = false; - boolean depthFar = false; - boolean depthToVideoTransform = false; - }; -*/ - function validateMediaTrackSupportedConstraints(supports) { assert_boolean_field(supports, 'videoKind', true); - assert_boolean_field(supports, 'focalLengthX', false); - assert_boolean_field(supports, 'focalLengthY', false); - assert_boolean_field(supports, 'principalPointX', false); - assert_boolean_field(supports, 'principalPointY', false); - assert_boolean_field(supports, 'deprojectionDistortionCoefficients', false); - assert_boolean_field(supports, 'projectionDistortionCoefficients', false); - assert_boolean_field(supports, 'depthNear', false); - assert_boolean_field(supports, 'depthFar', false); - assert_boolean_field(supports, 'depthToVideoTransform', false); } function runDictionaryTests(type, constraints) {
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/free-fall-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/free-fall-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/free-fall-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/free-fall-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.https-expected.txt b/third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.https-expected.txt new file mode 100644 index 0000000..55c8f99 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL X angle assert_approx_equals: expected a number but got a "undefined" +FAIL Y angle assert_approx_equals: expected a number but got a "undefined" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/horizontal-surface-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/screen-upmost-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/screen-upmost-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/screen-upmost-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/screen-upmost-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/screen-upright-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/screen-upright-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/screen-upright-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/screen-upright-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t001-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t001-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t001-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t001-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t002-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t002-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t002-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t002-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t003-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t003-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t003-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t003-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t006-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t006-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t006-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t006-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t009-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t009-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t009-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t009-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t010-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t010-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t010-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t010-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t012-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t012-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t012-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t012-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t021-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t021-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t021-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t021-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t022-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t022-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t022-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t022-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t023-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t023-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t023-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t023-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t025-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t025-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t025-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t025-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/orientation-event/t028-manual.html b/third_party/blink/web_tests/external/wpt/orientation-event/t028-manual.https.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/orientation-event/t028-manual.html rename to third_party/blink/web_tests/external/wpt/orientation-event/t028-manual.https.html
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html similarity index 89% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html index 04d56cb7a..7b09a17 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_change-touch-action-onpointerdown_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script src="pointerevent_support.js"></script> <style> #target0 { @@ -84,6 +87,7 @@ var styleIsChanged = false; var scrollIsReceived = false; + var scrollReceivedCorrectly = false; var firstTouchCompleted = false; var countToPass = 50; var xScr0, yScr0, xScr1, yScr1; @@ -101,7 +105,7 @@ }, "scroll was received while shouldn't"); scrollIsReceived = true; } - done(); + scrollReceivedCorrectly = true; }); on_event(target0, 'pointerdown', function(event) { @@ -124,6 +128,14 @@ on_event(target0, 'pointerup', function(event) { firstTouchCompleted = true; }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + test(function () { + assert_true(scrollReceivedCorrectly, "scroll should be received before the test finishes"); + }, "scroll should be received before the test finishes"); + done(); + }); } </script> <h1>touch-action: auto to none</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html similarity index 82% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html index 56be265..555e5feb0 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <!-- Additional helper script for common checks across event types --> <script type="text/javascript" src="pointerevent_support.js"></script> </head> @@ -44,7 +47,6 @@ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerleave"); }); eventTested = true; - test_pointerleave.done(); } } else { @@ -54,6 +56,14 @@ } } }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + test_pointerleave.step(function () { + assert_true(eventTested, "pointerleave should be received before the test finishes"); + }, "pointerleave should be received before the test finishes"); + test_pointerleave.done(); + }); } </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch.html similarity index 82% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch.html index 1888591a..13e7ffa 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_after_pointercancel_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <!-- Additional helper script for common checks across event types --> <script type="text/javascript" src="pointerevent_support.js"></script> </head> @@ -44,7 +47,6 @@ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerout"); }); eventTested = true; - test_pointerout.done(); } } else { @@ -55,6 +57,14 @@ } } }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + test_pointerout.step(function () { + assert_true(eventTested, "pointerout should be received before the test finishes"); + }, "pointerout should be received before the test finishes"); + test_pointerout.done(); + }); } </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html similarity index 83% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html index 49784004..4932361 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script src="pointerevent_support.js"></script> </head> <body class="scrollable"> @@ -22,6 +25,7 @@ <script type='text/javascript'> var pointercancelGot = false; + var lostpointercaptureGot = false; var count=0; var event_log = []; var detected_pointertypes = {}; @@ -57,13 +61,21 @@ test_pointerEvent.step(function () { assert_true(pointercancelGot, "pointercancel was received before lostpointercapture"); }); - test_pointerEvent.done(); + lostpointercaptureGot = true; }); on_event(target0, 'pointercancel', function(e) { event_log.push('pointercancel@target0'); pointercancelGot = true; }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + test_pointerEvent.step(function () { + assert_true(lostpointercaptureGot, "lostpointercapture should be received before the test finishes"); + }, "lostpointercapture should be received before the test finishes"); + test_pointerEvent.done(); + }); } </script> <h1>Pointer Events Capture Test</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch.html similarity index 87% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch.html index f5e9d12..e995ccd 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script src="pointerevent_support.js"></script> <style> #target0 { @@ -114,10 +117,19 @@ } if(xScrollIsReceived && yScrollIsReceived) { - test_touchaction.done(); updateDescriptionComplete(); } }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + return touchScrollInTarget(target0, 'right'); + }).then(function() { + test_touchaction.step(function () { + assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes"); + }, "x-scroll and y-scroll should be received before the test finishes"); + test_touchaction.done(); + }); } </script> <h1>touch-action: auto</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html similarity index 87% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html index d87d2b3..a1fefe1 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script src="pointerevent_support.js"></script> <style> #divParent { @@ -114,10 +117,19 @@ } if(xScrollIsReceived && yScrollIsReceived) { - test_touchaction.done(); updateDescriptionComplete(); } }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + return touchScrollInTarget(target0, 'right'); + }).then(function() { + test_touchaction.step(function () { + assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes"); + }, "x-scroll and y-scroll should be received before the test finishes"); + test_touchaction.done(); + }); } function enableScrolling() {
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html similarity index 86% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html index 0c900ff..0c88054 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <script src="pointerevent_support.js"></script> <style> #target0 { @@ -111,10 +114,19 @@ } if(xScrollIsReceived && yScrollIsReceived) { - test_touchaction.done(); updateDescriptionComplete(); } }); + + // Inject touch inputs and wait for all the actions finish to end the test. + touchScrollInTarget(target0, 'down').then(function() { + return touchScrollInTarget(target0, 'right'); + }).then(function() { + test_touchaction.step(function () { + assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes"); + }, "x-scroll and y-scroll should be received before the test finishes"); + test_touchaction.done(); + }); } </script> <h1>touch-action: pan-x pan-y</h1>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html new file mode 100644 index 0000000..2556e83 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html
@@ -0,0 +1,109 @@ +<!doctype html> +<html> + <head> + <title>Pointer Events pointer lock tests</title> + <meta name="viewport" content="width=device-width"> + <link rel="stylesheet" type="text/css" href="/external/wpt/pointerevents/pointerevent_styles.css"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> + <script type="text/javascript" src="../pointerevent_support.js"></script> + <style> + #testContainer { + touch-action: none; + user-select: none; + position: relative; + } + </style> + <script> + var last_pointer_client_pos = {'x': 0, 'y': 0} + var last_pointer_screen_pos = {'x': 0, 'y': 0} + + const kStateInit = 0 + const kStateLocked = 1 + const kStateUnlocked = 2. + + var test_state = kStateInit; + + function resetTestState() { + test_state = kStateInit; + document.exitPointerLock(); + } + + function run() { + var test_pointerEvent = setup_pointerevent_test("Test pointerevent coordinates when pointer is locked", ['mouse']); + var div1 = document.getElementById("target"); + + on_event(div1, 'pointerdown', function(event) { + if (test_state == kStateInit) + div1.requestPointerLock(); + }); + on_event(div1, 'pointerup', function(event) { + if (test_state == kStateLocked) + document.exitPointerLock(); + }); + on_event(div1, 'pointermove', function(event) { + if (test_state == kStateLocked) { + test_pointerEvent.step(function() { + assert_equals(last_pointer_client_pos['x'], event.clientX) + assert_equals(last_pointer_client_pos['y'], event.clientY) + assert_equals(last_pointer_screen_pos['x'], event.screenX) + assert_equals(last_pointer_screen_pos['y'], event.screenY) + }); + } else { + last_pointer_client_pos = {'x': event.clientX, 'y': event.clientY} + last_pointer_screen_pos = {'x': event.screenX, 'y': event.screenY} + } + }); + on_event(document, 'pointerlockchange', function(event) { + if (test_state == kStateInit) { + test_state = kStateLocked; + test_pointerEvent.step(function() { + assert_equals(document.pointerLockElement, div1, "document.pointerLockElement should be div1."); + }); + } else if (test_state == kStateLocked) { + test_state = kStateUnlocked; + test_pointerEvent.step(function() { + assert_equals(document.pointerLockElement, null, "document.pointerLockElement should be null."); + }); + test_pointerEvent.done(); + } + }); + + var actions = new test_driver.Actions(); + actions.pointerMove(/* x = */ 0, /* y = */ 0, {origin: target}).pointerDown(); + + pos_x = target.getBoundingClientRect().x + target.offsetWidth / 2; + pos_y = target.getBoundingClientRect().y + target.offsetHeight / 2; + for (var i = 0; i < 10; i++) { + // Alternatively move left/right and up/down. + pos_x += ((-1)**i) * i * 10; + pos_y -= ((-1)**i) * i * 10; + actions.pointerMove(pos_x, pos_y); + } + actions.pointerUp().send(); + } + </script> + </head> + <body onload="run()"> + <h1>Pointer Events movement in locked state test</h1> + <h2 id="pointerTypeDescription"></h2> + <h4> + Test Description: This test checks the pointer event coordinates stays unchanged when pointer is locked. + <ol> + <li>Press left button down on the green rectangle and hold it.</li> + <li>Move the mouse inside the green rectangle.</li> + <li>Release mouse button. </li> + </ol> + </ol> + + Test passes if the proper behavior of the events is observed. + </h4> + <div id="testContainer"> + <div id="target" style="width:800px;height:250px;background:green"></div> + </div> + <div class="spacer"></div> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html b/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html index e2417cb7..0d8ec33 100644 --- a/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html +++ b/third_party/blink/web_tests/external/wpt/portals/portal-activate-data.html
@@ -2,6 +2,8 @@ <title>Tests passing of data along with portal activation</title> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<body> +<canvas id="canvas"></canvas> <script> function nextMessage(target) { return new Promise((resolve, reject) => { @@ -33,6 +35,31 @@ }, "A string can be passed through activate data."); promise_test(async () => { + let aBuff = new ArrayBuffer(5); + let arr = new Int8Array(aBuff); + for (var i = 0; i < 5; i++) + arr[i] = i; + const {array} = await openPortalAndActivate( + 'return {array: Array.prototype.slice.call(new Int8Array(event.data))}', + {data: aBuff, transfer: [aBuff]}); + assert_equals(arr.length, 0); + assert_array_equals(array, [0, 1, 2, 3, 4]); +}, "An array buffer can be transferred through activate data."); + +promise_test(async () => { + let canvas = document.getElementById("canvas"); + let ctx = canvas.getContext("2d"); + ctx.fillStyle = "green"; + ctx.fillRect(0, 0, 150, 100); + let imageBitmap = await createImageBitmap(canvas, 0, 0, 150, 100); + const {height, width} = await openPortalAndActivate( + 'return {height: event.data.height, width: event.data.width}', + {data: imageBitmap, transfer: [imageBitmap]}); + assert_equals(height, 100); + assert_equals(width, 150); +}, "An image bitmap can be transferred through activate data."); + +promise_test(async () => { let {port1, port2} = new MessageChannel(); let replyViaPort = nextMessage(port1); port1.start(); @@ -63,3 +90,4 @@ openPortalAndActivate('', {data: null, transfer: [null]})); }, "Errors during transfer list processing are propagated."); </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/resize-observer/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/resize-observer/idlharness.window-expected.txt index 45105ba..b655335 100644 --- a/third_party/blink/web_tests/external/wpt/resize-observer/idlharness.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/resize-observer/idlharness.window-expected.txt
@@ -1,4 +1,5 @@ This is a testharness.js-based test. +Found 51 tests; 29 PASS, 22 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS ResizeObserverEntry creator PASS ResizeObserver interface: existence and properties of interface object @@ -7,13 +8,13 @@ PASS ResizeObserver interface: existence and properties of interface prototype object PASS ResizeObserver interface: existence and properties of interface prototype object's "constructor" property PASS ResizeObserver interface: existence and properties of interface prototype object's @@unscopables property -PASS ResizeObserver interface: operation observe(Element) +PASS ResizeObserver interface: operation observe(Element, ResizeObserverOptions) PASS ResizeObserver interface: operation unobserve(Element) PASS ResizeObserver interface: operation disconnect() PASS ResizeObserver must be primary interface of observer PASS Stringification of observer -PASS ResizeObserver interface: observer must inherit property "observe(Element)" with the proper type -PASS ResizeObserver interface: calling observe(Element) on observer with too few arguments must throw TypeError +PASS ResizeObserver interface: observer must inherit property "observe(Element, ResizeObserverOptions)" with the proper type +PASS ResizeObserver interface: calling observe(Element, ResizeObserverOptions) on observer with too few arguments must throw TypeError PASS ResizeObserver interface: observer must inherit property "unobserve(Element)" with the proper type PASS ResizeObserver interface: calling unobserve(Element) on observer with too few arguments must throw TypeError PASS ResizeObserver interface: observer must inherit property "disconnect()" with the proper type @@ -25,10 +26,22 @@ PASS ResizeObserverEntry interface: existence and properties of interface prototype object's @@unscopables property PASS ResizeObserverEntry interface: attribute target PASS ResizeObserverEntry interface: attribute contentRect +FAIL ResizeObserverEntry interface: attribute borderBoxSize assert_true: The prototype object must have a property "borderBoxSize" expected true got false +FAIL ResizeObserverEntry interface: attribute contentBoxSize assert_true: The prototype object must have a property "contentBoxSize" expected true got false PASS ResizeObserverEntry must be primary interface of entry PASS Stringification of entry PASS ResizeObserverEntry interface: entry must inherit property "target" with the proper type PASS ResizeObserverEntry interface: entry must inherit property "contentRect" with the proper type +FAIL ResizeObserverEntry interface: entry must inherit property "borderBoxSize" with the proper type assert_inherits: property "borderBoxSize" not found in prototype chain +FAIL ResizeObserverEntry interface: entry must inherit property "contentBoxSize" with the proper type assert_inherits: property "contentBoxSize" not found in prototype chain +FAIL ResizeObserverSize interface: existence and properties of interface object assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface object length assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface object name assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface: existence and properties of interface prototype object assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface: attribute inlineSize assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing +FAIL ResizeObserverSize interface: attribute blockSize assert_own_property: self does not have own property "ResizeObserverSize" expected property "ResizeObserverSize" missing FAIL ResizeObservation interface: existence and properties of interface object assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing FAIL ResizeObservation interface object length assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing FAIL ResizeObservation interface object name assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing @@ -36,8 +49,7 @@ FAIL ResizeObservation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing FAIL ResizeObservation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing FAIL ResizeObservation interface: attribute target assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing -FAIL ResizeObservation interface: attribute broadcastWidth assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing -FAIL ResizeObservation interface: attribute broadcastHeight assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing -FAIL ResizeObservation interface: operation isActive() assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing +FAIL ResizeObservation interface: attribute observedBox assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing +FAIL ResizeObservation interface: attribute lastReportedSize assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/radialgradient-fully-overlapping.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/radialgradient-fully-overlapping.svg index e16bb4a..5b5f7bd4 100644 --- a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/radialgradient-fully-overlapping.svg +++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/radialgradient-fully-overlapping.svg
@@ -3,14 +3,14 @@ <metadata> <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#RadialGradientNotes"/> <h:link rel="match" href="reference/green-100x100.svg"/> - <h:meta name="assert" content="If the start circle fully overlaps with the end circle, no gradient is drawn."/> + <h:meta name="assert" content="If the start circle fully overlaps with the end circle, the gradient should be drawn."/> </metadata> - <rect width="100" height="100" fill="green"/> + <rect width="100" height="100" fill="red"/> <radialGradient id="fully_overlapping" r="100" fr="100"> - <stop stop-color="red"/> - <stop stop-color="red" offset="1"/> + <stop stop-color="green"/> + <stop stop-color="green" offset="1"/> </radialGradient> <rect width="100" height="100" fill="url(#fully_overlapping) orange"/> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml b/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml index 17fca51..8076bc3 100644 --- a/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml +++ b/third_party/blink/web_tests/external/wpt/tools/ci/azure/affected_tests.yml
@@ -16,7 +16,7 @@ - template: install_safari.yml - template: update_hosts.yml - template: update_manifest.yml -- script: no_proxy='*' ./wpt run --yes --no-pause --no-fail-on-unexpected --no-restart-on-unexpected --affected ${{ parameters.affectedRange }} --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report.json --channel preview safari +- script: no_proxy='*' ./wpt run --yes --no-pause --no-fail-on-unexpected --no-restart-on-unexpected --affected ${{ parameters.affectedRange }} --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report.json --log-wptscreenshot $(Build.ArtifactStagingDirectory)/wpt_screenshot.txt --channel preview safari displayName: 'Run tests' - task: PublishBuildArtifacts@1 displayName: 'Publish results'
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py index e2e35d7..90655da 100644 --- a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py +++ b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
@@ -421,11 +421,11 @@ __load_cache = {} -def _load(logger, tests_root, manifest, types=None, meta_filters=None): +def _load(logger, tests_root, manifest, types=None, meta_filters=None, allow_cached=True): # "manifest" is a path or file-like object. manifest_path = (manifest if isinstance(manifest, string_types) else manifest.name) - if manifest_path in __load_cache: + if allow_cached and manifest_path in __load_cache: return __load_cache[manifest_path] if isinstance(manifest, string_types): @@ -450,7 +450,8 @@ types=types, meta_filters=meta_filters) - __load_cache[manifest_path] = rv + if allow_cached: + __load_cache[manifest_path] = rv return rv @@ -464,7 +465,8 @@ working_copy=False, types=None, meta_filters=None, - write_manifest=True): + write_manifest=True, + allow_cached=True): logger = get_logger() manifest = None @@ -474,7 +476,8 @@ tests_root, manifest_path, types=types, - meta_filters=meta_filters) + meta_filters=meta_filters, + allow_cached=allow_cached) except ManifestVersionMismatch: logger.info("Manifest version changed, rebuilding")
diff --git a/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.0.txt b/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.0.txt index 6f9a7714d..abaa830 100644 --- a/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.0.txt +++ b/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.0.txt
@@ -10,7 +10,7 @@ (on windows and linux), ini-file parsing and a lazy import mechanism. It runs unmodified on all Python interpreters compatible to Python2.4 up until Python 3.2. The general goal with "py" is to provide stable APIs -for some common tasks that are continously tested against many Python +for some common tasks that are continuously tested against many Python interpreters and thus also to help transition. Here are some docs: http://pylib.org @@ -20,7 +20,7 @@ as "pytest-2.0.0", see here for the revamped docs: http://pytest.org - + And "py.cleanup|py.lookup|py.countloc" etc. helpers are now part of the pycmd distribution, see http://pypi.python.org/pypi/pycmd
diff --git a/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.1.txt b/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.1.txt index a5aa76b..b37a148a 100644 --- a/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.1.txt +++ b/third_party/blink/web_tests/external/wpt/tools/third_party/py/doc/announce/release-1.4.1.txt
@@ -11,7 +11,7 @@ (on windows and linux), ini-file parsing and a lazy import mechanism. It runs unmodified on all Python interpreters compatible to Python2.4 up until Python 3.2, PyPy and Jython. The general goal with "py" is to -provide stable APIs for some common tasks that are continously tested +provide stable APIs for some common tasks that are continuously tested against many Python interpreters and thus also to help transition. Here are some docs: @@ -21,7 +21,7 @@ comes as its own separate "pytest" distribution, see: http://pytest.org - + Also, the "py.cleanup|py.lookup|py.countloc" helpers are now part of the pycmd distribution, see http://pypi.python.org/pypi/pycmd
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt deleted file mode 100644 index 6f066d2..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -This is a testharness.js-based test. -PASS Missing arguments -PASS Branding -PASS Zero initial -PASS Zero initial with valueOf -PASS Non-zero initial -PASS Zero initial with respected maximum -PASS Zero initial with respected maximum grown twice -PASS Zero initial growing too much -PASS Out-of-range argument: undefined -PASS Out-of-range argument: NaN -PASS Out-of-range argument: Infinity -PASS Out-of-range argument: -Infinity -PASS Out-of-range argument: -1 -PASS Out-of-range argument: 4294967296 -PASS Out-of-range argument: 68719476736 -PASS Out-of-range argument: "0x100000000" -PASS Out-of-range argument: object "[object Object]" -PASS Stray argument -FAIL Growing shared memory does not detach old buffer WebAssembly.Memory.grow(): Unable to grow instance memory. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt deleted file mode 100644 index 6f066d2..0000000 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/grow.any.worker-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -This is a testharness.js-based test. -PASS Missing arguments -PASS Branding -PASS Zero initial -PASS Zero initial with valueOf -PASS Non-zero initial -PASS Zero initial with respected maximum -PASS Zero initial with respected maximum grown twice -PASS Zero initial growing too much -PASS Out-of-range argument: undefined -PASS Out-of-range argument: NaN -PASS Out-of-range argument: Infinity -PASS Out-of-range argument: -Infinity -PASS Out-of-range argument: -1 -PASS Out-of-range argument: 4294967296 -PASS Out-of-range argument: 68719476736 -PASS Out-of-range argument: "0x100000000" -PASS Out-of-range argument: object "[object Object]" -PASS Stray argument -FAIL Growing shared memory does not detach old buffer WebAssembly.Memory.grow(): Unable to grow instance memory. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt index 1e7eedfb..e15f9c4 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 216 tests; 201 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 216 tests; 202 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Navigator: original interface defined PASS Partial dictionary WebGLContextAttributes: original dictionary defined @@ -27,7 +27,6 @@ PASS XRSession interface: existence and properties of interface prototype object's "constructor" property PASS XRSession interface: existence and properties of interface prototype object's @@unscopables property PASS XRSession interface: attribute mode -FAIL XRSession interface: attribute outputContext assert_true: The prototype object must have a property "outputContext" expected true got false PASS XRSession interface: attribute environmentBlendMode PASS XRSession interface: attribute renderState PASS XRSession interface: attribute viewerSpace @@ -53,6 +52,7 @@ PASS XRRenderState interface: attribute depthNear PASS XRRenderState interface: attribute depthFar PASS XRRenderState interface: attribute baseLayer +PASS XRRenderState interface: attribute outputContext PASS XRFrame interface: existence and properties of interface object PASS XRFrame interface object length PASS XRFrame interface object name
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-automation.js deleted file mode 100644 index fe24736..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-automation.js deleted file mode 100644 index c46cb0a..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-automation.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down'); -} - -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-automation.js deleted file mode 100644 index fe24736..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-automation.js deleted file mode 100644 index fe24736..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-automation.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down'); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-automation.js deleted file mode 100644 index f3e2b84a..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-automation.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down').then(function() { - return touchScrollInTarget('#target0', 'right'); - }); -} -
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js deleted file mode 100644 index 1c006c4..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#scrollTarget', 'down').then(function() { - return touchScrollInTarget('#scrollTarget', 'right'); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-automation.js deleted file mode 100644 index 4a2a9a4..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-automation.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return touchScrollInTarget('#target0', 'down').then(function() { - return touchScrollInTarget('#target0', 'right'); - }); -}
diff --git a/third_party/blink/web_tests/fast/css/font-face-local-file.html b/third_party/blink/web_tests/fast/css/font-face-local-file.html index dcf64225..150b170 100644 --- a/third_party/blink/web_tests/fast/css/font-face-local-file.html +++ b/third_party/blink/web_tests/fast/css/font-face-local-file.html
@@ -4,7 +4,6 @@ description('Local fonts should not be rejected by CORS'); if (window.testRunner) { - testRunner.setAllowUniversalAccessFromFileURLs(false); testRunner.setAllowFileAccessFromFileURLs(false); } window.jsTestIsAsync = true;
diff --git a/third_party/blink/web_tests/fast/dnd/cancel-dragging-outside-page.html b/third_party/blink/web_tests/fast/dnd/cancel-dragging-outside-page.html index dcc667a31..239c555 100644 --- a/third_party/blink/web_tests/fast/dnd/cancel-dragging-outside-page.html +++ b/third_party/blink/web_tests/fast/dnd/cancel-dragging-outside-page.html
@@ -15,8 +15,8 @@ <script> if (window.eventSender) { - test( () => { - const draggable_link = document.querySelector("#target"); + test(() => { + const draggable_link = document.querySelector('#target'); const clientRect = draggable_link.getBoundingClientRect(); const centerX = (clientRect.left + clientRect.right) / 2; @@ -25,6 +25,6 @@ eventSender.mouseDown(); eventSender.mouseMoveTo(centerX+200, centerY+200); eventSender.mouseLeave(); - }, "The renderer should not crash"); + }, 'The renderer should not crash'); } </script>
diff --git a/third_party/blink/web_tests/fast/dnd/file-drag-over-page-cancel.html b/third_party/blink/web_tests/fast/dnd/file-drag-over-page-cancel.html index cf083d04..0299368 100644 --- a/third_party/blink/web_tests/fast/dnd/file-drag-over-page-cancel.html +++ b/third_party/blink/web_tests/fast/dnd/file-drag-over-page-cancel.html
@@ -41,9 +41,7 @@ eventSender.mouseMoveTo(centerX, centerY); // dragleave on #dropwrapper - setTimeout(() => { - eventSender.keyDown("Escape"); - }, 0); + setTimeout(() => { eventSender.keyDown('Escape'); }, 0); } promise_test(() => {
diff --git a/third_party/blink/web_tests/fast/dnd/resources/drag-trigger-dom-move.js b/third_party/blink/web_tests/fast/dnd/resources/drag-trigger-dom-move.js index 2693529..920fa9a4 100644 --- a/third_party/blink/web_tests/fast/dnd/resources/drag-trigger-dom-move.js +++ b/third_party/blink/web_tests/fast/dnd/resources/drag-trigger-dom-move.js
@@ -1,4 +1,4 @@ -'use strict' +'use strict'; /** Moves the mouse to the center of |element|. */ const mouseMoveToCenter = element => { @@ -116,7 +116,7 @@ else if (testCase.action == 'appendChild') movedItemDestination.appendChild(movedItem); else - return reject("Error: Invalid testCase.action. Please make sure the testCase is spelled correctly"); + return reject('Error: Invalid testCase.action. Please make sure the testCase is spelled correctly'); // Click to resolve test as backup in case dragend never triggers to // end the test.
diff --git a/third_party/blink/web_tests/fast/dnd/resources/dropEffect-common.js b/third_party/blink/web_tests/fast/dnd/resources/dropEffect-common.js index 0cf52284..08082cac 100644 --- a/third_party/blink/web_tests/fast/dnd/resources/dropEffect-common.js +++ b/third_party/blink/web_tests/fast/dnd/resources/dropEffect-common.js
@@ -1,3 +1,5 @@ +'use strict'; + const mouseMoveToCenter = element => { const clientRect = element.getBoundingClientRect(); const centerX = (clientRect.left + clientRect.right) / 2;
diff --git a/third_party/blink/web_tests/fast/dnd/resources/event-mouse-coordinates.js b/third_party/blink/web_tests/fast/dnd/resources/event-mouse-coordinates.js index 5dab8c7..6dac2cd 100644 --- a/third_party/blink/web_tests/fast/dnd/resources/event-mouse-coordinates.js +++ b/third_party/blink/web_tests/fast/dnd/resources/event-mouse-coordinates.js
@@ -1,3 +1,5 @@ +'use strict'; + // The mouse bot will always be precise. Humans can click anywhere in the boxes. const epsilon = (window.eventSender) ? 0 : 50;
diff --git a/third_party/blink/web_tests/fast/dnd/resources/link-dragging-common.js b/third_party/blink/web_tests/fast/dnd/resources/link-dragging-common.js index ab815ac..cf45ad3 100644 --- a/third_party/blink/web_tests/fast/dnd/resources/link-dragging-common.js +++ b/third_party/blink/web_tests/fast/dnd/resources/link-dragging-common.js
@@ -1,3 +1,5 @@ +'use strict'; + const mouseMoveToCenter = (element) => { const clientRect = element.getBoundingClientRect(); const centerX = (clientRect.left + clientRect.right) / 2; @@ -10,7 +12,7 @@ let dragStartEffect = null; let dragStartUriList = null; let dragStartTypes = null; - let dragSource = null; + let dragStartTarget = null; // Enables the Ahem font, which makes the drag image platform-independent. if (window.testRunner)
diff --git a/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-body-quirk.html b/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-body-quirk.html index 9e64a7b..e59d797 100644 --- a/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-body-quirk.html +++ b/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-body-quirk.html
@@ -32,7 +32,7 @@ <body style="padding: 9px; margin: 10px" onload="test()"> <pre id="console"></pre> - <iframe name="static" src='data:text/html, + <iframe name="static" srcdoc=' <body style="padding: 9px; margin: 10px; outline: thin solid blue;"> <div id="target" style="padding: 6px; margin: 8px; outline: thin solid green;"></div> </body> @@ -41,7 +41,7 @@ <br> - <iframe name="relative" src='data:text/html, + <iframe name="relative" srcdoc=' <body style="position: relative; left: 12px; width: 150px; padding: 9px; margin: 10px; outline: thin solid blue;"> <div id="target" style="padding: 6px; margin: 8px; outline: thin solid green;"></div> </body> @@ -50,7 +50,7 @@ <br> - <iframe name="fixed" src='data:text/html, + <iframe name="fixed" srcdoc=' <body style="position: fixed; left: 12px; padding: 9px; margin: 10px; outline: thin solid blue;"> <div id="target" style="padding: 6px; margin: 8px; outline: thin solid green;"></div> </body> @@ -59,7 +59,7 @@ <br> - <iframe name="absolute" src='data:text/html, + <iframe name="absolute" srcdoc=' <body style="position: absolute; left: 12px; padding: 9px; margin: 10px; outline: thin solid blue;"> <div id="target" style="padding: 6px; margin: 8px; outline: thin solid green;"></div> </body>
diff --git a/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-html.html b/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-html.html index 27e1192..4b3145be 100644 --- a/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-html.html +++ b/third_party/blink/web_tests/fast/dom/Element/offsetLeft-offsetTop-html.html
@@ -30,13 +30,13 @@ <body style="padding: 9px; margin: 10px" onload="test()"> <pre id="console"></pre> - <iframe name="control" src='data:text/html, + <iframe name="control" srcdoc=' <html id="target"></html> '> </iframe> <br> - <iframe name="static" src='data:text/html, + <iframe name="static" srcdoc=' <html id="target" style="padding: 10px; margin: 10px; border: 10px solid blue;"> </html> '> @@ -44,7 +44,7 @@ <br> - <iframe name="absolute" src='data:text/html, + <iframe name="absolute" srcdoc=' <html id="target" style="position: absolute; left: 20px; top: 10px; width: 40px; height: 40px; padding: 10px; margin: 0px; border: 10px solid blue"> </html> '>
diff --git a/third_party/blink/web_tests/fast/dom/HTMLElement/iscontenteditable-designmodeon-subframe.html b/third_party/blink/web_tests/fast/dom/HTMLElement/iscontenteditable-designmodeon-subframe.html index 7317e12..ec373a0 100644 --- a/third_party/blink/web_tests/fast/dom/HTMLElement/iscontenteditable-designmodeon-subframe.html +++ b/third_party/blink/web_tests/fast/dom/HTMLElement/iscontenteditable-designmodeon-subframe.html
@@ -22,6 +22,6 @@ document.getElementById("subframe").style.display= 'none'; } </script> -<iframe id="subframe" onload="runTest()" src="data:text/html,<div id='div'></div>"></iframe> +<iframe id="subframe" onload="runTest()" srcdoc="<div id='div'></div>"></iframe> </body> </html>
diff --git a/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node-link.html b/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node-link.html index 3352302..5a981e2 100644 --- a/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node-link.html +++ b/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node-link.html
@@ -19,4 +19,4 @@ }; </script> -<iframe src="data:text/html,<link rel='stylesheet' href='data:text/css,*{}'>"></iframe> +<iframe srcdoc="<link rel='stylesheet' href='data:text/css,*{}'>"></iframe>
diff --git a/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node.html b/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node.html index 834b31b..4872dba6 100644 --- a/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node.html +++ b/third_party/blink/web_tests/fast/dom/StyleSheet/detached-sheet-owner-node.html
@@ -19,4 +19,4 @@ }; </script> -<iframe src="data:text/html,<style>*{}</style>"></iframe> +<iframe srcdoc="<style>*{}</style>"></iframe>
diff --git a/third_party/blink/web_tests/fast/dom/clientWidthAfterDocumentIsRemoved.html b/third_party/blink/web_tests/fast/dom/clientWidthAfterDocumentIsRemoved.html index e04bfba..7299a1cf 100644 --- a/third_party/blink/web_tests/fast/dom/clientWidthAfterDocumentIsRemoved.html +++ b/third_party/blink/web_tests/fast/dom/clientWidthAfterDocumentIsRemoved.html
@@ -1,7 +1,7 @@ <p>This test passes if it doesn't crash!</p> <iframe id="onlybear" - src="data:text/html, <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/html4/strict.dtd'><html></html>" + srcdoc="<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/html4/strict.dtd'><html></html>" > </iframe>
diff --git a/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-iframes.html b/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-iframes.html index 812a45b..54eb7756 100644 --- a/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-iframes.html +++ b/third_party/blink/web_tests/fast/dom/elementsFromPoint/elementsFromPoint-iframes.html
@@ -24,8 +24,8 @@ overflow-x: scroll; } </style> -<iframe id="iframe" src="data:text/html,<div id='div' style='width: 100px; height: 100px; background: red'></div>"></iframe> -<iframe id="iframeScrollbars" src="data:text/html,<div id='big' style='width: 500px; height: 500px; background: blue;'></div><div id='div' style='position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: green;'>"></iframe> +<iframe id="iframe" srcdoc="<div id='div' style='width: 100px; height: 100px; background: red'></div>"></iframe> +<iframe id="iframeScrollbars" srcdoc="<div id='big' style='width: 500px; height: 500px; background: blue;'></div><div id='div' style='position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: green;'>"></iframe> <div id="console"></div> <script> window.jsTestIsAsync = true; @@ -50,4 +50,4 @@ finishJSTest(); } -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/fast/dom/gc-6.html b/third_party/blink/web_tests/fast/dom/gc-6.html index df27698..ec6e738 100644 --- a/third_party/blink/web_tests/fast/dom/gc-6.html +++ b/third_party/blink/web_tests/fast/dom/gc-6.html
@@ -20,6 +20,7 @@ var frame = document.getElementById("frame"); spanB = frame.contentDocument.getElementById("span-B"); spanB.customProperty = "B"; + frame.srcdoc = ""; frame.onload = frameLoaded; frame.src = "about:blank"; } @@ -48,5 +49,5 @@ <div id="output"> </div> -<iframe id="frame" src='data:text/html,<div id="div"><span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span></div>'> +<iframe id="frame" srcdoc='<div id="div"><span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span></div>'> </body>
diff --git a/third_party/blink/web_tests/fast/dom/gc-7.html b/third_party/blink/web_tests/fast/dom/gc-7.html index 4f471b8..65780e8 100644 --- a/third_party/blink/web_tests/fast/dom/gc-7.html +++ b/third_party/blink/web_tests/fast/dom/gc-7.html
@@ -22,8 +22,9 @@ frameDoc = frame.contentDocument; spanB = frame.contentDocument.getElementById("span-B"); spanB.customProperty = "B"; + frame.srcdoc = ""; frame.onload = frameLoaded; - frame.src = 'about:blank' + frame.src = "about:blank"; } if (window.testRunner) { @@ -50,5 +51,5 @@ <div id="output"> </div> -<iframe id="frame" src='data:text/html,<div id="div"><span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span></div>'> +<iframe id="frame" srcdoc='<div id="div"><span id="span-A"><span id="span-B"><span id="span-C">original span</span></span></span></div>'> </body>
diff --git a/third_party/blink/web_tests/fast/dom/resources/constructors-cached-navigate.js b/third_party/blink/web_tests/fast/dom/resources/constructors-cached-navigate.js index 23dd840..98b98ce 100644 --- a/third_party/blink/web_tests/fast/dom/resources/constructors-cached-navigate.js +++ b/third_party/blink/web_tests/fast/dom/resources/constructors-cached-navigate.js
@@ -47,7 +47,8 @@ if (window.testRunner) testRunner.notifyDone(); }; - testFrame.src = 'data:text/html,<script>var constructors = ["Image", "MessageChannel", "Option", "XMLHttpRequest", "Audio"];' - + 'for(var i = 0; i < constructors.length; i++) if(window[constructors[i]])' - + 'window[constructors[i]].cachedOnOwnerDocument = true;</script>'; + testFrame.srcdoc = + '<script>var constructors = ["Image", "MessageChannel", "Option", "XMLHttpRequest", "Audio"];' + + 'for(var i = 0; i < constructors.length; i++) if(window[constructors[i]])' + + 'window[constructors[i]].cachedOnOwnerDocument = true;</script>'; }
diff --git a/third_party/blink/web_tests/fast/dom/root-client-size-iframe.html b/third_party/blink/web_tests/fast/dom/root-client-size-iframe.html index 915a0f9..dbf1a33 100644 --- a/third_party/blink/web_tests/fast/dom/root-client-size-iframe.html +++ b/third_party/blink/web_tests/fast/dom/root-client-size-iframe.html
@@ -4,7 +4,7 @@ iframe { width: 100px; height: 100px; } iframe.wider { width: 200px; } </style> -<iframe id="frame" src="data:text/html,<!DOCTYPE html>iframe" onload="runTests()"></iframe> +<iframe id="frame" srcdoc="<!DOCTYPE html>iframe" onload="runTests()"></iframe> <script> description("Style recalc/layout when reading clientWidth of documentElement in iframe.");
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html b/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html index 7063a0a..8df3af5c 100644 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/date-picker-ax.html
@@ -7,8 +7,7 @@ <script src="resources/calendar-picker-common.js"></script> </head> <body> -<p id="description"></p> -<div id="console"></div> + <input type="date" id="date1" value="2000-01-02"> <script> @@ -18,10 +17,10 @@ accessibilityController.setNotificationListener(function(axnode, type) { if (type == 'Focus') { - console.log('Focused: ' + escapeHTML(accessibilityController.focusedElement.name.replace(/,/g, ''))); + console.log('Focused: ' + accessibilityController.focusedElement.name.replace(/,/g, '')); } else if (type == 'MarkDirty') { if (++markDirtyCounter == 2) { - testButtonDescription(); + setTimeout(testButtonDescription, 0); } else if (markDirtyCounter == 3) { // Highlight 2000-02 in the month popup. setTimeout(function() { eventSender.keyDown('ArrowRight'); }, 0);
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax-expected.txt b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax-expected.txt deleted file mode 100644 index c462e39..0000000 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -Focused -Focused -PASS Received MarkDirty -PASS Received MarkDirty -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax.html b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax.html index 13a8921..e2f9fbad 100644 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax.html +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-ax.html
@@ -1,32 +1,39 @@ <!DOCTYPE html> <html> +<head> + <script src="../../../resources/testharness.js"></script> + <script src="../../../resources/testharnessreport.js"></script> + <script src="../../forms/resources/picker-common.js"></script> + <script src="resources/calendar-picker-common.js"></script> +</head> + <body> -<script src="../../../resources/js-test.js"></script> -<script src="../../forms/resources/picker-common.js"></script> -<script src="resources/calendar-picker-common.js"></script> -<p id="description"></p> -<div id="console"></div> <input type="month" id="month1" value="2000-01"> <script> -description('Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events.'); +async_test((t) => { + var markDirtyCounter = 0; + var focusCounter = 0; + accessibilityController.setNotificationListener(function(axnode, type) { + if (type == 'Focus') { + console.log('Focused: ' + accessibilityController.focusedElement.name.replace(/,/g, '')); + focusCounter++; + } else if (type == 'MarkDirty') { + console.log('Received MarkDirty'); + markDirtyCounter++; + if (focusCounter == 2 && markDirtyCounter == 2) { + t.done(); + } + } + }); -accessibilityController.setNotificationListener(function(axnode, type) { - if (type == 'Focus') { - debug('Focused'); - } else if (type == 'MarkDirty') { - testPassed('Received MarkDirty'); - if (++markDirtyCounter == 2) - finishJSTest(); + var month1 = document.getElementById('month1'); + function test1() { + eventSender.keyDown('ArrowDown'); } -}); -var markDirtyCounter = 0; -var month1 = document.getElementById('month1'); -openPicker(month1, test1); -function test1() { - eventSender.keyDown('ArrowRight'); -} + openPicker(month1, test1); +}, 'Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events.'); </script> </body>
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax-expected.txt b/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax-expected.txt deleted file mode 100644 index c462e39..0000000 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -Focused -Focused -PASS Received MarkDirty -PASS Received MarkDirty -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax.html b/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax.html index aeef1f7..1b3172f 100644 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax.html +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/week-picker-ax.html
@@ -1,32 +1,41 @@ <!DOCTYPE html> <html> +<head> + <script src="../../../resources/testharness.js"></script> + <script src="../../../resources/testharnessreport.js"></script> + <script src="../../forms/resources/picker-common.js"></script> + <script src="resources/calendar-picker-common.js"></script> +</head> + <body> -<script src="../../../resources/js-test.js"></script> -<script src="../../forms/resources/picker-common.js"></script> -<script src="resources/calendar-picker-common.js"></script> -<p id="description"></p> -<div id="console"></div> <input type="week" id="week1" value="2000-W13"> <script> -description('Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events.'); +async_test((t) => { + var markDirtyCounter = 0; + var focusCounter = 0; + accessibilityController.setNotificationListener(function(axnode, type) { + if (type == 'Focus') { + console.log('Focused: ' + accessibilityController.focusedElement.name.replace(/,/g, '')); + focusCounter++; + } else if (type == 'MarkDirty') { + console.log('Received MarkDirty'); + markDirtyCounter++; + if (focusCounter == 2 && markDirtyCounter == 2) { + t.done(); + } + } + }); -accessibilityController.setNotificationListener(function(axnode, type) { - if (type == 'Focus') { - debug('Focused'); - } else if (type == 'MarkDirty') { - testPassed('Received MarkDirty'); - if (++markDirtyCounter == 2) - finishJSTest(); + var week1 = document.getElementById('week1'); + function test1() { + eventSender.keyDown('ArrowDown'); } -}); -var markDirtyCounter = 0; -var week1 = document.getElementById('week1'); -openPicker(week1, test1); -function test1() { - eventSender.keyDown('ArrowDown'); -} + openPicker(week1, test1); +}, 'Tests if typing an arrow key dispatches |Focus| and |MarkDirty| a11y events.'); + + </script> </body>
diff --git a/third_party/blink/web_tests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-ax-value-changed-notification.html b/third_party/blink/web_tests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-ax-value-changed-notification.html index 7026b596..255b11e 100644 --- a/third_party/blink/web_tests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-ax-value-changed-notification.html +++ b/third_party/blink/web_tests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-ax-value-changed-notification.html
@@ -13,12 +13,12 @@ [ "Focus", "Month", "10" ], [ "Focus", "Day", "09" ], [ "Focus", "Year", "2012" ], + [ "ValueChanged", "Day", "04" ], + [ "ValueChanged", "Day", "04" ], + [ "ValueChanged", "Year", "2013" ], + [ "ValueChanged", "Year", "2013" ], [ "Focus", "Hours", "12" ], [ "Focus", "Minutes", "34" ], - [ "ValueChanged", "Day", "04" ], - [ "ValueChanged", "Day", "04" ], - [ "ValueChanged", "Year", "2013" ], - [ "ValueChanged", "Year", "2013" ], [ "ValueChanged", "Hours", "02" ], [ "ValueChanged", "Hours", "02" ], [ "ValueChanged", "Minutes", "33" ], @@ -29,8 +29,6 @@ t.step_func((element, notification) => { if (notification == 'Focus' || notification == 'ValueChanged') { var next_expectation = expected.shift(); - console.log('next_expectation: ' + JSON.stringify(next_expectation)); - console.log('actual: [' + notification + ', ' + element.name.trim() + ', ' + element.valueDescription.substr(20) + ']'); assert_equals(notification, next_expectation[0]); assert_equals(element.name.trim(), next_expectation[1]); assert_equals(element.valueDescription.substr(20), next_expectation[2]);
diff --git a/third_party/blink/web_tests/fast/forms/label/continous-click-on-label.html b/third_party/blink/web_tests/fast/forms/label/continous-click-on-label.html index 076814e..7278ae8 100644 --- a/third_party/blink/web_tests/fast/forms/label/continous-click-on-label.html +++ b/third_party/blink/web_tests/fast/forms/label/continous-click-on-label.html
@@ -24,16 +24,16 @@ shouldBeFalse('checkbox.checked'); debug('The checkbox should be checked after three clicks'); -testWithContinousClick(span, 3); +testWithContinuousClick(span, 3); shouldBeTrue('checkbox.checked'); debug('Checkbox should still be checked after ten clicks'); -testWithContinousClick(span, 10); +testWithContinuousClick(span, 10); shouldBeTrue('checkbox.checked'); checkbox.style.display = 'none'; -function testWithContinousClick(element, number) +function testWithContinuousClick(element, number) { eventSender.mouseMoveTo(element.offsetLeft, element.offsetTop); for (n = 0; n < number; ++n) {
diff --git a/third_party/blink/web_tests/fast/forms/month-multiple-fields/month-multiple-fields-ax-value-changed-notification.html b/third_party/blink/web_tests/fast/forms/month-multiple-fields/month-multiple-fields-ax-value-changed-notification.html index 9d99741..4849cb3 100644 --- a/third_party/blink/web_tests/fast/forms/month-multiple-fields/month-multiple-fields-ax-value-changed-notification.html +++ b/third_party/blink/web_tests/fast/forms/month-multiple-fields/month-multiple-fields-ax-value-changed-notification.html
@@ -12,6 +12,8 @@ var expected = [ [ "Focus", "Month", "October" ], [ "Focus", "Year", "2012" ], + [ "ValueChanged", "Year", "0004" ], + [ "ValueChanged", "Year", "0004" ], [ "ValueChanged", "Year", "0005" ], [ "ValueChanged", "Year", "0005" ] ]; @@ -20,8 +22,6 @@ t.step_func((element, notification) => { if (notification == 'Focus' || notification == 'ValueChanged') { var next_expectation = expected.shift(); - console.log('next_expectation: ' + JSON.stringify(next_expectation)); - console.log('actual: [' + notification + ', ' + element.name.trim() + ', ' + element.valueDescription.substr(20) + ']'); assert_equals(notification, next_expectation[0]); assert_equals(element.name.trim(), next_expectation[1]); assert_equals(element.valueDescription.substr(20), next_expectation[2]);
diff --git a/third_party/blink/web_tests/fast/forms/time-multiple-fields/time-multiple-fields-ax-value-changed-notification.html b/third_party/blink/web_tests/fast/forms/time-multiple-fields/time-multiple-fields-ax-value-changed-notification.html index 7ac02605..59b833e8 100644 --- a/third_party/blink/web_tests/fast/forms/time-multiple-fields/time-multiple-fields-ax-value-changed-notification.html +++ b/third_party/blink/web_tests/fast/forms/time-multiple-fields/time-multiple-fields-ax-value-changed-notification.html
@@ -12,6 +12,8 @@ var expected = [ [ "Focus", "Hours", "12" ], [ "Focus", "Minutes", "34" ], + [ "ValueChanged", "Minutes", "04" ], + [ "ValueChanged", "Minutes", "04" ], [ "ValueChanged", "Minutes", "05" ], [ "ValueChanged", "Minutes", "05" ] ]; @@ -19,8 +21,6 @@ t.step_func((element, notification) => { if (notification == 'Focus' || notification == 'ValueChanged') { var next_expectation = expected.shift(); - console.log('next_expectation: ' + JSON.stringify(next_expectation)); - console.log('actual: [' + notification + ', ' + element.name.trim() + ', ' + element.valueDescription.substr(20) + ']'); assert_equals(notification, next_expectation[0]); assert_equals(element.name.trim(), next_expectation[1]); assert_equals(element.valueDescription.substr(20), next_expectation[2]);
diff --git a/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-ax-value-changed-notification.html b/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-ax-value-changed-notification.html index 9b8280d..a72e6da3 100644 --- a/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-ax-value-changed-notification.html +++ b/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-ax-value-changed-notification.html
@@ -12,6 +12,8 @@ var expected = [ [ "Focus", "Week", "10" ], [ "Focus", "Year", "2012" ], + [ "ValueChanged", "Year", "0004" ], + [ "ValueChanged", "Year", "0004" ], [ "ValueChanged", "Year", "0005" ], [ "ValueChanged", "Year", "0005" ] ]; @@ -19,8 +21,6 @@ t.step_func((element, notification) => { if (notification == 'Focus' || notification == 'ValueChanged') { var next_expectation = expected.shift(); - console.log('next_expectation: ' + JSON.stringify(next_expectation)); - console.log('actual: [' + notification + ', ' + element.name.trim() + ', ' + element.valueDescription.substr(20) + ']'); assert_equals(notification, next_expectation[0]); assert_equals(element.name.trim(), next_expectation[1]); assert_equals(element.valueDescription.substr(20), next_expectation[2]);
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html index 3f7d8fc..9719b6a6e 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html +++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #targetDiv { width: 200px; @@ -30,13 +31,6 @@ var rect = target_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollLeft() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "left"); -} - -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up"); -} var overscrolled_x_delta = 0; var overscrolled_y_delta = 0; @@ -49,26 +43,48 @@ } document.addEventListener("overscroll", onOverscroll); -promise_test (async (t) => { - // Make sure that no overscroll event is sent to target_div. - target_div.addEventListener("overscroll", - t.unreached_func("target_div got unexpected overscroll event.")); - +async function test_overscroll_event_fire(source_device, + precise_scrolling_delta) { await waitForCompositorCommit(); - - // Scroll left on target div and wait for the doc to get overscroll event. - await scrollLeft(); - await waitFor(() => { return overscrolled_x_delta < 0; }, - 'Document did not receive overscroll event after scroll left on target.'); - assert_equals(target_div.scrollLeft, 0); - overscrolled_x_delta = 0; overscrolled_y_delta = 0; // Scroll up on target div and wait for the doc to get overscroll event. - await scrollUp(); + await scrollUp(source_device, precise_scrolling_delta); await waitFor(() => { return overscrolled_y_delta < 0; }, 'Document did not receive overscroll event after scroll up on target.'); assert_equals(target_div.scrollTop, 0); -}, 'Tests that the document gets overscroll event when no element scrolls.'); + + // Scroll left on target div and wait for the doc to get overscroll event. + await scrollLeft(source_device, precise_scrolling_delta); + await waitFor(() => { return overscrolled_x_delta < 0; }, + 'Document did not receive overscroll event after scroll left on target.'); + assert_equals(target_div.scrollLeft, 0); +} + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to target_div. + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + false /* precise_scrolling_delta */); +}, 'Tests that the document gets overscroll event when no element scrolls ' + + 'after wheel scrolling in smooth-scrolling path.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to target_div. + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + true /* precise_scrolling_delta */); +}, 'Tests that the document gets overscroll event when no element scrolls ' + + 'after non-animated wheel scrolling.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to target_div. + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the document gets overscroll event when no element scrolls ' + + 'after touch scrolling.'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html index 1ef5dfd9..0c27d32 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html +++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #overscrollXDiv { width: 600px; @@ -49,13 +50,6 @@ var rect = target_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollLeft() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "left"); -} - -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up"); -} var overscrolled_x_delta = 0; var overscrolled_y_delta = 0; @@ -74,33 +68,58 @@ document.getElementById('overscrollYDiv'). addEventListener("overscroll", onOverscrollY); +async function test_overscroll_event_fire(source_device, + precise_scrolling_delta ) { + overscrolled_x_delta = 0; + overscrolled_y_delta = 0; + await waitForCompositorCommit(); + + // Scroll up on target div and wait for the element with overscroll-y to get + // overscroll event. + await scrollUp(source_device, precise_scrolling_delta); + await waitFor(() => { return overscrolled_y_delta < 0; }, + 'Expected element did not receive overscroll event after scroll up on ' + + 'target.'); + assert_equals(target_div.scrollTop, 0); + + // Scroll left on target div and wait for the element with overscroll-x to + // get overscroll event. + await scrollLeft(source_device, precise_scrolling_delta); + await waitFor(() => { return overscrolled_x_delta < 0; }, + 'Expected element did not receive overscroll event after scroll left ' + + 'on target.'); + assert_equals(target_div.scrollLeft, 0); +} + promise_test (async (t) => { // Make sure that no overscroll event is sent to document or target_div. document.addEventListener("overscroll", t.unreached_func("Document got unexpected overscroll event.")); target_div.addEventListener("overscroll", t.unreached_func("target_div got unexpected overscroll event.")); - - await waitForCompositorCommit(); - - // Scroll left on target div and wait for the element with overscroll-x to - // get overscroll event. - await scrollLeft(); - await waitFor(() => { return overscrolled_x_delta < 0; }, - 'Expected element did not receive overscroll event after scroll left ' + - 'on target.'); - assert_equals(target_div.scrollLeft, 0); - - overscrolled_x_delta = 0; - overscrolled_y_delta = 0; - - // Scroll up on target div and wait for the element with overscroll-y to get - // overscroll event. - await scrollUp(); - await waitFor(() => { return overscrolled_y_delta < 0; }, - 'Expected element did not receive overscroll event after scroll up on ' + - 'target.'); - assert_equals(target_div.scrollTop, 0); + return test_overscroll_event_fire(GestureSourceType.TOUCH_INPUT); }, 'Tests that the last element in the cut scroll chain gets overscroll ' + - 'event when no element scrolls.'); + 'event when no element scrolls by touch.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to document or target_div. + document.addEventListener("overscroll", + t.unreached_func("Document got unexpected overscroll event.")); + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + true /* precise_scrolling_delta */); +}, 'Tests that the last element in the cut scroll chain gets overscroll ' + + 'event when no element scrolls by wheel in non-animated scroll path.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to document or target_div. + document.addEventListener("overscroll", + t.unreached_func("Document got unexpected overscroll event.")); + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + false /* precise_scrolling_delta */); +}, 'Tests that the last element in the cut scroll chain gets overscroll ' + + 'event when no element scrolls by wheel in smooth-scrolling.'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-scrolled-element.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-scrolled-element.html index 534c5d0..84e483e8 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-scrolled-element.html +++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-scrolled-element.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #scrollableDiv { width: 200px; @@ -30,13 +31,6 @@ var rect = scrolling_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollRight() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "right"); -} - -function scrollDown() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "down"); -} var overscrolled_x_delta = 0; var overscrolled_y_delta = 0; @@ -48,15 +42,15 @@ } scrolling_div.addEventListener("overscroll", onOverscroll); -promise_test (async (t) => { - // Make sure that no overscroll event is sent to document. - document.addEventListener("overscroll", - t.unreached_func("Document got unexpected overscroll event.")); - +async function test_overscroll_event_fire(source_device, + precise_scrolling_delta) { + scrolling_div.scrollTo(0, 0); + overscrolled_x_delta = 0; + overscrolled_y_delta = 0; await waitForCompositorCommit(); // Do a horizontal scroll and wait for overscroll event. - await scrollRight(); + await scrollRight(source_device, precise_scrolling_delta); await waitFor(() => { return overscrolled_x_delta > 0; }, 'Scroller did not receive overscroll event after horizontal scroll.'); assert_equals(scrolling_div.scrollWidth - scrolling_div.scrollLeft, @@ -66,10 +60,35 @@ overscrolled_y_delta = 0; // Do a vertical scroll and wait for overscroll event. - await scrollDown(); + await scrollDown(source_device, precise_scrolling_delta); await waitFor(() => { return overscrolled_y_delta > 0; }, 'Scroller did not receive overscroll event after vertical scroll.'); assert_equals(scrolling_div.scrollHeight - scrolling_div.scrollTop, scrolling_div.clientHeight); -}, 'Tests that the scrolled element gets overscroll event after fully scrolling.'); +} + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to document. + document.addEventListener("overscroll", + t.unreached_func("Document got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the scrolled element gets overscroll event after fully scrolling by touch.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to document. + document.addEventListener("overscroll", + t.unreached_func("Document got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + true /* precise_scrolling_delta */); +}, 'Tests that the scrolled element gets overscroll event after fully' + + 'scrolling by non-animating wheel scrolling.'); + +promise_test (async (t) => { + // Make sure that no overscroll event is sent to document. + document.addEventListener("overscroll", + t.unreached_func("Document got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, + false /* precise_scrolling_delta */); +}, 'Tests that the scrolled element gets overscroll event after fully' + + 'scrolling by animated wheel scrolling (smooth-scrolling)'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html index c0da609..eae168b8 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html +++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #targetDiv { width: 200px; @@ -31,29 +32,48 @@ var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up"); -} +var window_received_overscroll = false; -var window_received_autoscroll = false; function onOverscroll(event) { assert_false(event.cancelable); // overscroll events targetting document are bubbled to the window. assert_true(event.bubbles); - window_received_autoscroll = true; + window_received_overscroll = true; } window.addEventListener("overscroll", onOverscroll); +async function test_overscroll_event_fire(source_device, + precise_scroll_deltas) { + window_received_overscroll = false; + await waitForCompositorCommit(); + + // Scroll up on target div and wait for the window to get overscroll event. + await scrollUp(source_device, precise_scroll_deltas); + await waitFor(() => { return window_received_overscroll; }, + 'Window did not receive overscroll event after scroll up on target.'); +} + promise_test (async (t) => { // Make sure that no overscroll event is sent to target_div. target_div.addEventListener("overscroll", t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the window gets overscroll event when no element scrolls' + + 'after touch scrolling.'); - await waitForCompositorCommit(); +promise_test (async (t) => { + // Make sure that no overscroll event is sent to target_div. + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, true); +}, 'Tests that the window gets overscroll event when no element scrolls ' + + 'after non-animated wheel scrolling.'); - // Scroll up on target div and wait for the window to get overscroll event. - await scrollUp(); - await waitFor(() => { return window_received_autoscroll; }, - 'Window did not receive overscroll event after scroll up on target.'); -}, 'Tests that the window gets overscroll event when no element scrolls.'); +promise_test (async (t) => { + // Make sure that no overscroll event is sent to target_div. + target_div.addEventListener("overscroll", + t.unreached_func("target_div got unexpected overscroll event.")); + return test_overscroll_event_fire(GestureSourceType.MOUSE_INPUT, false); +}, 'Tests that the window gets overscroll event when no element scrolls ' + + 'after animated wheel scrolling(smooth scrolling).'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/resources/scroll-util.js b/third_party/blink/web_tests/fast/scrolling/events/resources/scroll-util.js new file mode 100644 index 0000000..c7c84322 --- /dev/null +++ b/third_party/blink/web_tests/fast/scrolling/events/resources/scroll-util.js
@@ -0,0 +1,34 @@ +// The functions in this file require gesture-util.js + +function scroll(direction, source_device, precise_scrolling_delta) { + return smoothScroll(800 /*pixels to scroll*/, x, y, source_device, direction, + 2000 /*pixels per sec*/, precise_scrolling_delta); +} + +function scrollLeft(source_device, precise_scrolling_delta) { + if (source_device == GestureSourceType.MOUSE_INPUT) + return scroll("left", source_device, precise_scrolling_delta); + return scroll("left", source_device); +} + +function scrollUp(source_device, precise_scrolling_delta) { + if (source_device == GestureSourceType.MOUSE_INPUT) + return scroll("up", source_device, precise_scrolling_delta); + return scroll("up", source_device); +} +function scrollUp(source_device, precise_scrolling_delta) { + if (source_device == GestureSourceType.MOUSE_INPUT) + return scroll("up", source_device, precise_scrolling_delta); + return scroll("up", source_device); +} +function scrollRight(source_device, precise_scrolling_delta) { + if (source_device == GestureSourceType.MOUSE_INPUT) + return scroll("right", source_device, precise_scrolling_delta); + return scroll("right", source_device); +} + +function scrollDown(source_device, precise_scrolling_delta) { + if (source_device == GestureSourceType.MOUSE_INPUT) + return scroll("down", source_device, precise_scrolling_delta); + return scroll("down", source_device); +}
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-after-snap.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-after-snap.html new file mode 100644 index 0000000..ad739c4 --- /dev/null +++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-after-snap.html
@@ -0,0 +1,81 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/gesture-util.js"></script> +<style> +div { + position: absolute; +} +#scroller { + width: 500px; + height: 500px; + overflow: scroll; + scroll-snap-type: both mandatory; + border: solid black 5px; +} +#space { + width: 2000px; + height: 2000px; +} +.target { + width: 200px; + height: 200px; + scroll-snap-align: start; + background-color: blue; +} +</style> + +<div id="scroller"> + <div id="space"></div> + <div class="target" style="left: 0px; top: 0px;"></div> + <div class="target" style="left: 80px; top: 80px;"></div> + <div class="target" style="left: 200px; top: 200px;"></div> +</div> + +<script> +if (window.internals) + internals.runtimeFlags.overscrollCustomizationEnabled = true; + +var scroller = document.getElementById("scroller"); +var space = document.getElementById("space"); +const MAX_FRAME_COUNT = 700; +const MAX_UNCHANGED_FRAME = 20; + +function scrollLeft() { + return scroller.scrollLeft; +} + +var scroll_arrived_after_scroll_end = false; +var scroll_end_arrived = false; +scroller.addEventListener("scroll", () => { + if (scroll_end_arrived) + scroll_arrived_after_scroll_end = true; +}); +scroller.addEventListener("scrollend", () => { + scroll_end_arrived = true; +}); +promise_test (async () => { + await waitForCompositorCommit(); + await smoothScroll(100, 200, 200, GestureSourceType.TOUCH_INPUT, 'down'); + // Wait for the scroll snap animation to finish. + await waitForAnimationEnd(scrollLeft, MAX_FRAME_COUNT, MAX_UNCHANGED_FRAME); + await waitFor(() => { return scroll_end_arrived; }); + // Verify that scroll snap animation has finished before firing scrollend event. + assert_false(scroll_arrived_after_scroll_end); +}, "Tests that scrollend is fired after scroll snap animation completion."); + +promise_test (async () => { + // Reset scroll state. + scroller.scrollTo(0, 0); + await waitForCompositorCommit(); + scroll_end_arrived = false; + scroll_arrived_after_scroll_end = false; + + await swipe(100, 200, 200, 'up'); + // Wait for the scroll snap animation to finish. + await waitForAnimationEnd(scrollLeft, MAX_FRAME_COUNT, MAX_UNCHANGED_FRAME); + await waitFor(() => { return scroll_end_arrived; }); + // Verify that scroll snap animation has finished before firing scrollend event. + assert_false(scroll_arrived_after_scroll_end); +}, "Tests that scrollend is fired after fling snap animation completion."); +</script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html index 09d47a8..cbcedc32 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html +++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #targetDiv { width: 200px; @@ -30,15 +31,6 @@ var rect = target_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollLeft() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "left", - SPEED_INSTANT); -} - -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up", - SPEED_INSTANT); -} var horizontal_scrollend_arrived = false; var vertical_scrollend_arrived = false; @@ -57,23 +49,48 @@ document.addEventListener("scrollend", onHorizontalScrollEnd); document.addEventListener("scrollend", onVerticalScrollEnd); -promise_test (async (t) => { - // Make sure that no scrollend event is sent to target_div. - target_div.addEventListener("scrollend", - t.unreached_func("target_div got unexpected scrollend event.")); - +async function test_scrollend_event_fire(source_device, + precise_scrolling_delta) { + horizontal_scrollend_arrived = false; + vertical_scrollend_arrived = false; await waitForCompositorCommit(); // Scroll left on target div and wait for the doc to get scrollend event. - await scrollLeft(); + await scrollLeft(source_device, precise_scrolling_delta); await waitFor(() => { return horizontal_scrollend_arrived; }, 'Document did not receive scrollend event after scroll left on target.'); assert_equals(target_div.scrollLeft, 0); // Scroll up on target div and wait for the doc to get scrollend event. - await scrollUp(); - await waitFor(() => { return horizontal_scrollend_arrived; }, + await scrollUp(source_device, precise_scrolling_delta); + await waitFor(() => { return vertical_scrollend_arrived; }, 'Document did not receive scrollend event after scroll up on target.'); assert_equals(target_div.scrollTop, 0); -}, 'Tests that the document gets scrollend event when no element scrolls.'); +} + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to target_div. + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the document gets scrollend event when no element scrolls by ' + + 'touch.'); + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to target_div. + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, + true /* precise_scrolling_delta */); +}, 'Tests that the document gets scrollend event when no element scrolls by '+ + ' wheel in non-animated scrolling path.'); + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to target_div. + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, + false /* precise_scrolling_delta */); +}, 'Tests that the document gets scrollend event when no element scrolls by '+ + ' wheel in smooth scrolling path.'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-element-with-overscroll-behavior.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-element-with-overscroll-behavior.html index 0a9e9c7..dc2608ba 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-element-with-overscroll-behavior.html +++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-element-with-overscroll-behavior.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #overscrollXDiv { width: 600px; @@ -49,15 +50,6 @@ var rect = target_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollLeft() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "left", - SPEED_INSTANT); -} - -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up", - SPEED_INSTANT); -} var horizontal_scrollend_arrived = false; var vertical_scrollend_arrived = false; @@ -76,18 +68,15 @@ document.getElementById('overscrollYDiv'). addEventListener("scrollend", onVerticalScrollEnd); -promise_test (async (t) => { - // Make sure that no scrollend event is sent to document or target_div. - document.addEventListener("scrollend", - t.unreached_func("Document got unexpected scrollend event.")); - target_div.addEventListener("scrollend", - t.unreached_func("target_div got unexpected scrollend event.")); - +async function test_scrollend_event_fire(source_device, + precise_scrolling_delta) { + horizontal_scrollend_arrived = false; + vertical_scrollend_arrived = false; await waitForCompositorCommit(); // Scroll left on target div and wait for the element with overscroll-x to // get scrollend event. - await scrollLeft(); + await scrollLeft(source_device, precise_scrolling_delta); await waitFor(() => { return horizontal_scrollend_arrived; }, 'Expected element did not receive scrollend event after scroll left ' + 'on target.'); @@ -95,11 +84,42 @@ // Scroll up on target div and wait for the element with overscroll-y to get // scrollend event. - await scrollUp(); + await scrollUp(source_device, precise_scrolling_delta); await waitFor(() => { return vertical_scrollend_arrived; }, 'Expected element did not receive scrollend event after scroll up on ' + 'target.'); assert_equals(target_div.scrollTop, 0); +} + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document or target_div. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.TOUCH_INPUT); }, 'Tests that the last element in the cut scroll chain gets scrollend ' + - 'event when no element scrolls.'); + 'event when no element scrolls by touch.'); + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document or target_div. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, + true /* precise_scrolling_delta */); +}, 'Tests that the last element in the cut scroll chain gets scrollend ' + + 'event when no element scrolls by wheel in non-animated scroll path.'); + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document or target_div. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, + false /* precise_scrolling_delta */); +}, 'Tests that the last element in the cut scroll chain gets scrollend ' + + 'event when no element scrolls by wheel in smooth scrolling path.'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-scrolled-element.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-scrolled-element.html index 64649ee..0065c12 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-scrolled-element.html +++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-scrolled-element.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #scrollableDiv { width: 200px; @@ -30,15 +31,6 @@ var rect = scrolling_div.getBoundingClientRect(); var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollRight() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "right", - SPEED_INSTANT); -} - -function scrollDown() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "down", - SPEED_INSTANT); -} var horizontal_scrollend_arrived = false; var vertical_scrollend_arrived = false; @@ -55,25 +47,46 @@ scrolling_div.addEventListener("scrollend", onHorizontalScrollEnd); scrolling_div.addEventListener("scrollend", onVerticalScrollEnd); -promise_test (async (t) => { - // Make sure that no scrollend event is sent to document. - document.addEventListener("scrollend", - t.unreached_func("Document got unexpected scrollend event.")); - +async function test_scrollend_event_fire(source_device, + precise_scroll_deltas) { + horizontal_scrollend_arrived = false; + vertical_scrollend_arrived = false; + scrolling_div.scrollTo(0, 0); await waitForCompositorCommit(); // Do a horizontal scroll and wait for scrollend event. - await scrollRight(); + await scrollRight(source_device, precise_scroll_deltas); await waitFor(() => { return horizontal_scrollend_arrived; }, 'Scroller did not receive scrollend event after horizontal scroll.'); assert_equals(scrolling_div.scrollWidth - scrolling_div.scrollLeft, scrolling_div.clientWidth); // Do a vertical scroll and wait for scrollend event. - await scrollDown(); + await scrollDown(source_device, precise_scroll_deltas); await waitFor(() => { return vertical_scrollend_arrived; }, 'Scroller did not receive scrollend event after vertical scroll.'); assert_equals(scrolling_div.scrollHeight - scrolling_div.scrollTop, scrolling_div.clientHeight); -}, 'Tests that the scrolled element gets scrollend event at the end of scroll.'); +} + +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the scrolled element gets scrollend event at the end of touch scrolling.'); +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, true); +}, 'Tests that the scrolled element gets scrollend event at the end of ' + + 'non-animated wheel scrolling.'); +promise_test (async (t) => { + // Make sure that no scrollend event is sent to document. + document.addEventListener("scrollend", + t.unreached_func("Document got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, false); +}, 'Tests that the scrolled element gets scrollend event at the end of ' + + 'animated wheel scrolling (smooth-scrolling).'); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html index 4b01c4e6..d7d1b19 100644 --- a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html +++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html
@@ -2,6 +2,7 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/gesture-util.js"></script> +<script src="resources/scroll-util.js"></script> <style> #targetDiv { width: 200px; @@ -31,11 +32,6 @@ var x = rect.left + rect.width / 2; var y = rect.top + rect.height / 2; -function scrollUp() { - return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up", - SPEED_INSTANT); -} - var scrollend_arrived = false; function onScrollEnd(event) { assert_false(event.cancelable); @@ -45,17 +41,36 @@ } window.addEventListener("scrollend", onScrollEnd); +async function test_scrollend_event_fire(source_device, precise_scroll_deltas) { + scrollend_arrived = false; + await waitForCompositorCommit(); + + // Scroll up on target div and wait for the doc to get scrollend event. + await scrollUp(source_device, precise_scroll_deltas); + await waitFor(() => { return scrollend_arrived; }, + 'Window did not receive scrollend event after scroll up on target.'); + assert_equals(target_div.scrollTop, 0); +} + promise_test (async (t) => { // Make sure that no scrollend event is sent to target_div. target_div.addEventListener("scrollend", t.unreached_func("target_div got unexpected scrollend event.")); - - await waitForCompositorCommit(); - - // Scroll up on target div and wait for the doc to get scrollend event. - await scrollUp(); - await waitFor(() => { return scrollend_arrived; }, - 'Window did not receive scrollend event after scroll up on target.'); - assert_equals(target_div.scrollTop, 0); -}, 'Tests that the window gets scrollend event when no element scrolls.'); + return test_scrollend_event_fire(GestureSourceType.TOUCH_INPUT); +}, 'Tests that the window gets scrollend event when no element scrolls ' + + 'after touch scrolling.'); +promise_test (async (t) => { + // Make sure that no scrollend event is sent to target_div. + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, true); +}, 'Tests that the window gets scrollend event when no element scrolls ' + + 'after non-animated wheel scrolling.'); +promise_test (async (t) => { + // Make sure that no scrollend event is sent to target_div. + target_div.addEventListener("scrollend", + t.unreached_func("target_div got unexpected scrollend event.")); + return test_scrollend_event_fire(GestureSourceType.MOUSE_INPUT, false); +}, 'Tests that the window gets scrollend event when no element scrolls ' + + 'after animated wheel scrolling(smooth scrolling).'); </script>
diff --git a/third_party/blink/web_tests/fast/text/selection/insert-text-crash-expected.txt b/third_party/blink/web_tests/fast/text/selection/insert-text-crash-expected.txt deleted file mode 100644 index 22f5fd8..0000000 --- a/third_party/blink/web_tests/fast/text/selection/insert-text-crash-expected.txt +++ /dev/null
@@ -1,3 +0,0 @@ -CONSOLE ERROR: line 60: Uncaught TypeError: Cannot read property 'parentNode' of null -a:ce#@::l -Test passes if it does not CRASH.
diff --git a/third_party/blink/web_tests/fast/text/selection/insert-text-crash.html b/third_party/blink/web_tests/fast/text/selection/insert-text-crash.html index e40d917..98fe502 100644 --- a/third_party/blink/web_tests/fast/text/selection/insert-text-crash.html +++ b/third_party/blink/web_tests/fast/text/selection/insert-text-crash.html
@@ -1,4 +1,6 @@ <!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> <style> span { float: left !important; @@ -50,14 +52,18 @@ document.addEventListener("DOMNodeRemoved", DOMNodeRemoved, true); window.onload = function() { - document.designMode = "on"; + test(function() { + assert_throws(new TypeError, function() { + document.designMode = "on"; - var oElement = document.getElementById('col'); - oElement.parentNode.replaceChild(document.createElementNS('http://www.w3.org/2000/svg', 'feSpecularLighting'), oElement); + var oElement = document.getElementById('col'); + oElement.parentNode.replaceChild(document.createElementNS('http://www.w3.org/2000/svg', 'feSpecularLighting'), oElement); - document.execCommand('InsertOrderedList', false, false); - var oElement = document.getElementById('svg'); - oElement.parentNode.replaceChild(document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform'), oElement); + document.execCommand('InsertOrderedList'); + var oElement = document.getElementById('svg'); + oElement.parentNode.replaceChild(document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform'), oElement); + }); + }); }; </script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..f93627a --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png new file mode 100644 index 0000000..fe4c60fb --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-basics.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-basics.html index e3e5220..7a3e3d5 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-basics.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-basics.html
@@ -4,7 +4,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html index 96ef490..9199e804 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html
@@ -3,9 +3,9 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <body>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-origins.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-origins.html index 9cbccb6..c488f720 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-origins.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-origins.html
@@ -3,8 +3,8 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html index 2bebfae..f113f13 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-create-with-virtual-authenticator.html
@@ -3,9 +3,9 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <body>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-basics.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-basics.html index f50637c..4a970f7 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-basics.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-basics.html
@@ -4,7 +4,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-errors.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-errors.html index 9a3ae8a..afdc4a8c 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-errors.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-errors.html
@@ -3,7 +3,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html index 9827d33..5039922 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
@@ -3,9 +3,9 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <body>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-origins.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-origins.html index f21ad60..203bf2a 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-origins.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-origins.html
@@ -4,7 +4,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html index b9778bd..48e9db0 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html
@@ -3,9 +3,9 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <body>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html index 2f185fb..d55bd51 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html
@@ -4,7 +4,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-store-basics.html b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-store-basics.html index 15e07fc1..040d0c5c 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-store-basics.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/credentialscontainer-store-basics.html
@@ -4,7 +4,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/mock-authenticator.html b/third_party/blink/web_tests/http/tests/credentialmanager/mock-authenticator.html index 57f6445..3658e29 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/mock-authenticator.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/mock-authenticator.html
@@ -3,7 +3,7 @@ <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/register-then-sign.html b/third_party/blink/web_tests/http/tests/credentialmanager/register-then-sign.html index 6224469..10b0381 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/register-then-sign.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/register-then-sign.html
@@ -3,7 +3,7 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/test-inputs.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-create-helper.html b/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-create-helper.html index 5e2ca6d..d12d590 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-create-helper.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-create-helper.html
@@ -1,7 +1,7 @@ <!DOCTYPE HTML> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> <script src="test-inputs.js"></script> <script src="mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-get-helper.html b/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-get-helper.html index 3a694509..66ed93e 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-get-helper.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/resources/publickey-get-helper.html
@@ -1,7 +1,7 @@ <!DOCTYPE HTML> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom.js"></script> <script src="/gen/third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/authenticator.mojom.js"></script> <script src="test-inputs.js"></script> <script src="mock-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/tools/virtual-authenticator-environment-manual.html b/third_party/blink/web_tests/http/tests/credentialmanager/tools/virtual-authenticator-environment-manual.html index 90994b7..da90830 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/tools/virtual-authenticator-environment-manual.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/tools/virtual-authenticator-environment-manual.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <title>Credential Manager: helper page for manual testing using the Testing API.</title> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="../resources/virtual-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/virtual-navigator-credentials.html b/third_party/blink/web_tests/http/tests/credentialmanager/virtual-navigator-credentials.html index 2198b627..ae9e2d0 100644 --- a/third_party/blink/web_tests/http/tests/credentialmanager/virtual-navigator-credentials.html +++ b/third_party/blink/web_tests/http/tests/credentialmanager/virtual-navigator-credentials.html
@@ -3,7 +3,7 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="/gen/third_party/blink/public/platform/modules/webauthn/virtual_authenticator.mojom.js"></script> +<script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.js"></script> <script src="resources/virtual-navigator-credentials.js"></script> <script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/accessibility/edit-aria-attributes.js b/third_party/blink/web_tests/http/tests/devtools/elements/accessibility/edit-aria-attributes.js index ec999f70c..41bc4b7 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/accessibility/edit-aria-attributes.js +++ b/third_party/blink/web_tests/http/tests/devtools/elements/accessibility/edit-aria-attributes.js
@@ -34,9 +34,14 @@ treeElement._startEditing(); treeElement._prompt._element.textContent = 'radio'; treeElement._prompt._element.dispatchEvent(TestRunner.createKeyEvent('Enter')); - self.runtime.sharedInstance(Accessibility.AccessibilitySidebarView).doUpdate().then(() => { - postRoleChange(); - }); + // Give the document lifecycle a chance to run before updating the view. + window.setTimeout(() => { + self.runtime.sharedInstance(Accessibility.AccessibilitySidebarView) + .doUpdate() + .then(() => { + postRoleChange(); + }); + }, 0); } function postRoleChange() {
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt new file mode 100644 index 0000000..cd0e0a2 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar-expected.txt
@@ -0,0 +1,124 @@ +Tests that the sidebar uses the correct styling for mixed content subresources. + +Origin sidebar: +<DIV > + <#document-fragment > + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + <DIV class=tree-outline-disclosure > + <OL class=tree-outline role=tree tabindex=-1 > + <LI role=treeitem class=security-main-view-sidebar-tree-item selected force-white-icons tabindex=0 > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > + </SPAN> + <DIV class=icon lock-icon lock-icon-neutral > + </DIV> + <SPAN class=title > +Overview + </SPAN> + </LI> + <OL class=children role=group > + </OL> + <LI role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > +Main origin + </SPAN> + </LI> + <OL class=children expanded role=group > + <LI role=treeitem class=security-main-view-reload-message > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > +Reload to view details + </SPAN> + </LI> + <OL class=children role=group > + </OL> + </OL> + <LI role=treeitem class=parent always-parent expanded security-sidebar-origins aria-expanded=true > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > +Non-secure origins + </SPAN> + </LI> + <OL class=children expanded role=group > + <LI role=treeitem class=security-sidebar-tree-item > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > + </SPAN> + <DIV class=icon security-property security-property-insecure > + </DIV> + <SPAN > + <SPAN class=url-scheme-insecure > +http + </SPAN> + <SPAN class=url-scheme-separator > +:// + </SPAN> + <SPAN > +foo.test + </SPAN> + </SPAN> + </LI> + <OL class=children role=group > + </OL> + <LI role=treeitem class=security-sidebar-tree-item > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > + </SPAN> + <DIV class=icon security-property security-property-insecure > + </DIV> + <SPAN > + <SPAN class=url-scheme-insecure > +http + </SPAN> + <SPAN class=url-scheme-separator > +:// + </SPAN> + <SPAN > +bar.test + </SPAN> + </SPAN> + </LI> + <OL class=children role=group > + </OL> + </OL> + <LI role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > +Secure origins + </SPAN> + </LI> + <OL class=children expanded hidden role=group > + </OL> + <LI role=treeitem class=parent always-parent expanded security-sidebar-origins hidden aria-expanded=true > + <DIV class=selection fill > + </DIV> + <SPAN class=tree-element-title > +Unknown / canceled + </SPAN> + </LI> + <OL class=children expanded hidden role=group > + </OL> + </OL> + </DIV> + <STYLE type=text/css > + </STYLE> + <STYLE type=text/css > + </STYLE> + </#document-fragment> +</DIV> +
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js new file mode 100644 index 0000000..eb988775 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js
@@ -0,0 +1,55 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult( + `Tests that the sidebar uses the correct styling for mixed content subresources.\n`); + await TestRunner.loadModule('security_test_runner'); + await TestRunner.showPanel('security'); + + /** @type {!Protocol.Security.InsecureContentStatus} */ + var insecureContentStatus = { + ranMixedContent: true, + displayedMixedContent: true, + ranContentWithCertErrors: false, + displayedContentWithCertErrors: false, + ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, + displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral + }; + + var mixedExplanations = [ + { + securityState: Protocol.Security.SecurityState.Neutral, + summary: 'Neutral Test Summary', + description: 'Neutral Test Description', + mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable, + certificate: [] + }, + { + securityState: Protocol.Security.SecurityState.Insecure, + summary: 'Insecure Test Summary', + description: 'Insecure Test Description', + mixedContentType: Protocol.Security.MixedContentType.Blockable, + certificate: [] + } + ]; + TestRunner.mainTarget.model(Security.SecurityModel) + .dispatchEventToListeners( + Security.SecurityModel.Events.SecurityStateChanged, + new Security.PageSecurityState( + Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null)); + + var passive = new SDK.NetworkRequest(0, 'http://foo.test', 'https://foo.test', 0, 0, null); + passive.mixedContentType = 'optionally-blockable'; + SecurityTestRunner.dispatchRequestFinished(passive); + + var active = new SDK.NetworkRequest(0, 'http://bar.test', 'https://bar.test', 0, 0, null); + active.mixedContentType = 'blockable'; + SecurityTestRunner.dispatchRequestFinished(active); + + TestRunner.addResult('Origin sidebar:'); + TestRunner.dumpDeepInnerHTML(Security.SecurityPanel._instance()._sidebarTree.element); + + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation-expected.txt new file mode 100644 index 0000000..cb266d3 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation-expected.txt
@@ -0,0 +1,5 @@ +Tests that aborted navigation request does not result in navigation. +Request to http://www.example.com/, type: Document +Error text from Page.navigate: net::ERR_ABORTED +current location: http://127.0.0.1:8000/inspector-protocol/resources/test-page.html +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation.js new file mode 100644 index 0000000..b99fc4f --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/abort-navigation.js
@@ -0,0 +1,22 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startURL( + '../resources/test-page.html', + `Tests that aborted navigation request does not result in navigation.`); + + await testRunner.browserP().Target.setDiscoverTargets({discover: true}); + await dp.Page.enable(); + var FetchHelper = await testRunner.loadScript('resources/fetch-test.js'); + var helper = new FetchHelper(testRunner, dp, dp); + await helper.enable(false); + + testRunner.browserP().Target.onTargetInfoChanged( + () => testRunner.log('FAIL: got Target.onTargetInfoChanged')); + + helper.onceRequest().fail({ errorReason: 'Aborted' }); + + let error = (await dp.Page.navigate({url: "http://www.example.com/"})).result.errorText; + testRunner.log(`Error text from Page.navigate: ${error}`); + const location = await session.evaluate('location.href'); + testRunner.log(`current location: ${location}`); + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic-expected.txt index 15a05d8..c49c8ca8 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic-expected.txt
@@ -1,14 +1,14 @@ Tests basic function of the fetch domain. -Request to undefined, type: Document -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/inspector-protocol/resources/inspector-protocol-page.html, type: Document +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after Fetch.fulfillRequest: overriden response body -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.continueRequest: Hello world -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.continueRequest with new URL: ****************************************** -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.failRequest: fail Sending invalid header (should result in error) -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/inspector-protocol/network/resources/echo-headers.php?headers=HTTP_X_DEVTOOLS_TEST, type: XHR Got error: Invalid header
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic.js index 7e21c2a..0bdd2c7 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-basic.js
@@ -4,10 +4,9 @@ var FetchHelper = await testRunner.loadScript('resources/fetch-test.js'); var helper = new FetchHelper(testRunner, testRunner.browserP(), dp); - await helper.enable(); + await helper.enable(true); helper.onceRequest().fulfill({ - fetchId: params.fetchId, responseCode: 200, responseHeaders: [], body: btoa("overriden response body")
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer-expected.txt index 15a05d8..c49c8ca8 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer-expected.txt
@@ -1,14 +1,14 @@ Tests basic function of the fetch domain. -Request to undefined, type: Document -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/inspector-protocol/resources/inspector-protocol-page.html, type: Document +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after Fetch.fulfillRequest: overriden response body -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.continueRequest: Hello world -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.continueRequest with new URL: ****************************************** -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/devtools/network/resources/resource.php, type: XHR Response after fetch.failRequest: fail Sending invalid header (should result in error) -Request to undefined, type: XHR +Request to http://127.0.0.1:8000/inspector-protocol/network/resources/echo-headers.php?headers=HTTP_X_DEVTOOLS_TEST, type: XHR Got error: Invalid header
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer.js index 650b614..7dc4a28 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/fetch-renderer.js
@@ -4,10 +4,9 @@ var FetchHelper = await testRunner.loadScript('resources/fetch-test.js'); var helper = new FetchHelper(testRunner, dp, dp); - await helper.enable(); + await helper.enable(true); helper.onceRequest().fulfill({ - fetchId: params.fetchId, responseCode: 200, responseHeaders: [], body: btoa("overriden response body")
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/resources/fetch-test.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/resources/fetch-test.js index 21881aba..e78f93e9 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/resources/fetch-test.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fetch/resources/fetch-test.js
@@ -37,7 +37,7 @@ } _handleError(result) { - if (result.error) + if (result.error && !/Invalid InterceptionId/.test(result.error.message)) this._testRunner.log(`Got error: ${result.error.message}`); } }; @@ -57,10 +57,12 @@ }); } - enable(patterns) { - this._protocol.Fetch.enable({patterns}); - this.onceRequest().continueRequest(); - return this._pageProtocol.Page.reload(); + async enable(reload) { + await this._protocol.Fetch.enable({}); + if (reload) { + this.onceRequest().continueRequest(); + await this._pageProtocol.Page.reload(); + } } onRequest(pattern) { @@ -79,7 +81,7 @@ const params = event.params; const response = event.responseErrorReason || event.responseStatusCode; const response_text = response ? 'Response' : 'Request'; - this._testRunner.log(`${response_text} to ${params.url}, type: ${params.resourceType}`); + this._testRunner.log(`${response_text} to ${params.request.url}, type: ${params.resourceType}`); } _findHandler(event) {
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 66eb4c3..5a77993 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -3550,7 +3550,6 @@ getter connection getter deviceMemory getter hardwareConcurrency - getter idle getter language getter languages getter locks
diff --git a/third_party/blink/web_tests/platform/android/fast/forms/date-multiple-fields/date-multiple-fields-ax-value-changed-notification-expected.txt b/third_party/blink/web_tests/platform/android/fast/forms/date-multiple-fields/date-multiple-fields-ax-value-changed-notification-expected.txt deleted file mode 100644 index b13f6d6b..0000000 --- a/third_party/blink/web_tests/platform/android/fast/forms/date-multiple-fields/date-multiple-fields-ax-value-changed-notification-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This test checks value changed accessibility notifications. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -Focus =AXValueDescription: - -PASS successfullyParsed is true - - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/platform/linux/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/linux/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..9857d35 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/linux/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index fe4c60fb..a043fa03 100644 --- a/third_party/blink/web_tests/platform/linux/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/linux/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..9857d35 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index fe4c60fb..a043fa03 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt deleted file mode 100644 index 39e546e..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent -PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent -PASS Test that embed navigations are not observable by the parent -PASS Test that crossorigin embed navigations are not observable by the parent -PASS Test that embed refreshes are not observable by the parent -PASS Test that crossorigin embed refreshes are not observable by the parent -PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent -PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent -PASS Test that iframe navigations are not observable by the parent -PASS Test that crossorigin iframe navigations are not observable by the parent -PASS Test that iframe refreshes are not observable by the parent -PASS Test that crossorigin iframe refreshes are not observable by the parent -FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" -FAIL Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" -PASS Test that object navigations are not observable by the parent -PASS Test that crossorigin object navigations are not observable by the parent -PASS Test that object refreshes are not observable by the parent -PASS Test that crossorigin object refreshes are not observable by the parent -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..797ef0d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index a013c17..8a62543 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index a013c17..8a62543 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac-retina/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..797ef0d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-retina/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..49f8a8f --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/mac/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index 4540dcc..04b7d55 100644 --- a/third_party/blink/web_tests/platform/mac/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/mac/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt deleted file mode 100644 index b88a5245..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -PASS Test that embed navigations are not observable by the parent, even after history navigations by the parent -PASS Test that crossorigin embed navigations are not observable by the parent, even after history navigations by the parent -PASS Test that embed navigations are not observable by the parent -PASS Test that crossorigin embed navigations are not observable by the parent -PASS Test that embed refreshes are not observable by the parent -PASS Test that crossorigin embed refreshes are not observable by the parent -PASS Test that iframe navigations are not observable by the parent, even after history navigations by the parent -PASS Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent -PASS Test that iframe navigations are not observable by the parent -PASS Test that crossorigin iframe navigations are not observable by the parent -PASS Test that iframe refreshes are not observable by the parent -PASS Test that crossorigin iframe refreshes are not observable by the parent -FAIL Test that object navigations are not observable by the parent, even after history navigations by the parent promise_test: Unhandled rejection with value: "FAIL - first document not exposed" -PASS Test that crossorigin object navigations are not observable by the parent, even after history navigations by the parent -PASS Test that object navigations are not observable by the parent -PASS Test that crossorigin object navigations are not observable by the parent -PASS Test that object refreshes are not observable by the parent -PASS Test that crossorigin object refreshes are not observable by the parent -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..797ef0d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index 4540dcc..04b7d55 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/platform/win/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..03b5322 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/win7/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index a099336..d2feeb47 100644 --- a/third_party/blink/web_tests/platform/win7/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/win7/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/win/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt rename to third_party/blink/web_tests/platform/win7/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
diff --git a/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png b/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png index a099336..d2feeb47 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/printing/composited-thead-tfoot-repeat-expected.html b/third_party/blink/web_tests/printing/composited-thead-tfoot-repeat-expected.html deleted file mode 100644 index 63d3238f..0000000 --- a/third_party/blink/web_tests/printing/composited-thead-tfoot-repeat-expected.html +++ /dev/null
@@ -1,121 +0,0 @@ -<!DOCTYPE html> -<style> -body { - font-size: 30px; - line-height: 50px; -} -</style> -<script> -if (window.testRunner) - testRunner.setPrinting(); -</script> -<table> - <thead> - <tr> - <th>Header</th> - </tr> - </thead> - <tbody> - <tr> - <td>1</td> - </tr> - <tr> - <td>2</td> - </tr> - <tr> - <td>3</td> - </tr> - <tr> - <td>4</td> - </tr> - <tr> - <td>5</td> - </tr> - <tr> - <td>6</td> - </tr> - <tr> - <td>7</td> - </tr> - <tr> - <td>8</td> - </tr> - <tr> - <td>9</td> - </tr> - <tr> - <td>10</td> - </tr> - <tr> - <td>11</td> - </tr> - <tr> - <td>12</td> - </tr> - <tr> - <td>13</td> - </tr> - <tr> - <td>14</td> - </tr> - <tr> - <td>15</td> - </tr> - <tr> - <td>16</td> - </tr> - <tr> - <td>17</td> - </tr> - <tr> - <td>18</td> - </tr> - <tr> - <td>19</td> - </tr> - <tr> - <td>20</td> - </tr> - <tr> - <td>21</td> - </tr> - <tr> - <td>22</td> - </tr> - <tr> - <td>23</td> - </tr> - <tr> - <td>24</td> - </tr> - <tr> - <td>25</td> - </tr> - <tr> - <td>26</td> - </tr> - <tr> - <td>27</td> - </tr> - <tr> - <td>28</td> - </tr> - <tr> - <td>29</td> - </tr> - <tr> - <td>30</td> - </tr> - <tr> - <td>31</td> - </tr> - <tr> - <td>32</td> - </tr> - </tbody> - <tfoot> - <tr> - <th>Footer</th> - </tr> - </tfoot> -</table>
diff --git a/third_party/blink/web_tests/svg/W3C-SVG-1.1/animate-elem-41-t.svg b/third_party/blink/web_tests/svg/W3C-SVG-1.1/animate-elem-41-t.svg index d02f14b8..8e0e31d 100644 --- a/third_party/blink/web_tests/svg/W3C-SVG-1.1/animate-elem-41-t.svg +++ b/third_party/blink/web_tests/svg/W3C-SVG-1.1/animate-elem-41-t.svg
@@ -18,15 +18,15 @@ <Paragraph> For each graphics properties, there are three tests. One animates the graphics - property directly on an element (such as a rect or a line) which uses the - property. The other two tests apply the animation on a container element (g and - a), and validate that the animated property is inherited by elements which + property directly on an element (such as a rect or a line) which uses the + property. The other two tests apply the animation on a container element (g and + a), and validate that the animated property is inherited by elements which are child of the container. </Paragraph> <Paragraph> - For each animation test, the element on which the animation is applied is also - translated by an animation so that the various states of the animation can + For each animation test, the element on which the animation is applied is also + translated by an animation so that the various states of the animation can be checked more easily. In most tests, there is a gray reference marker which shows the expected animation state at the begining of the animation, mid-way, or at the end of the animation. @@ -34,10 +34,10 @@ <Paragraph> The following animations should show continuous changes: fill, stroke, - stroke-width, stroke-miterlimit, stroke-dashoffset and color. Note that + stroke-width, stroke-miterlimit, stroke-dashoffset and color. Note that visually, stroke-miterlimit shows a sharp transition, but that is because the miter is cut off when the animated miter limit reaches the test sharp - angle's miter value. The stroke-miterlimit value is changed continously + angle's miter value. The stroke-miterlimit value is changed continuously but that is not visible in this test. </Paragraph> @@ -88,7 +88,7 @@ <animate attributeName="fill" to="rgb(255,165,0)" dur="3s" fill="freeze"/> <animate attributeName="x" to="40" dur="3s" fill="freeze"/> </rect> - + <g transform="translate(110, 0)"> <rect x="10" width="8" height="8"/> <animate attributeName="fill" to="rgb(255,165,0)" dur="3s" fill="freeze"/> @@ -99,7 +99,7 @@ <rect x="10" width="8" height="8"/> <animate attributeName="fill" to="rgb(255,165,0)" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> - </a> + </a> </g> @@ -118,7 +118,7 @@ <animate attributeName="fill-rule" to="evenodd" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </polyline> - + <g transform="translate(110, 0)"> <animate attributeName="fill-rule" to="evenodd" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -129,7 +129,7 @@ <animate attributeName="fill-rule" to="evenodd" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <polyline points="20,10,0,10,15,20,10,2,5,20,20,10"/> - </a> + </a> </g> @@ -150,7 +150,7 @@ <animate attributeName="stroke" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </rect> - + <g transform="translate(110, 0)"> <animate attributeName="stroke" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -161,7 +161,7 @@ <animate attributeName="stroke" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <rect x="10" width="8" height="8" stroke-width="3"/> - </a> + </a> </g> <g id="setThree" transform="translate(0,60)"> @@ -180,7 +180,7 @@ <animate attributeName="stroke-width" from="1" to="5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </line> - + <g transform="translate(110, 0)"> <animate attributeName="stroke-width" from="1" to="5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -191,7 +191,7 @@ <animate attributeName="stroke-width" from="1" to="5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <line x1="10" y1="8" x2="20" y2="8" stroke="gray"/> - </a> + </a> </g> <g id="setFour" transform="translate(0,80)" stroke-width="4" stroke="rgb(204,0,102)"> @@ -209,7 +209,7 @@ <animate attributeName="stroke-linecap" from="butt" to="round" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </line> - + <g transform="translate(110, 0)"> <animate attributeName="stroke-linecap" from="butt" to="round" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -220,7 +220,7 @@ <animate attributeName="stroke-linecap" from="butt" to="round" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <line x1="10" y1="8" x2="12" y2="8" stroke-width="12"/> - </a> + </a> </g> <g id="setFive" transform="translate(5,100)" fill="none" stroke-miterlimit="10" stroke-width="3" stroke="rgb(204,0,102)"> @@ -238,7 +238,7 @@ <animate attributeName="stroke-linejoin" from="miter" to="bevel" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </polyline> - + <g transform="translate(110, 0)"> <animate attributeName="stroke-linejoin" from="miter" to="bevel" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -249,7 +249,7 @@ <animate attributeName="stroke-linejoin" from="miter" to="bevel" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <polyline points="5,2,20,5,5,8"/> - </a> + </a> </g> <g id="setSix" transform="translate(5,120)" stroke-miterlimit="1" fill="none" stroke-width="3" stroke="rgb(204,0,102)"> @@ -267,7 +267,7 @@ <animate attributeName="stroke-miterlimit" from="1" to="10" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </polyline> - + <g transform="translate(110, 0)"> <animate attributeName="stroke-miterlimit" from="1" to="10" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -278,7 +278,7 @@ <animate attributeName="stroke-miterlimit" from="1" to="10" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <polyline points="5,0,20,5,5,10"/> - </a> + </a> </g> @@ -297,7 +297,7 @@ <animate attributeName="stroke-dashoffset" from="0" to="5.5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="40" dur="3s" fill="freeze" additive="sum"/> </line> - + <g transform="translate(110, 0)"> <animate attributeName="stroke-dashoffset" from="0" to="5.5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="40" dur="3s" fill="freeze" additive="sum"/> @@ -308,7 +308,7 @@ <animate attributeName="stroke-dashoffset" from="0" to="5.5" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="40" dur="3s" fill="freeze" additive="sum"/> <line x1="0" y1="0" x2="25" y2="0"/> - </a> + </a> </g> <g id="setEight" transform="translate(0,160)"> @@ -325,7 +325,7 @@ <animate attributeName="display" from="inline" to="none" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </rect> - + <g transform="translate(110, 0)"> <animate attributeName="display" from="inline" to="none" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -336,7 +336,7 @@ <animate attributeName="display" from="inline" to="none" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <rect x="10" width="8" height="8"/> - </a> + </a> </g> <g id="setNine" transform="translate(0,180)"> @@ -354,7 +354,7 @@ <animate attributeName="visibility" from="visible" to="hidden" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </rect> - + <g transform="translate(110, 0)"> <animate attributeName="visibility" from="visible" to="hidden" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -365,7 +365,7 @@ <animate attributeName="visibility" from="visible" to="hidden" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <rect x="10" width="8" height="8"/> - </a> + </a> </g> <g id="setTen" color="rgb(204,0,102)" transform="translate(0,200)"> @@ -384,7 +384,7 @@ <animate attributeName="color" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> </rect> - + <g transform="translate(110, 0)" fill="currentColor"> <animate attributeName="color" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> @@ -395,7 +395,7 @@ <animate attributeName="color" from="rgb(204,0,102)" to="rgb(255,165,0)" dur="3s" fill="freeze"/> <animateTransform type="translate" attributeName="transform" from="0" to="30" dur="3s" fill="freeze" additive="sum"/> <rect x="10" width="8" height="8"/> - </a> + </a> </g> </g>
diff --git a/third_party/blink/web_tests/svg/custom/radialGradient-focal-radius-expected.png b/third_party/blink/web_tests/svg/custom/radialGradient-focal-radius-expected.png index 2ff02c9..f8348ec 100644 --- a/third_party/blink/web_tests/svg/custom/radialGradient-focal-radius-expected.png +++ b/third_party/blink/web_tests/svg/custom/radialGradient-focal-radius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-all/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-all/README.txt index 5d548a8..78d46c9 100644 --- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-all/README.txt +++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-all/README.txt
@@ -1,3 +1,3 @@ # This suite runs the tests in LayoutTests/paint/dark-mode -# with --blink-settings="highContrastMode=3,darkModePagePolicy=0" +# with --blink-settings="darkMode=3,darkModePagePolicy=0" # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-background/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-background/README.txt index 156dcb7..fa0625cb60 100644 --- a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-background/README.txt +++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/page-policy-background/README.txt
@@ -1,3 +1,3 @@ # This suite runs the tests in LayoutTests/paint/dark-mode -# with --blink-settings="highContrastMode=3,darkModePagePolicy=1" +# with --blink-settings="darkMode=3,darkModePagePolicy=1" # See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png b/third_party/blink/web_tests/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png new file mode 100644 index 0000000..9110f5b --- /dev/null +++ b/third_party/blink/web_tests/virtual/layout_ng_experimental/printing/composited-thead-tfoot-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/linux/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt rename to third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/resource-timing/nested-context-navigations-expected.txt
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 4549102..d1cf0ff 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -639,21 +639,19 @@ [Worker] getter newVersion [Worker] getter oldVersion [Worker] method constructor -[Worker] interface IdleManager +[Worker] interface IdleDetector : EventTarget [Worker] attribute @@toStringTag +[Worker] getter onchange +[Worker] getter state [Worker] method constructor -[Worker] method query +[Worker] method start +[Worker] method stop +[Worker] setter onchange [Worker] interface IdleState [Worker] attribute @@toStringTag [Worker] getter screen [Worker] getter user [Worker] method constructor -[Worker] interface IdleStatus : EventTarget -[Worker] attribute @@toStringTag -[Worker] getter onchange -[Worker] getter state -[Worker] method constructor -[Worker] setter onchange [Worker] interface ImageBitmap [Worker] attribute @@toStringTag [Worker] getter height @@ -3604,7 +3602,6 @@ [Worker] getter connection [Worker] getter deviceMemory [Worker] getter hardwareConcurrency -[Worker] getter idle [Worker] getter language [Worker] getter languages [Worker] getter locks
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 32c72c04..4a37281 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4129,21 +4129,19 @@ getter didTimeout method constructor method timeRemaining -interface IdleManager +interface IdleDetector : EventTarget attribute @@toStringTag + getter onchange + getter state method constructor - method query + method start + method stop + setter onchange interface IdleState attribute @@toStringTag getter screen getter user method constructor -interface IdleStatus : EventTarget - attribute @@toStringTag - getter onchange - getter state - method constructor - setter onchange interface Image attribute @@toStringTag getter align @@ -4829,7 +4827,6 @@ getter geolocation getter hardwareConcurrency getter hid - getter idle getter keyboard getter language getter languages
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index fe76c974..3a90b85 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -3461,7 +3461,6 @@ [Worker] getter connection [Worker] getter deviceMemory [Worker] getter hardwareConcurrency -[Worker] getter idle [Worker] getter language [Worker] getter languages [Worker] getter locks
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn index 78f0711..fd42aeb 100644 --- a/third_party/grpc/BUILD.gn +++ b/third_party/grpc/BUILD.gn
@@ -359,7 +359,6 @@ "src/src/core/lib/iomgr/udp_server.cc", "src/src/core/lib/iomgr/unix_sockets_posix.cc", "src/src/core/lib/iomgr/unix_sockets_posix_noop.cc", - "src/src/core/lib/iomgr/wakeup_fd_cv.cc", "src/src/core/lib/iomgr/wakeup_fd_eventfd.cc", "src/src/core/lib/iomgr/wakeup_fd_nospecial.cc", "src/src/core/lib/iomgr/wakeup_fd_pipe.cc",
diff --git a/third_party/grpc/METADATA b/third_party/grpc/METADATA index 6ea71b5..b0d0044 100644 --- a/third_party/grpc/METADATA +++ b/third_party/grpc/METADATA
@@ -13,7 +13,7 @@ type: GIT value: "https://github.com/grpc/grpc" } - version: "0fc01a302f03c313d33492439366821cb66e0eb6" - last_upgrade_date { year: 2019 month: 2 day: 28 } + version: "b245ad4ae810ed6bc13378421edfd3986a8ffac3" + last_upgrade_date { year: 2019 month: 3 day: 20 } license_type: NOTICE }
diff --git a/third_party/grpc/README.chromium b/third_party/grpc/README.chromium index 527d57f..0be6ed6 100644 --- a/third_party/grpc/README.chromium +++ b/third_party/grpc/README.chromium
@@ -2,7 +2,7 @@ URL: https://github.com/grpc/grpc Version: 0 Date: Feb 3, 2019 -Revision: 0fc01a302f03c313d33492439366821cb66e0eb6 +Revision: b245ad4ae810ed6bc13378421edfd3986a8ffac3 License: Apache 2.0 License File: NOT_SHIPPED Security Critical: yes
diff --git a/third_party/leveldatabase/BUILD.gn b/third_party/leveldatabase/BUILD.gn index 16a55729..3d32c4ad 100644 --- a/third_party/leveldatabase/BUILD.gn +++ b/third_party/leveldatabase/BUILD.gn
@@ -13,17 +13,6 @@ "src", "src/include", ] - - if (is_win) { - # windows.h #defines DeleteFile to DeleteFileW on Unicode builds. This - # definition is in effect in a large part of Chromium's compilation units. - # leveldb::Env has a DeleteFile method, which becomes DeleteFileW when the - # definition is in effect. - # - # Define the macro everywhere, to avoid reasoning about which headers bring - # windows.h in. - defines += [ "DeleteFile=DeleteFileW" ] - } } leveldb_sources = [
diff --git a/third_party/leveldatabase/README.chromium b/third_party/leveldatabase/README.chromium index 06f2ffec..9402317e 100644 --- a/third_party/leveldatabase/README.chromium +++ b/third_party/leveldatabase/README.chromium
@@ -1,7 +1,7 @@ Name: LevelDB: A Fast Persistent Key-Value Store Short Name: leveldb URL: https://github.com/google/leveldb.git -Version: 1.20.git.7b945f200339aa47c24788d3ee9910c09c513843 +Version: 1.20.git.9ce30510d482f5b2fa2965201453f0fc914f700c License: New BSD License File: src/LICENSE Security Critical: yes
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc index b43fbca..6f5c1ab5 100644 --- a/third_party/leveldatabase/env_chromium.cc +++ b/third_party/leveldatabase/env_chromium.cc
@@ -42,6 +42,13 @@ #include "third_party/leveldatabase/src/include/leveldb/options.h" #include "third_party/re2/src/re2/re2.h" +#if defined(OS_WIN) +#undef DeleteFile +#define base_DeleteFile base::DeleteFileW +#else // defined(OS_WIN) +#define base_DeleteFile base::DeleteFile +#endif // defined(OS_WIN) + using base::FilePath; using base::trace_event::MemoryAllocatorDump; using base::trace_event::MemoryDumpArgs; @@ -869,7 +876,7 @@ FILE_PATH_LITERAL("*.bak")); for (base::FilePath fname = dir_reader.Next(); !fname.empty(); fname = dir_reader.Next()) { - histogram->AddBoolean(base::DeleteFile(fname, false)); + histogram->AddBoolean(base_DeleteFile(fname, false)); } } @@ -903,7 +910,7 @@ Status result; FilePath fname_filepath = FilePath::FromUTF8Unsafe(fname); // TODO(jorlow): Should we assert this is a file? - if (!base::DeleteFile(fname_filepath, false)) { + if (!base_DeleteFile(fname_filepath, false)) { result = MakeIOError(fname, "Could not delete file.", kDeleteFile); RecordErrorAt(kDeleteFile); } @@ -927,7 +934,7 @@ Status ChromiumEnv::DeleteDir(const std::string& name) { Status result; // TODO(jorlow): Should we assert this is a directory? - if (!base::DeleteFile(FilePath::FromUTF8Unsafe(name), false)) { + if (!base_DeleteFile(FilePath::FromUTF8Unsafe(name), false)) { result = MakeIOError(name, "Could not delete directory.", kDeleteDir); RecordErrorAt(kDeleteDir); }
diff --git a/third_party/leveldatabase/env_chromium.h b/third_party/leveldatabase/env_chromium.h index dfed32e..1927050 100644 --- a/third_party/leveldatabase/env_chromium.h +++ b/third_party/leveldatabase/env_chromium.h
@@ -19,6 +19,8 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/metrics/histogram.h" +#include "base/synchronization/condition_variable.h" +#include "build/build_config.h" #include "leveldb/cache.h" #include "leveldb/db.h" #include "leveldb/env.h" @@ -26,6 +28,12 @@ #include "port/port_chromium.h" #include "util/mutexlock.h" +#if defined(OS_WIN) && defined(DeleteFile) +// See comment in env.h. +#undef DeleteFile +#define ENV_CHROMIUM_DELETEFILE_UNDEFINED +#endif // defined(OS_WIN) && defined(DeleteFile) + namespace base { namespace trace_event { class MemoryAllocatorDump; @@ -369,4 +377,9 @@ } // namespace leveldb_env +// Redefine DeleteFile if necessary. +#if defined(OS_WIN) && defined(ENV_CHROMIUM_DELETEFILE_UNDEFINED) +#define DeleteFile DeleteFileW +#endif + #endif // THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_H_
diff --git a/third_party/leveldatabase/env_chromium_unittest.cc b/third_party/leveldatabase/env_chromium_unittest.cc index b0818d9..9c9ea6b 100644 --- a/third_party/leveldatabase/env_chromium_unittest.cc +++ b/third_party/leveldatabase/env_chromium_unittest.cc
@@ -18,6 +18,7 @@ #include "base/test/scoped_task_environment.h" #include "base/test/test_suite.h" #include "base/trace_event/process_memory_dump.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/leveldb_chrome.h" @@ -27,6 +28,10 @@ #define FPL FILE_PATH_LITERAL +#if defined(OS_WIN) && defined(DeleteFile) +#undef DeleteFile +#endif + using base::trace_event::MemoryDumpArgs; using base::trace_event::MemoryDumpLevelOfDetail; using base::trace_event::ProcessMemoryDump;
diff --git a/third_party/leveldatabase/leveldb_chrome.cc b/third_party/leveldatabase/leveldb_chrome.cc index 5c15aabc..e84aacdb 100644 --- a/third_party/leveldatabase/leveldb_chrome.cc +++ b/third_party/leveldatabase/leveldb_chrome.cc
@@ -21,10 +21,18 @@ #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/process_memory_dump.h" +#include "build/build_config.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" #include "util/mutexlock.h" +#if defined(OS_WIN) +#undef DeleteFile +#define base_DeleteFile base::DeleteFileW +#else // defined(OS_WIN) +#define base_DeleteFile base::DeleteFile +#endif // defined(OS_WIN) + using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; using base::trace_event::MemoryAllocatorDump; using base::trace_event::MemoryDumpArgs; @@ -365,7 +373,7 @@ // TODO(cmumford): To be fully safe this implementation should acquire a lock // as there is some daylight in between DestroyDB and DeleteFile. - if (!base::DeleteFile(db_path, true)) { + if (!base_DeleteFile(db_path, true)) { // Only delete the directory when when DestroyDB is successful. This is // because DestroyDB checks for database locks, and will fail if in use. return leveldb::Status::IOError(db_path.AsUTF8Unsafe(), "Error deleting");
diff --git a/third_party/leveldatabase/port/port_chromium.cc b/third_party/leveldatabase/port/port_chromium.cc index b84c6e0..570035d2 100644 --- a/third_party/leveldatabase/port/port_chromium.cc +++ b/third_party/leveldatabase/port/port_chromium.cc
@@ -6,48 +6,12 @@ #include <string> -#include "base/threading/platform_thread.h" #include "third_party/crc32c/src/include/crc32c/crc32c.h" #include "third_party/snappy/src/snappy.h" -#include "util/logging.h" namespace leveldb { namespace port { -Mutex::Mutex() = default; - -Mutex::~Mutex() = default; - -void Mutex::Lock() { - mu_.Acquire(); -} - -void Mutex::Unlock() { - mu_.Release(); -} - -void Mutex::AssertHeld() { - mu_.AssertAcquired(); -} - -CondVar::CondVar(Mutex* mu) - : cv_(&mu->mu_) { -} - -CondVar::~CondVar() = default; - -void CondVar::Wait() { - cv_.Wait(); -} - -void CondVar::Signal(){ - cv_.Signal(); -} - -void CondVar::SignalAll() { - cv_.Broadcast(); -} - bool Snappy_Compress(const char* input, size_t input_length, std::string* output) {
diff --git a/third_party/leveldatabase/port/port_chromium.h b/third_party/leveldatabase/port/port_chromium.h index f37cf52c..6a9f74e4 100644 --- a/third_party/leveldatabase/port/port_chromium.h +++ b/third_party/leveldatabase/port/port_chromium.h
@@ -7,16 +7,13 @@ #ifndef STORAGE_LEVELDB_PORT_PORT_CHROMIUM_H_ #define STORAGE_LEVELDB_PORT_PORT_CHROMIUM_H_ -#include <stddef.h> -#include <stdint.h> - +#include <cassert> +#include <condition_variable> // NOLINT #include <cstring> +#include <mutex> // NOLINT #include <string> -#include "base/atomicops.h" #include "base/macros.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "build/build_config.h" @@ -28,56 +25,41 @@ class LOCKABLE Mutex { public: - Mutex(); - ~Mutex(); - void Lock() EXCLUSIVE_LOCK_FUNCTION(); - void Unlock() UNLOCK_FUNCTION(); - void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); + Mutex() = default; + ~Mutex() = default; + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); } + void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); } + void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {} private: - base::Lock mu_; - friend class CondVar; - DISALLOW_COPY_AND_ASSIGN(Mutex); + std::mutex mu_; }; +// Thinly wraps std::condition_variable. class CondVar { public: - explicit CondVar(Mutex* mu); - ~CondVar(); - void Wait(); - void Signal(); - void SignalAll(); + explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); } + ~CondVar() = default; + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Wait() { + std::unique_lock<std::mutex> lock(mu_->mu_, std::adopt_lock); + cv_.wait(lock); + lock.release(); + } + void Signal() { cv_.notify_one(); } + void SignalAll() { cv_.notify_all(); } private: - base::ConditionVariable cv_; - - DISALLOW_COPY_AND_ASSIGN(CondVar); -}; - -class AtomicPointer { - public: - AtomicPointer() = default; - ~AtomicPointer() = default; - - explicit AtomicPointer(void* p) : rep_(reinterpret_cast<Rep>(p)) {} - - inline void* Acquire_Load() const { - return reinterpret_cast<void*>(base::subtle::Acquire_Load(&rep_)); - } - inline void Release_Store(void* v) { - base::subtle::Release_Store(&rep_, reinterpret_cast<Rep>(v)); - } - inline void* NoBarrier_Load() const { - return reinterpret_cast<void*>(base::subtle::NoBarrier_Load(&rep_)); - } - inline void NoBarrier_Store(void* v) { - base::subtle::NoBarrier_Store(&rep_, reinterpret_cast<Rep>(v)); - } - - private: - using Rep = base::subtle::AtomicWord; - Rep rep_; + std::condition_variable cv_; + Mutex* const mu_; }; bool Snappy_Compress(const char* input, size_t input_length,
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index f6bf534..101cc63 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Thursday March 14 2019 +Date: Wednesday March 20 2019 Branch: master -Commit: 1533bd84f12e5b24b5c2e41d1729942c7aa218ad +Commit: 3e2b4b3d4803f20814d6b6cb3109efbc95249b60 Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 72e4d8ce..cb1ddae 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 8 #define VERSION_PATCH 0 -#define VERSION_EXTRA "239-g1533bd84f" +#define VERSION_EXTRA "271-g3e2b4b3d48" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.8.0-239-g1533bd84f" -#define VERSION_STRING " v1.8.0-239-g1533bd84f" +#define VERSION_STRING_NOSP "v1.8.0-271-g3e2b4b3d48" +#define VERSION_STRING " v1.8.0-271-g3e2b4b3d48"
diff --git a/third_party/mockito/BUILD.gn b/third_party/mockito/BUILD.gn index bb61bcbbe..7cc06a13 100644 --- a/third_party/mockito/BUILD.gn +++ b/third_party/mockito/BUILD.gn
@@ -11,6 +11,7 @@ testonly = true proguard_configs = [ "//third_party/mockito/proguard.flags" ] deps = [ + "//third_party/android_tools:android_test_base_java", "//third_party/byte_buddy:byte_buddy_agent_java", "//third_party/byte_buddy:byte_buddy_android_java", "//third_party/byte_buddy:byte_buddy_java",
diff --git a/third_party/node/README.chromium b/third_party/node/README.chromium index 2f10e6e..9ba18d04 100644 --- a/third_party/node/README.chromium +++ b/third_party/node/README.chromium
@@ -1,7 +1,7 @@ Name: Node JS Short Name: node URL: https://github.com/nodejs/node -Version: 8.9.1 +Version: 10.15.3 Revision: f098f8295c407e5a5126b501ed5f1aa80bd86106 Date: Tue Dec 06 2016 18:07:35 GMT-0800 (PST) License: NodeJS
diff --git a/third_party/node/linux/node-linux-x64.tar.gz.sha1 b/third_party/node/linux/node-linux-x64.tar.gz.sha1 index 4857494..5d19fdea 100644 --- a/third_party/node/linux/node-linux-x64.tar.gz.sha1 +++ b/third_party/node/linux/node-linux-x64.tar.gz.sha1
@@ -1 +1 @@ -1bdce2f7303ac1db18166035a0c4035134d46bbc +3f578b6dec3fdddde88a9e889d9dd5d660c26db9
diff --git a/third_party/node/mac/node-darwin-x64.tar.gz.sha1 b/third_party/node/mac/node-darwin-x64.tar.gz.sha1 index fce5c68..9c99df24 100644 --- a/third_party/node/mac/node-darwin-x64.tar.gz.sha1 +++ b/third_party/node/mac/node-darwin-x64.tar.gz.sha1
@@ -1 +1 @@ -c52ee3605efb50ae391bdbe547fb385f39c5a7a9 +37d5bb727fa6f3f29a8981962903d0a2371a3f2d
diff --git a/third_party/node/update_node_binaries b/third_party/node/update_node_binaries index 8619780..1f12c49 100755 --- a/third_party/node/update_node_binaries +++ b/third_party/node/update_node_binaries
@@ -15,7 +15,7 @@ cd "$(dirname "$0")" BASE_URL="https://nodejs.org/dist" -NODE_VERSION="v8.9.1" +NODE_VERSION="v10.15.3" update_unix() { local SUFFIX="$1" @@ -84,7 +84,7 @@ # First download checksum file. rm -f "SHASUMS256.txt" -wget "https://nodejs.org/dist/latest-v8.x/SHASUMS256.txt" +wget "https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt" update_unix "darwin-x64" "mac" update_unix "linux-x64" "linux"
diff --git a/third_party/node/win/node.exe.sha1 b/third_party/node/win/node.exe.sha1 index aec1c377..7c39c6c6 100644 --- a/third_party/node/win/node.exe.sha1 +++ b/third_party/node/win/node.exe.sha1
@@ -1 +1 @@ -b8a7c3e2e5f3e88a3e9c132bec496b917d1f2fd8 +8853bd913cd387c2f88a1ab307780278e16caa69
diff --git a/tools/android/roll/android_deps/build.gradle b/tools/android/roll/android_deps/build.gradle index fa323a8..91ce60a 100644 --- a/tools/android/roll/android_deps/build.gradle +++ b/tools/android/roll/android_deps/build.gradle
@@ -82,6 +82,8 @@ // Androidx test libraries testCompile "androidx.test:core:1.0.0" testCompile "androidx.test:monitor:1.1.0" + testCompile "androidx.test:rules:1.1.0" + testCompile "androidx.test:runner:1.1.0" testCompile "androidx.test.ext:junit:1.0.0" }
diff --git a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 8fbb3ab..bd7a2086 100644 --- a/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/tools/android/roll/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -202,6 +202,17 @@ // a call to SplitCompat.install() into it. sb.append(' split_compat_class_names = [ "com/google/ar/core/InstallActivity" ]\n') break + case 'androidx_test_rules': + // Target needs Android SDK deps which exist in third_party/android_tools. + sb.append("""\ + | deps += [ + | "//third_party/android_tools:android_test_base_java", + | "//third_party/android_tools:android_test_mock_java", + | "//third_party/android_tools:android_test_runner_java", + | ] + | + |""".stripMargin()) + break } }
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index e823c9b9e..e271342 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -370,6 +370,9 @@ "third_party/blink/public/blink_resources.grd": { "includes": [25500], }, + "third_party/blink/renderer/modules/media_controls/non_touch/resources/media_controls_non_touch_resources.grd": { + "structures": [25590], + }, "third_party/blink/renderer/modules/media_controls/resources/media_controls_resources.grd": { "includes": [25600], "structures": [25700],
diff --git a/tools/json_to_struct/json_to_struct.gni b/tools/json_to_struct/json_to_struct.gni index 5ebda45..d923439 100644 --- a/tools/json_to_struct/json_to_struct.gni +++ b/tools/json_to_struct/json_to_struct.gni
@@ -61,5 +61,9 @@ deps = [ ":$action_name", ] + + if (defined(invoker.deps)) { + deps += invoker.deps + } } }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 68a70e9..a9e9d86 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -118,8 +118,8 @@ }, 'chromium.clang': { - 'CFI Linux CF': 'cfi_full_cfi_diag_recover_release_static', - 'CFI Linux ToT': 'clang_tot_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on', + 'CFI Linux CF': 'cfi_full_cfi_icall_cfi_diag_recover_release_static', + 'CFI Linux ToT': 'clang_tot_cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on', 'CrWinAsan': 'asan_clang_fuzzer_static_v8_heap_minimal_symbols_release_tot', 'CrWinAsan(dll)': 'asan_clang_shared_v8_heap_minimal_symbols_release_tot', @@ -449,7 +449,7 @@ 'chromium.memory': { 'Android CFI': 'android_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_goma', 'Linux ASan LSan Builder': 'asan_lsan_release_trybot', - 'Linux CFI': 'cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_goma', + 'Linux CFI': 'cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on_goma', 'Linux Chromium OS ASan LSan Builder': 'asan_lsan_chromeos_release_trybot', 'Linux ChromiumOS MSan Builder': 'chromeos_msan_release_bot', 'Linux MSan Builder': 'msan_release_bot', @@ -713,7 +713,7 @@ 'linux_arm': 'release_trybot_arm', 'linux_chromium_archive_rel_ng': 'release_bot', 'linux_chromium_asan_rel_ng': 'asan_lsan_release_trybot', - 'linux_chromium_cfi_rel_ng': 'cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_goma', + 'linux_chromium_cfi_rel_ng': 'cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on_goma', 'linux_chromium_chromeos_asan_rel_ng': 'asan_lsan_chromeos_release_trybot', 'linux_chromium_chromeos_msan_rel_ng': 'chromeos_msan_release_bot', 'linux_chromium_clobber_deterministic': 'release_trybot', @@ -1142,12 +1142,12 @@ 'cast', 'cast_audio', 'release_trybot', ], - 'cfi_full_cfi_diag_recover_release_static': [ - 'cfi_full', 'cfi_diag', 'cfi_recover', 'thin_lto', 'release', 'static', + 'cfi_full_cfi_icall_cfi_diag_recover_release_static': [ + 'cfi_full', 'cfi_icall', 'cfi_diag', 'cfi_recover', 'thin_lto', 'release', 'static', ], - 'cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_goma': [ - 'cfi_full', 'cfi_diag', 'thin_lto', 'release', 'static', 'dcheck_always_on', 'goma', + 'cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on_goma': [ + 'cfi_full', 'cfi_icall', 'cfi_diag', 'thin_lto', 'release', 'static', 'dcheck_always_on', 'goma', ], 'chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot': [ @@ -1187,8 +1187,8 @@ 'clang_tot', 'asan', 'lsan', 'static', 'release', ], - 'clang_tot_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on': [ - 'clang_tot', 'cfi_full', 'cfi_diag', 'thin_lto', 'release', 'static', 'dcheck_always_on', + 'clang_tot_cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on': [ + 'clang_tot', 'cfi_full', 'cfi_icall', 'cfi_diag', 'thin_lto', 'release', 'static', 'dcheck_always_on', ], 'clang_tot_win_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on': [ @@ -1919,6 +1919,10 @@ 'gn_args': 'use_cfi_cast=true', }, + 'cfi_icall': { + 'gn_args': 'use_cfi_icall=true', + }, + 'cfi_diag': { 'gn_args': 'use_cfi_diag=true', },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 1ecc61c..c37023c 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -20161,6 +20161,14 @@ <description>Please enter the description of this user action.</description> </action> +<action name="TabContextMenu_FocusMode"> + <owner>dfried@chromium.org</owner> + <owner>yiningwang@google.com</owner> + <description> + User selected Focus This Tab from the tab context menu. + </description> +</action> + <action name="TabContextMenu_MuteTabs"> <owner>miu@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index c4705069..dda3435 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -147,234 +147,510 @@ <summary> Track which Windows accessibility APIs are being called by clients. </summary> - <int value="0" label="UMA_API_ACC_DO_DEFAULT_ACTION">accDoDefaultAction</int> - <int value="1" label="UMA_API_ACC_HIT_TEST">accHitTest</int> - <int value="2" label="UMA_API_ACC_LOCATION">accLocation</int> - <int value="3" label="UMA_API_ACC_NAVIGATE">accNavigate</int> - <int value="4" label="UMA_API_ACC_SELECT">accSelect</int> - <int value="5" label="UMA_API_ADD_SELECTION">addSelection</int> + <int value="0" label="UMA_API_ACC_DO_DEFAULT_ACTION"> + MSAA accDoDefaultAction + </int> + <int value="1" label="UMA_API_ACC_HIT_TEST">MSAA accHitTest</int> + <int value="2" label="UMA_API_ACC_LOCATION">MSAA accLocation</int> + <int value="3" label="UMA_API_ACC_NAVIGATE">MSAA accNavigate</int> + <int value="4" label="UMA_API_ACC_SELECT">MSAA accSelect</int> + <int value="5" label="UMA_API_ADD_SELECTION">IA2 addSelection</int> <int value="6" label="UMA_API_CONVERT_RETURNED_ELEMENT"> - ConvertReturnedElement + UIA ConvertReturnedElement </int> - <int value="7" label="UMA_API_DO_ACTION">doAction</int> - <int value="8" label="UMA_API_GET_ACCESSIBLE_AT">get_accessibleAt</int> - <int value="9" label="UMA_API_GET_ACC_CHILD">get_accChild</int> - <int value="10" label="UMA_API_GET_ACC_CHILD_COUNT">get_accChildCount</int> + <int value="7" label="UMA_API_DO_ACTION">IA2 doAction</int> + <int value="8" label="UMA_API_GET_ACCESSIBLE_AT">IA2 get_accessibleAt</int> + <int value="9" label="UMA_API_GET_ACC_CHILD">MSAA get_accChild</int> + <int value="10" label="UMA_API_GET_ACC_CHILD_COUNT"> + MSAA get_accChildCount + </int> <int value="11" label="UMA_API_GET_ACC_DEFAULT_ACTION"> - get_accDefaultAction + MSAA get_accDefaultAction </int> - <int value="12" label="UMA_API_GET_ACC_DESCRIPTION">get_accDescription</int> - <int value="13" label="UMA_API_GET_ACC_FOCUS">get_accFocus</int> - <int value="14" label="UMA_API_GET_ACC_HELP">get_accHelp</int> - <int value="15" label="UMA_API_GET_ACC_HELP_TOPIC">get_accHelpTopic</int> + <int value="12" label="UMA_API_GET_ACC_DESCRIPTION"> + MSAA get_accDescription + </int> + <int value="13" label="UMA_API_GET_ACC_FOCUS">MSAA get_accFocus</int> + <int value="14" label="UMA_API_GET_ACC_HELP">MSAA get_accHelp</int> + <int value="15" label="UMA_API_GET_ACC_HELP_TOPIC">MSAA get_accHelpTopic</int> <int value="16" label="UMA_API_GET_ACC_KEYBOARD_SHORTCUT"> - get_accKeyboardShortcut + MSAA get_accKeyboardShortcut </int> - <int value="17" label="UMA_API_GET_ACC_NAME">get_accName</int> - <int value="18" label="UMA_API_GET_ACC_PARENT">get_accParent</int> - <int value="19" label="UMA_API_GET_ACC_ROLE">get_accRole</int> - <int value="20" label="UMA_API_GET_ACC_SELECTION">get_accSelection</int> - <int value="21" label="UMA_API_GET_ACC_STATE">get_accState</int> - <int value="22" label="UMA_API_GET_ACC_VALUE">get_accValue</int> - <int value="23" label="UMA_API_GET_ANCHOR">get_anchor</int> - <int value="24" label="UMA_API_GET_ANCHOR_TARGET">get_anchorTarget</int> - <int value="25" label="UMA_API_GET_APP_NAME">get_appName</int> - <int value="26" label="UMA_API_GET_APP_VERSION">get_appVersion</int> + <int value="17" label="UMA_API_GET_ACC_NAME">MSAA get_accName</int> + <int value="18" label="UMA_API_GET_ACC_PARENT">MSAA get_accParent</int> + <int value="19" label="UMA_API_GET_ACC_ROLE">MSAA get_accRole</int> + <int value="20" label="UMA_API_GET_ACC_SELECTION">MSAA get_accSelection</int> + <int value="21" label="UMA_API_GET_ACC_STATE">MSAA get_accState</int> + <int value="22" label="UMA_API_GET_ACC_VALUE">MSAA get_accValue</int> + <int value="23" label="UMA_API_GET_ANCHOR">IA2 get_anchor</int> + <int value="24" label="UMA_API_GET_ANCHOR_TARGET">IA2 get_anchorTarget</int> + <int value="25" label="UMA_API_GET_APP_NAME">IA2 get_appName</int> + <int value="26" label="UMA_API_GET_APP_VERSION">IA2 get_appVersion</int> <int value="27" label="UMA_API_GET_ATTRIBUTES_FOR_NAMES"> - get_attributesForNames + ISDN get_attributesForNames </int> - <int value="28" label="UMA_API_GET_CAPTION">get_caption</int> - <int value="29" label="UMA_API_GET_CARET_OFFSET">get_caretOffset</int> - <int value="30" label="UMA_API_GET_CELL_AT">get_cellAt</int> + <int value="28" label="UMA_API_GET_CAPTION">IA2 get_caption</int> + <int value="29" label="UMA_API_GET_CARET_OFFSET">IA2 get_caretOffset</int> + <int value="30" label="UMA_API_GET_CELL_AT">IA2 get_cellAt</int> <int value="31" label="UMA_API_GET_CHARACTER_EXTENTS"> - get_characterExtents + IA2 get_characterExtents </int> - <int value="32" label="UMA_API_GET_CHILD_AT">get_childAt</int> - <int value="33" label="UMA_API_GET_CHILD_INDEX">get_childIndex</int> + <int value="32" label="UMA_API_GET_CHILD_AT">ISDN get_childAt</int> + <int value="33" label="UMA_API_GET_CHILD_INDEX">IA2 get_childIndex</int> <int value="34" label="UMA_API_GET_CLIPPED_SUBSTRING_BOUNDS"> - get_clippedSubstringBounds + IA2 get_clippedSubstringBounds </int> <int value="35" label="UMA_API_GET_COLUMN_DESCRIPTION"> - get_columnDescription + IA2 get_columnDescription </int> - <int value="36" label="UMA_API_GET_COLUMN_EXTENT">get_columnExtent</int> - <int value="37" label="UMA_API_GET_COLUMN_EXTENT_AT">get_columnExtentAt</int> - <int value="38" label="UMA_API_GET_COLUMN_HEADER">get_columnHeader</int> + <int value="36" label="UMA_API_GET_COLUMN_EXTENT">IA2 get_columnExtent</int> + <int value="37" label="UMA_API_GET_COLUMN_EXTENT_AT"> + IA2 get_columnExtentAt + </int> + <int value="38" label="UMA_API_GET_COLUMN_HEADER">IA2 get_columnHeader</int> <int value="39" label="UMA_API_GET_COLUMN_HEADER_CELLS"> - get_columnHeaderCells + IA2 get_columnHeaderCells </int> - <int value="40" label="UMA_API_GET_COLUMN_INDEX">get_columnIndex</int> - <int value="41" label="UMA_API_GET_COMPUTED_STYLE">get_computedStyle</int> + <int value="40" label="UMA_API_GET_COLUMN_INDEX">IA2 get_columnIndex</int> + <int value="41" label="UMA_API_GET_COMPUTED_STYLE"> + ISDN get_computedStyle + </int> <int value="42" label="UMA_API_GET_COMPUTED_STYLE_FOR_PROPERTIES"> - get_computedStyleForProperties + ISDN get_computedStyleForProperties </int> - <int value="43" label="UMA_API_GET_CURRENT_VALUE">get_currentValue</int> - <int value="44" label="UMA_API_GET_DESCRIPTION">get_description</int> - <int value="45" label="UMA_API_GET_DOC_TYPE">get_docType</int> - <int value="46" label="UMA_API_GET_DOM_TEXT">get_domText</int> - <int value="47" label="UMA_API_GET_END_INDEX">get_endIndex</int> - <int value="48" label="UMA_API_GET_EXTENDED_ROLE">get_extendedRole</int> - <int value="49" label="UMA_API_GET_EXTENDED_STATES">get_extendedStates</int> - <int value="50" label="UMA_API_GET_FIRST_CHILD">get_firstChild</int> - <int value="51" label="UMA_API_GET_FONT_FAMILY">get_fontFamily</int> - <int value="52" label="UMA_API_GET_GROUP_POSITION">get_groupPosition</int> + <int value="43" label="UMA_API_GET_CURRENT_VALUE">IA2 get_currentValue</int> + <int value="44" label="UMA_API_GET_DESCRIPTION">IA2 get_description</int> + <int value="45" label="UMA_API_GET_DOC_TYPE">IA2 get_docType</int> + <int value="46" label="UMA_API_GET_DOM_TEXT">IA2 get_domText</int> + <int value="47" label="UMA_API_GET_END_INDEX">IA2 get_endIndex</int> + <int value="48" label="UMA_API_GET_EXTENDED_ROLE">IA2 get_extendedRole</int> + <int value="49" label="UMA_API_GET_EXTENDED_STATES"> + IA2 get_extendedStates + </int> + <int value="50" label="UMA_API_GET_FIRST_CHILD">ISDN get_firstChild</int> + <int value="51" label="UMA_API_GET_FONT_FAMILY">IA2 get_fontFamily</int> + <int value="52" label="UMA_API_GET_GROUP_POSITION">IA2 get_groupPosition</int> <int value="53" label="UMA_API_GET_HOST_RAW_ELEMENT_PROVIDER"> - get_HostRawElementProvider + UIA get_HostRawElementProvider </int> - <int value="54" label="UMA_API_GET_HYPERLINK">get_hyperlink</int> - <int value="55" label="UMA_API_GET_HYPERLINK_INDEX">get_hyperlinkIndex</int> + <int value="54" label="UMA_API_GET_HYPERLINK">IA2 get_hyperlink</int> + <int value="55" label="UMA_API_GET_HYPERLINK_INDEX"> + IA2 get_hyperlinkIndex + </int> <int value="56" label="UMA_API_GET_IACCESSIBLE_PAIR"> - GetIAccessiblePair ALT + UIA GetIAccessiblePair ALT </int> - <int value="57" label="UMA_API_GET_IMAGE_POSITION">get_imagePosition</int> - <int value="58" label="UMA_API_GET_IMAGE_SIZE">get_imageSize</int> - <int value="59" label="UMA_API_GET_INDEX_IN_PARENT">get_indexInParent</int> - <int value="60" label="UMA_API_GET_INNER_HTML">get_innerHTML</int> + <int value="57" label="UMA_API_GET_IMAGE_POSITION">IA2 get_imagePosition</int> + <int value="58" label="UMA_API_GET_IMAGE_SIZE">IA2 get_imageSize</int> + <int value="59" label="UMA_API_GET_INDEX_IN_PARENT"> + IA2 get_indexInParent + </int> + <int value="60" label="UMA_API_GET_INNER_HTML">ISDN get_innerHTML</int> <int value="61" label="UMA_API_GET_IS_COLUMN_SELECTED"> - get_isColumnSelected + IA2 get_isColumnSelected </int> - <int value="62" label="UMA_API_GET_IS_ROW_SELECTED">get_isRowSelected</int> - <int value="63" label="UMA_API_GET_IS_SELECTED">get_isSelected</int> - <int value="64" label="UMA_API_GET_KEY_BINDING">get_keyBinding</int> - <int value="65" label="UMA_API_GET_LANGUAGE">get_language</int> - <int value="66" label="UMA_API_GET_LAST_CHILD">get_lastChild</int> - <int value="67" label="UMA_API_GET_LOCALE">get_locale</int> + <int value="62" label="UMA_API_GET_IS_ROW_SELECTED"> + IA2 get_isRowSelected + </int> + <int value="63" label="UMA_API_GET_IS_SELECTED">IA2 get_isSelected</int> + <int value="64" label="UMA_API_GET_KEY_BINDING">IA2 get_keyBinding</int> + <int value="65" label="UMA_API_GET_LANGUAGE">ISDN get_language</int> + <int value="66" label="UMA_API_GET_LAST_CHILD">ISDN get_lastChild</int> + <int value="67" label="UMA_API_GET_LOCALE">IA2 get_locale</int> <int value="68" label="UMA_API_GET_LOCALIZED_EXTENDED_ROLE"> - get_localizedExtendedRole + IA2 get_localizedExtendedRole </int> <int value="69" label="UMA_API_GET_LOCALIZED_EXTENDED_STATES"> - get_localizedExtendedStates + IA2 get_localizedExtendedStates </int> - <int value="70" label="UMA_API_GET_LOCALIZED_NAME">get_localizedName</int> - <int value="71" label="UMA_API_GET_LOCAL_INTERFACE">get_localInterface</int> - <int value="72" label="UMA_API_GET_MAXIMUM_VALUE">get_maximumValue</int> - <int value="73" label="UMA_API_GET_MIME_TYPE">get_mimeType</int> - <int value="74" label="UMA_API_GET_MINIMUM_VALUE">get_minimumValue</int> - <int value="75" label="UMA_API_GET_NAME">get_name</int> + <int value="70" label="UMA_API_GET_LOCALIZED_NAME">IA2 get_localizedName</int> + <int value="71" label="UMA_API_GET_LOCAL_INTERFACE"> + ISDN get_localInterface + </int> + <int value="72" label="UMA_API_GET_MAXIMUM_VALUE">IA2 get_maximumValue</int> + <int value="73" label="UMA_API_GET_MIME_TYPE">IA2 get_mimeType</int> + <int value="74" label="UMA_API_GET_MINIMUM_VALUE">IA2 get_minimumValue</int> + <int value="75" label="UMA_API_GET_NAME">IA2 get_name</int> <int value="76" label="UMA_API_GET_NAMESPACE_URI_FOR_ID"> - get_nameSpaceURIForID ALT + IA2 get_nameSpaceURIForID ALT </int> - <int value="77" label="UMA_API_GET_NEW_TEXT">get_newText</int> - <int value="78" label="UMA_API_GET_NEXT_SIBLING">get_nextSibling</int> - <int value="79" label="UMA_API_GET_NODE_INFO">get_nodeInfo</int> - <int value="80" label="UMA_API_GET_N_CHARACTERS">get_nCharacters</int> - <int value="81" label="UMA_API_GET_N_COLUMNS">get_nColumns</int> + <int value="77" label="UMA_API_GET_NEW_TEXT">IA2 get_newText</int> + <int value="78" label="UMA_API_GET_NEXT_SIBLING">ISDN get_nextSibling</int> + <int value="79" label="UMA_API_GET_NODE_INFO">ISDN get_nodeInfo</int> + <int value="80" label="UMA_API_GET_N_CHARACTERS">IA2 get_nCharacters</int> + <int value="81" label="UMA_API_GET_N_COLUMNS">IA2 get_nColumns</int> <int value="82" label="UMA_API_GET_N_EXTENDED_STATES"> - get_nExtendedStates + IA2 get_nExtendedStates </int> - <int value="83" label="UMA_API_GET_N_HYPERLINKS">get_nHyperlinks</int> - <int value="84" label="UMA_API_GET_N_RELATIONS">get_nRelations</int> - <int value="85" label="UMA_API_GET_N_ROWS">get_nRows</int> - <int value="86" label="UMA_API_GET_N_SELECTED_CELLS">get_nSelectedCells</int> + <int value="83" label="UMA_API_GET_N_HYPERLINKS">IA2 get_nHyperlinks</int> + <int value="84" label="UMA_API_GET_N_RELATIONS">IA2 get_nRelations</int> + <int value="85" label="UMA_API_GET_N_ROWS">IA2 get_nRows</int> + <int value="86" label="UMA_API_GET_N_SELECTED_CELLS"> + IA2 get_nSelectedCells + </int> <int value="87" label="UMA_API_GET_N_SELECTED_CHILDREN"> - get_nSelectedChildren + IA2 get_nSelectedChildren </int> <int value="88" label="UMA_API_GET_N_SELECTED_COLUMNS"> - get_nSelectedColumns + IA2 get_nSelectedColumns </int> - <int value="89" label="UMA_API_GET_N_SELECTED_ROWS">get_nSelectedRows</int> - <int value="90" label="UMA_API_GET_N_SELECTIONS">get_nSelections</int> - <int value="91" label="UMA_API_GET_OBJECT_FOR_CHILD">GetObjectForChild</int> - <int value="92" label="UMA_API_GET_OFFSET_AT_POINT">get_offsetAtPoint</int> - <int value="93" label="UMA_API_GET_OLD_TEXT">get_oldText</int> - <int value="94" label="UMA_API_GET_PARENT_NODE">get_parentNode</int> - <int value="95" label="UMA_API_GET_PATTERN_PROVIDER">GetPatternProvider</int> - <int value="96" label="UMA_API_GET_PREVIOUS_SIBLING">get_previousSibling</int> - <int value="97" label="UMA_API_GET_PROPERTY_VALUE">GetPropertyValue</int> - <int value="98" label="UMA_API_GET_PROVIDER_OPTIONS">get_ProviderOptions</int> - <int value="99" label="UMA_API_GET_RELATION">get_relation</int> - <int value="100" label="UMA_API_GET_RELATIONS">get_relations</int> + <int value="89" label="UMA_API_GET_N_SELECTED_ROWS"> + IA2 get_nSelectedRows + </int> + <int value="90" label="UMA_API_GET_N_SELECTIONS">IA2 get_nSelections</int> + <int value="91" label="UMA_API_GET_OBJECT_FOR_CHILD"> + UIA GetObjectForChild + </int> + <int value="92" label="UMA_API_GET_OFFSET_AT_POINT"> + IA2 get_offsetAtPoint + </int> + <int value="93" label="UMA_API_GET_OLD_TEXT">IA2 get_oldText</int> + <int value="94" label="UMA_API_GET_PARENT_NODE">ISDN get_parentNode</int> + <int value="95" label="UMA_API_GET_PATTERN_PROVIDER"> + UIA GetPatternProvider + </int> + <int value="96" label="UMA_API_GET_PREVIOUS_SIBLING"> + ISDN get_previousSibling + </int> + <int value="97" label="UMA_API_GET_PROPERTY_VALUE">UIA GetPropertyValue</int> + <int value="98" label="UMA_API_GET_PROVIDER_OPTIONS"> + UIA get_ProviderOptions + </int> + <int value="99" label="UMA_API_GET_RELATION">IA2 get_relation</int> + <int value="100" label="UMA_API_GET_RELATIONS">IA2 get_relations</int> <int value="101" label="UMA_API_GET_ROW_COLUMN_EXTENTS"> - get_rowColumnExtents + IA2 get_rowColumnExtents </int> <int value="102" label="UMA_API_GET_ROW_COLUMN_EXTENTS_AT_INDEX"> - get_rowColumnExtentsAtIndex + IA2 get_rowColumnExtentsAtIndex </int> - <int value="103" label="UMA_API_GET_ROW_DESCRIPTION">get_rowDescription</int> - <int value="104" label="UMA_API_GET_ROW_EXTENT">get_rowExtent</int> - <int value="105" label="UMA_API_GET_ROW_EXTENT_AT">get_rowExtentAt</int> - <int value="106" label="UMA_API_GET_ROW_HEADER">get_rowHeader</int> - <int value="107" label="UMA_API_GET_ROW_HEADER_CELLS">get_rowHeaderCells</int> - <int value="108" label="UMA_API_GET_ROW_INDEX">get_rowIndex</int> - <int value="109" label="UMA_API_GET_RUNTIME_ID">GetRuntimeId</int> - <int value="110" label="UMA_API_GET_SELECTED_CELLS">get_selectedCells</int> + <int value="103" label="UMA_API_GET_ROW_DESCRIPTION"> + IA2 get_rowDescription + </int> + <int value="104" label="UMA_API_GET_ROW_EXTENT">IA2 get_rowExtent</int> + <int value="105" label="UMA_API_GET_ROW_EXTENT_AT">IA2 get_rowExtentAt</int> + <int value="106" label="UMA_API_GET_ROW_HEADER">IA2 get_rowHeader</int> + <int value="107" label="UMA_API_GET_ROW_HEADER_CELLS"> + IA2 get_rowHeaderCells + </int> + <int value="108" label="UMA_API_GET_ROW_INDEX">IA2 get_rowIndex</int> + <int value="109" label="UMA_API_GET_RUNTIME_ID">UIA GetRuntimeId</int> + <int value="110" label="UMA_API_GET_SELECTED_CELLS"> + IA2 get_selectedCells + </int> <int value="111" label="UMA_API_GET_SELECTED_CHILDREN"> - get_selectedChildren + IA2 get_selectedChildren </int> <int value="112" label="UMA_API_GET_SELECTED_COLUMNS"> - get_selectedColumns + IA2 get_selectedColumns </int> - <int value="113" label="UMA_API_GET_SELECTED_ROWS">get_selectedRows</int> - <int value="114" label="UMA_API_GET_SELECTION">get_selection</int> - <int value="115" label="UMA_API_GET_START_INDEX">get_startIndex</int> - <int value="116" label="UMA_API_GET_STATES">get_states</int> - <int value="117" label="UMA_API_GET_SUMMARY">get_summary</int> - <int value="118" label="UMA_API_GET_TABLE">get_table</int> - <int value="119" label="UMA_API_GET_TEXT">get_text</int> + <int value="113" label="UMA_API_GET_SELECTED_ROWS">IA2 get_selectedRows</int> + <int value="114" label="UMA_API_GET_SELECTION">IA2 get_selection</int> + <int value="115" label="UMA_API_GET_START_INDEX">IA2 get_startIndex</int> + <int value="116" label="UMA_API_GET_STATES">IA2 get_states</int> + <int value="117" label="UMA_API_GET_SUMMARY">IA2 get_summary</int> + <int value="118" label="UMA_API_GET_TABLE">IA2 get_table</int> + <int value="119" label="UMA_API_GET_TEXT">IA2 get_text</int> <int value="120" label="UMA_API_GET_TEXT_AFTER_OFFSET"> - get_textAfterOffset + IA2 get_textAfterOffset </int> - <int value="121" label="UMA_API_GET_TEXT_AT_OFFSET">get_textAtOffset</int> + <int value="121" label="UMA_API_GET_TEXT_AT_OFFSET">IA2 get_textAtOffset</int> <int value="122" label="UMA_API_GET_TEXT_BEFORE_OFFSET"> - get_textBeforeOffset + IA2 get_textBeforeOffset </int> - <int value="123" label="UMA_API_GET_TITLE">get_title</int> - <int value="124" label="UMA_API_GET_TOOLKIT_NAME">get_toolkitName</int> - <int value="125" label="UMA_API_GET_TOOLKIT_VERSION">get_toolkitVersion</int> + <int value="123" label="UMA_API_GET_TITLE">IA2 get_title</int> + <int value="124" label="UMA_API_GET_TOOLKIT_NAME">IA2 get_toolkitName</int> + <int value="125" label="UMA_API_GET_TOOLKIT_VERSION"> + IA2 get_toolkitVersion + </int> <int value="126" label="UMA_API_GET_UNCLIPPED_SUBSTRING_BOUNDS"> - get_unclippedSubstringBounds + IA2 get_unclippedSubstringBounds </int> - <int value="127" label="UMA_API_GET_UNIQUE_ID">get_uniqueID</int> - <int value="128" label="UMA_API_GET_URL">get_URL</int> - <int value="129" label="UMA_API_GET_VALID">get_valid</int> - <int value="130" label="UMA_API_GET_WINDOW_HANDLE">get_windowHandle</int> - <int value="131" label="UMA_API_IA2_GET_ATTRIBUTES">get_attributes ALT</int> - <int value="132" label="UMA_API_IA2_SCROLL_TO">scrollTo ALT</int> + <int value="127" label="UMA_API_GET_UNIQUE_ID">IA2 get_uniqueID</int> + <int value="128" label="UMA_API_GET_URL">IA2 get_URL</int> + <int value="129" label="UMA_API_GET_VALID">IA2 get_valid</int> + <int value="130" label="UMA_API_GET_WINDOW_HANDLE">IA2 get_windowHandle</int> + <int value="131" label="UMA_API_IA2_GET_ATTRIBUTES"> + IA2 get_attributes ALT + </int> + <int value="132" label="UMA_API_IA2_SCROLL_TO">IA2 scrollTo ALT</int> <int value="133" label="UMA_API_IAACTION_GET_DESCRIPTION"> - get_description ALT + IA2 get_description ALT </int> <int value="134" label="UMA_API_IATEXT_GET_ATTRIBUTES"> - get_attributes ALT + IA2 get_attributes ALT </int> <int value="135" label="UMA_API_ISIMPLEDOMNODE_GET_ATTRIBUTES"> - get_attributes ALT + ISDN get_attributes ALT </int> - <int value="136" label="UMA_API_ISIMPLEDOMNODE_SCROLL_TO">scrollTo ALT</int> - <int value="137" label="UMA_API_N_ACTIONS">nActions</int> + <int value="136" label="UMA_API_ISIMPLEDOMNODE_SCROLL_TO"> + ISDN scrollTo ALT + </int> + <int value="137" label="UMA_API_N_ACTIONS">IA2 nActions</int> <int value="138" label="UMA_API_PUT_ALTERNATE_VIEW_MEDIA_TYPES"> - put_alternateViewMediaTypes + IA2 put_alternateViewMediaTypes </int> <int value="139" label="UMA_API_QUERY_SERVICE">QueryService</int> - <int value="140" label="UMA_API_REMOVE_SELECTION">removeSelection</int> - <int value="141" label="UMA_API_ROLE">role</int> - <int value="142" label="UMA_API_SCROLL_SUBSTRING_TO">scrollSubstringTo</int> - <int value="143" label="UMA_API_SCROLL_SUBSTRING_TO_POINT"> - scrollSubstringToPoint + <int value="140" label="UMA_API_REMOVE_SELECTION">IA2 removeSelection</int> + <int value="141" label="UMA_API_ROLE">IA2 role</int> + <int value="142" label="UMA_API_SCROLL_SUBSTRING_TO"> + IA2 scrollSubstringTo </int> - <int value="144" label="UMA_API_SCROLL_TO_POINT">scrollToPoint</int> - <int value="145" label="UMA_API_SCROLL_TO_SUBSTRING">scrollToSubstring</int> - <int value="146" label="UMA_API_SELECT_COLUMN">selectColumn</int> - <int value="147" label="UMA_API_SELECT_ROW">selectRow</int> - <int value="148" label="UMA_API_SET_CARET_OFFSET">setCaretOffset</int> - <int value="149" label="UMA_API_SET_CURRENT_VALUE">setCurrentValue</int> - <int value="150" label="UMA_API_SET_SELECTION">setSelection</int> + <int value="143" label="UMA_API_SCROLL_SUBSTRING_TO_POINT"> + IA2 scrollSubstringToPoint + </int> + <int value="144" label="UMA_API_SCROLL_TO_POINT">IA2 scrollToPoint</int> + <int value="145" label="UMA_API_SCROLL_TO_SUBSTRING"> + IA2 scrollToSubstring + </int> + <int value="146" label="UMA_API_SELECT_COLUMN">IA2 selectColumn</int> + <int value="147" label="UMA_API_SELECT_ROW">IA2 selectRow</int> + <int value="148" label="UMA_API_SET_CARET_OFFSET">IA2 setCaretOffset</int> + <int value="149" label="UMA_API_SET_CURRENT_VALUE">IA2 setCurrentValue</int> + <int value="150" label="UMA_API_SET_SELECTION">IA2 setSelection</int> <int value="151" label="UMA_API_TABLE2_GET_SELECTED_COLUMNS"> - get_selectedColumns ALT + IA2 get_selectedColumns ALT </int> <int value="152" label="UMA_API_TABLE2_GET_SELECTED_ROWS"> - get_selectedRows ALT + IA2 get_selectedRows ALT </int> <int value="153" label="UMA_API_TABLECELL_GET_COLUMN_INDEX"> - get_columnIndex ALT + IA2 get_columnIndex ALT </int> <int value="154" label="UMA_API_TABLECELL_GET_IS_SELECTED"> - get_isSelected ALT + IA2 get_isSelected ALT </int> <int value="155" label="UMA_API_TABLECELL_GET_ROW_INDEX"> - get_rowIndex ALT + IA2 get_rowIndex ALT </int> - <int value="156" label="UMA_API_UNSELECT_COLUMN">unselectColumn</int> - <int value="157" label="UMA_API_UNSELECT_ROW">unselectRow</int> + <int value="156" label="UMA_API_UNSELECT_COLUMN">IA2 unselectColumn</int> + <int value="157" label="UMA_API_UNSELECT_ROW">IA2 unselectRow</int> + <int value="158" label="UMA_API_GET_BOUNDINGRECTANGLE"> + UIA get_BoundingRectangle + </int> + <int value="159" label="UMA_API_GET_FRAGMENTROOT">UIA get_FragmentRoot</int> + <int value="160" label="UMA_API_GETEMBEDDEDFRAGMENTROOTS"> + UIA GetEmbeddedFragmentRoots + </int> + <int value="161" label="UMA_API_NAVIGATE">UIA Navigate</int> + <int value="162" label="UMA_API_SETFOCUS">UIA SetFocus</int> + <int value="163" label="UMA_API_SHOWCONTEXTMENU">UIA ShowContextMenu</int> + <int value="164" label="UMA_API_EXPANDCOLLAPSE_COLLAPSE"> + UIA ExpandCollapse.Collapse + </int> + <int value="165" label="UMA_API_EXPANDCOLLAPSE_EXPAND"> + UIA ExpandCollapse.Expand + </int> + <int value="166" label="UMA_API_EXPANDCOLLAPSE_GET_EXPANDCOLLAPSESTATE"> + UIA ExpandCollapse.get_ExpandCollapseState + </int> + <int value="167" label="UMA_API_GRIDITEM_GET_COLUMN"> + UIA GridItem.get_Column + </int> + <int value="168" label="UMA_API_GRIDITEM_GET_COLUMNSPAN"> + UIA GridItem.get_ColumnSpan + </int> + <int value="169" label="UMA_API_GRIDITEM_GET_CONTAININGGRID"> + UIA GridItem.get_ContainingGrid + </int> + <int value="170" label="UMA_API_GRIDITEM_GET_ROW">UIA GridItem.get_Row</int> + <int value="171" label="UMA_API_GRIDITEM_GET_ROWSPAN"> + UIA GridItem.get_RowSpan + </int> + <int value="172" label="UMA_API_GRID_GETITEM">UIA Grid.GetItem</int> + <int value="173" label="UMA_API_GRID_GET_ROWCOUNT">UIA Grid.get_RowCount</int> + <int value="174" label="UMA_API_GRID_GET_COLUMNCOUNT"> + UIA Grid.get_ColumnCount + </int> + <int value="175" label="UMA_API_INVOKE_INVOKE">UIA Invoke.Invoke</int> + <int value="176" label="UMA_API_RANGEVALUE_SETVALUE"> + UIA RangeValue.SetValue + </int> + <int value="177" label="UMA_API_RANGEVALUE_GET_LARGECHANGE"> + UIA RangeValue.get_LargeChange + </int> + <int value="178" label="UMA_API_RANGEVALUE_GET_MAXIMUM"> + UIA RangeValue.get_Maximum + </int> + <int value="179" label="UMA_API_RANGEVALUE_GET_MINIMUM"> + UIA RangeValue.get_Minimum + </int> + <int value="180" label="UMA_API_RANGEVALUE_GET_SMALLCHANGE"> + UIA RangeValue.get_SmallChange + </int> + <int value="181" label="UMA_API_RANGEVALUE_GET_VALUE"> + UIA RangeValue.get_Value + </int> + <int value="182" label="UMA_API_SCROLLITEM_SCROLLINTOVIEW"> + UIA ScrollItem.ScrollIntoView + </int> + <int value="183" label="UMA_API_SCROLL_SCROLL">UIA Scroll.Scroll</int> + <int value="184" label="UMA_API_SCROLL_SETSCROLLPERCENT"> + UIA Scroll.SetScrollPercent + </int> + <int value="185" label="UMA_API_SCROLL_GET_HORIZONTALLYSCROLLABLE"> + UIA Scroll.get_HorizontallyScrollable + </int> + <int value="186" label="UMA_API_SCROLL_GET_HORIZONTALSCROLLPERCENT"> + UIA Scroll.get_HorizontalScrollPercent + </int> + <int value="187" label="UMA_API_SCROLL_GET_HORIZONTALVIEWSIZE"> + UIA Scroll.get_HorizontalViewSize + </int> + <int value="188" label="UMA_API_SCROLL_GET_VERTICALLYSCROLLABLE"> + UIA Scroll.get_VerticallyScrollable + </int> + <int value="189" label="UMA_API_SCROLL_GET_VERTICALSCROLLPERCENT"> + UIA Scroll.get_VerticalScrollPercent + </int> + <int value="190" label="UMA_API_SCROLL_GET_VERTICALVIEWSIZE"> + UIA Scroll.get_VerticalViewSize + </int> + <int value="191" label="UMA_API_SELECTIONITEM_ADDTOSELECTION"> + UIA SelectionItem.AddToSelection + </int> + <int value="192" label="UMA_API_SELECTIONITEM_REMOVEFROMSELECTION"> + UIA SelectionItem.RemoveFromSelection + </int> + <int value="193" label="UMA_API_SELECTIONITEM_SELECT"> + UIA SelectionItem.Select + </int> + <int value="194" label="UMA_API_SELECTIONITEM_GET_ISSELECTED"> + UIA SelectionItem.get_IsSelected + </int> + <int value="195" label="UMA_API_SELECTIONITEM_GET_SELECTIONCONTAINER"> + UIA SelectionItem.get_SelectionContainer + </int> + <int value="196" label="UMA_API_SELECTION_GETSELECTION"> + UIA Selection.GetSelection + </int> + <int value="197" label="UMA_API_SELECTION_GET_CANSELECTMULTIPLE"> + UIA Selection.get_CanSelectMultiple + </int> + <int value="198" label="UMA_API_SELECTION_GET_ISSELECTIONREQUIRED"> + UIA Selection.get_IsSelectionRequired + </int> + <int value="199" label="UMA_API_TABLEITEM_GETCOLUMNHEADERITEMS"> + UIA TableItem.GetColumnHeaderItems + </int> + <int value="200" label="UMA_API_TABLEITEM_GETROWHEADERITEMS"> + UIA TableItem.GetRowHeaderItems + </int> + <int value="201" label="UMA_API_TABLE_GETCOLUMNHEADERS"> + UIA Table.GetColumnGeaders + </int> + <int value="202" label="UMA_API_TABLE_GETROWHEADERS"> + UIA Table.GetRowHeaders + </int> + <int value="203" label="UMA_API_TABLE_GET_ROWORCOLUMNMAJOR"> + UIA Table.get_RowOrColumnMajor + </int> + <int value="204" label="UMA_API_TEXT_GETSELECTION">UIA Text.GetSelection</int> + <int value="205" label="UMA_API_TEXT_GETVISIBLERANGES"> + UIA Text.GetVisibleRanges + </int> + <int value="206" label="UMA_API_TEXT_RANGEFROMCHILD"> + UIA Text.RangeFromChild + </int> + <int value="207" label="UMA_API_TEXT_RANGEFROMPOINT"> + UIA Text.RangeFromPoint + </int> + <int value="208" label="UMA_API_TEXT_GET_DOCUMENTRANGE"> + UIA Text.get_DocumentRange + </int> + <int value="209" label="UMA_API_TEXT_GET_SUPPORTEDTEXTSELECTION"> + UIA Text.get_SupportedTextSelection + </int> + <int value="210" label="UMA_API_TEXTCHILD_GET_TEXTCONTAINER"> + UIA TextChild.get_TextContainer + </int> + <int value="211" label="UMA_API_TEXTCHILD_GET_TEXTRANGE"> + UIA TextChild.get_TextRange + </int> + <int value="212" label="UMA_API_TEXTEDIT_GETACTIVECOMPOSITION"> + UIA TextEdit.GetActiveComposition + </int> + <int value="213" label="UMA_API_TEXTEDIT_GETCONVERSIONTARGET"> + UIA TextEdit.GetConversionTarget + </int> + <int value="214" label="UMA_API_TEXTRANGE_CLONE">UIA TextRange.Clone</int> + <int value="215" label="UMA_API_TEXTRANGE_COMPARE">UIA TextRange.Compare</int> + <int value="216" label="UMA_API_TEXTRANGE_COMPAREENDPOINTS"> + UIA TextRange.CompareEndpoints + </int> + <int value="217" label="UMA_API_TEXTRANGE_EXPANDTOENCLOSINGUNIT"> + UIA TextRange.ExpandToEnclosingUnit + </int> + <int value="218" label="UMA_API_TEXTRANGE_FINDATTRIBUTE"> + UIA TextRange.FindAttribute + </int> + <int value="219" label="UMA_API_TEXTRANGE_FINDTEXT"> + UIA TextRange.FindText + </int> + <int value="220" label="UMA_API_TEXTRANGE_GETATTRIBUTEVALUE"> + UIA TextChange.GetAttributeValue + </int> + <int value="221" label="UMA_API_TEXTRANGE_GETBOUNDINGRECTANGLES"> + UIA TextRange.GetBoundingRectangles + </int> + <int value="222" label="UMA_API_TEXTRANGE_GETENCLOSINGELEMENT"> + UIA TextRange.GetEnclosingElement + </int> + <int value="223" label="UMA_API_TEXTRANGE_GETTEXT">UIA TextRange.GetText</int> + <int value="224" label="UMA_API_TEXTRANGE_MOVE">UIA TextRange.Move</int> + <int value="225" label="UMA_API_TEXTRANGE_MOVEENDPOINTBYUNIT"> + UIA TextRange.MoveEndpointByUnit + </int> + <int value="226" label="UMA_API_TEXTRANGE_MOVEENPOINTBYRANGE"> + UIA TextRange.MoveEndpointByRange + </int> + <int value="227" label="UMA_API_TEXTRANGE_SELECT">UIA TextRange.Select</int> + <int value="228" label="UMA_API_TEXTRANGE_ADDTOSELECTION"> + UIA TextRange.AddToSelection + </int> + <int value="229" label="UMA_API_TEXTRANGE_REMOVEFROMSELECTION"> + UIA TextRange.RemoveFromSelection + </int> + <int value="230" label="UMA_API_TEXTRANGE_SCROLLINTOVIEW"> + UIA TextRange.ScrollIntoView + </int> + <int value="231" label="UMA_API_TEXTRANGE_GETCHILDREN"> + UIA TextRange.GetChildren + </int> + <int value="232" label="UMA_API_TOGGLE_TOGGLE">UIA Toggle.Toggle</int> + <int value="233" label="UMA_API_TOGGLE_GET_TOGGLESTATE"> + UIA Toggle.get_ToggleState + </int> + <int value="234" label="UMA_API_VALUE_SETVALUE">UIA Value.SetValue</int> + <int value="235" label="UMA_API_VALUE_GET_ISREADONLY"> + UIA Value.get_IsReadOnly + </int> + <int value="236" label="UMA_API_VALUE_GET_VALUE">UIA Value.get_Value</int> + <int value="237" label="UMA_API_WINDOW_SETVISUALSTATE"> + UIA Window.SetVisualState + </int> + <int value="238" label="UMA_API_WINDOW_CLOSE">UIA Window.Close</int> + <int value="239" label="UMA_API_WINDOW_WAITFORINPUTIDLE"> + UIA Window.WaitForInputIdle + </int> + <int value="240" label="UMA_API_WINDOW_GET_CANMAXIMIZE"> + UIA Window.get_CanMaximize + </int> + <int value="241" label="UMA_API_WINDOW_GET_CANMINIMIZE"> + UIA Window.get_CanMinimize + </int> + <int value="242" label="UMA_API_WINDOW_GET_ISMODAL"> + UIA Window.get_IsModal + </int> + <int value="243" label="UMA_API_WINDOW_GET_WINDOWVISUALSTATE"> + UIA Window.get_WindowVisualState + </int> + <int value="244" label="UMA_API_WINDOW_GET_WINDOWINTERACTIONSTATE"> + UIA Window.get_WindowInteractionState + </int> + <int value="245" label="UMA_API_WINDOW_GET_ISTOPMOST"> + UIA Window.get_IsTopmost + </int> </enum> <enum name="AccessibilityWinAPIGetPropertyValueEnum"> @@ -1806,17 +2082,31 @@ </enum> <enum name="AppListSearchResult"> - <int value="0" label="OMNIBOX"/> - <int value="1" label="APP"/> - <int value="2" label="WEBSTORE"/> - <int value="3" label="SEARCH_WEBSTORE"/> - <int value="4" label="SEARCH_PEOPLE"/> - <int value="5" label="SUGGESTION"/> - <int value="6" label="LAUNCHER_SEARCH_PROVIDER"/> - <int value="7" label="PLAY_STORE_UNINSTALLED_APP"/> - <int value="8" label="PLAY_STORE_INSTANT_APP"/> - <int value="9" label="ANSWER_CARD"/> - <int value="10" label="PLAY_STORE_APP_SHORTCUT"/> + <int value="0" label="OMNIBOX_DEPRECATED"/> + <int value="1" label="APP_DEPRECATED"/> + <int value="2" label="WEBSTORE_DEPRECATED"/> + <int value="3" label="SEARCH_WEBSTORE_DEPRECATED"/> + <int value="4" label="SEARCH_PEOPLE_DEPRECATED"/> + <int value="5" label="SUGGESTION_DEPRECATED"/> + <int value="6" label="LauncherSearchProvider (local or drive file)"/> + <int value="7" label="Uninstalled App From PlayStore"/> + <int value="8" label="Arc++ Instant App"/> + <int value="9" label="Answer Card"/> + <int value="10" label="Arc++ App Shortcut"/> + <int value="11" label="Omnibox, URL What You Typed"/> + <int value="12" label="Omnibox, Bookmark"/> + <int value="13" label="Omnibox, Recently Visited Website"/> + <int value="14" label="Omnibox, Recent Doc In Drive"/> + <int value="15" label="Omnibox, Web Query"/> + <int value="16" label="Omnibox, History"/> + <int value="17" label="Arc++ App"/> + <int value="18" label="Arc++ Reinstall App"/> + <int value="19" label="Internal App"/> + <int value="20" label="Extension App"/> + <int value="21" label="Crostini App"/> + <int value="22" label="Settings Shortcut"/> + <int value="23" label="AppDataResult, Person From Contacts"/> + <int value="24" label="AppDataResult, Note Document"/> </enum> <enum name="AppListSearchResultDisplayType"> @@ -21300,10 +21590,10 @@ <int value="1936" label="MediaStreamConstraintsGroupIdAudio"/> <int value="1937" label="MediaStreamConstraintsGroupIdVideo"/> <int value="1938" label="MediaStreamConstraintsVideoKind"/> - <int value="1939" label="MediaStreamConstraintsDepthNear"/> - <int value="1940" label="MediaStreamConstraintsDepthFar"/> - <int value="1941" label="MediaStreamConstraintsFocalLengthX"/> - <int value="1942" label="MediaStreamConstraintsFocalLengthY"/> + <int value="1939" label="OBSOLETE_MediaStreamConstraintsDepthNear"/> + <int value="1940" label="OBSOLETE_MediaStreamConstraintsDepthFar"/> + <int value="1941" label="OBSOLETE_MediaStreamConstraintsFocalLengthX"/> + <int value="1942" label="OBSOLETE_MediaStreamConstraintsFocalLengthY"/> <int value="1943" label="MediaStreamConstraintsMediaStreamSourceAudio"/> <int value="1944" label="MediaStreamConstraintsMediaStreamSourceVideo"/> <int value="1945" label="MediaStreamConstraintsRenderToAssociatedSink"/> @@ -23429,6 +23719,27 @@ <int value="5" label="Unknown Error"/> </enum> +<enum name="FileSystemProviderMountType"> + <int value="0" label="Unknown"/> + <int value="1" label="Zip Unpacker"/> + <int value="2" label="File System for Dropbox"/> + <int value="3" label="File System for One Drive"/> + <int value="4" label="SFTP File System"/> + <int value="5" label="Box for ChromeOS"/> + <int value="6" label="Ted Talks"/> + <int value="7" label="WebDAV File System"/> + <int value="8" label="Cloud Storage"/> + <int value="9" label="Scan"/> + <int value="10" label="File System for SMB CIFS"/> + <int value="11" label="Add My Documents"/> + <int value="12" label="Wicked Good Unarchiver"/> + <int value="13" label="Network File Share for ChromeOS"/> + <int value="14" label="LAN Folder"/> + <int value="15" label="Zip Archiver"/> + <int value="16" label="Secure Shell App"/> + <int value="17" label="Native Network SMB"/> +</enum> + <enum name="FileType"> <int value="0" label="other"/> <int value="1" label=".doc"/> @@ -24295,6 +24606,7 @@ <int value="272110624" label="SteelSeriesProduct1420"/> <int value="355600640" label="Razer1532Product0900"/> <int value="416361536" label="GoogleProduct2c40"/> + <int value="416370734" label="GoogleProduct502e"/> <int value="550920817" label="Vendor20d6Product6271"/> <int value="550930917" label="Vendor20d6Product89e5"/> <int value="572653664" label="MacAllyProduct0060"/> @@ -32320,6 +32632,7 @@ <int value="-802348444" label="disable-site-engagement-service"/> <int value="-799931058" label="UseMultiloginEndpoint:disabled"/> <int value="-798187384" label="try-supported-channel-layouts"/> + <int value="-797520931" label="ExtensionsToolbarMenu:disabled"/> <int value="-797310986" label="CSSFragmentIdentifiers:disabled"/> <int value="-795600188" label="disable-async-dns"/> <int value="-793921836" label="ShowAllDialogsWithViewsToolkit:disabled"/> @@ -32441,6 +32754,7 @@ <int value="-612480090" label="FasterLocationReload:enabled"/> <int value="-610411643" label="enable-printer-app-search"/> <int value="-606898702" label="MaterialDesignSettings:disabled"/> + <int value="-606431158" label="DrawVerticallyEdgeToEdge:enabled"/> <int value="-604814313" label="enable-pinch"/> <int value="-604269405" label="ContentSuggestionsFaviconsFromNewServer:enabled"/> @@ -33252,6 +33566,7 @@ <int value="739938466" label="WebPaymentsPerMethodCanMakePaymentQuota:disabled"/> <int value="740056959" label="ImeServiceConnectable:enabled"/> + <int value="740619684" label="ExtensionsToolbarMenu:enabled"/> <int value="745783589" label="translate-force-trigger-on-english"/> <int value="745868416" label="disable-system-timezone-automatic-detection"/> <int value="746765012" label="AutofillEnableToolbarStatusChip:disabled"/> @@ -33487,6 +33802,7 @@ <int value="1152491093" label="MediaSessionService:disabled"/> <int value="1153454438" label="AutofillCreditCardLastUsedDateDisplay:disabled"/> + <int value="1155905651" label="DrawVerticallyEdgeToEdge:disabled"/> <int value="1155923106" label="NTPOfflinePages:enabled"/> <int value="1161075291" label="OmniboxReverseTabSwitchLogic:disabled"/> <int value="1163255347" label="ash-enable-touch-view-touch-feedback"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 74dea85..0df95417 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -37605,6 +37605,16 @@ </summary> </histogram> +<histogram name="FileBrowser.FileSystemProviderMounted" + enum="FileSystemProviderMountType" expires_after="M79"> + <owner>slangley@chromium.org</owner> + <owner>weifangsun@chromium.org</owner> + <summary> + The type of file system provider that has been mounted. This metric is + emmitted on mounting of the filesystem. + </summary> +</histogram> + <histogram name="FileBrowser.FolderShortcut.Add" expires_after="M79"> <owner>slangley@chromium.org</owner> <owner>weifangsun@chromium.org</owner> @@ -38448,7 +38458,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.EmailProvidersInteraction" - enum="NuxEmailProvidersInteractions" expires_after="M75"> + enum="NuxEmailProvidersInteractions" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38462,7 +38472,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.EmailProvidersSelection" - enum="NuxEmailProvidersSelections" expires_after="M75"> + enum="NuxEmailProvidersSelections" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38473,7 +38483,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.GoogleAppsInteraction" - enum="NuxGoogleAppsInteractions" expires_after="M75"> + enum="NuxGoogleAppsInteractions" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38485,7 +38495,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.GoogleAppsSelection" - enum="NuxGoogleAppsSelections" expires_after="M75"> + enum="NuxGoogleAppsSelections" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38496,7 +38506,11 @@ </histogram> <histogram name="FirstRun.NewUserExperience.LandingPageInteraction" - enum="NuxLandingPageInteractions" expires_after="M75"> + enum="NuxLandingPageInteractions" expires_after="never"> +<!-- expires-never: Captures users' initial interaction with chrome. We will + need to track how the metrics change over time, and how different + acquisition campaigns impact this metric. --> + <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38506,7 +38520,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.NtpBackgroundInteraction" - enum="NuxNtpBackgroundInteractions" expires_after="2019-05-31"> + enum="NuxNtpBackgroundInteractions" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>johntlee@chromium.org</owner> <summary> @@ -38519,7 +38533,11 @@ </histogram> <histogram name="FirstRun.NewUserExperience.SetAsDefaultInteraction" - enum="NuxSetAsDefaultInteractions" expires_after="M75"> + enum="NuxSetAsDefaultInteractions" expires_after="never"> +<!-- expires-never: Captures users' initial interaction with chrome. We will + need to track how the metrics change over time, and how different + acquisition campaigns impact this metric. --> + <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -38529,7 +38547,7 @@ </histogram> <histogram name="FirstRun.NewUserExperience.SignInInterstitialInteraction" - enum="NuxSignInInterstitialInteractions" expires_after="M75"> + enum="NuxSignInInterstitialInteractions" expires_after="M76"> <owner>hcarmona@chromium.org</owner> <owner>scottchen@chromium.org</owner> <summary> @@ -46191,8 +46209,11 @@ </summary> </histogram> -<histogram name="Launch.Modes" enum="LaunchMode"> +<histogram name="Launch.Modes" enum="LaunchMode" expires_after="never"> +<!-- expires-never: used from time to time on Windows to measure the value of the various Chrome shortcuts (grt@) --> + <owner>calamity@chromium.org</owner> + <owner>grt@chromium.org</owner> <summary>The different ways Chrome is launched.</summary> </histogram> @@ -95914,6 +95935,9 @@ <histogram name="RendererScheduler.ExpectedTaskQueueingDurationWithoutMainFrame" units="microseconds"> + <obsolete> + Removed March 2019. + </obsolete> <owner>tdresser@chromium.org</owner> <owner>npm@chromium.org</owner> <summary> @@ -109421,6 +109445,15 @@ </summary> </histogram> +<histogram name="Setup.Install.RemoveProfileStatistics" + enum="BooleanDeletedOrNot" expires_after="M79"> + <owner>waffles@chromium.org</owner> + <summary> + Hit following a successful install or update when the legacy profile count + keys / values are deleted from the registry. + </summary> +</histogram> + <histogram name="Setup.Install.Result" enum="SetupInstallResult"> <owner>grt@chromium.org</owner> <owner>bcwhite@chromium.org</owner> @@ -118378,6 +118411,14 @@ </summary> </histogram> +<histogram name="Sync.NonRedundantInvalidationPerModelType" + enum="SyncModelTypes" expires_after="M77"> + <owner>melandory@chromium.org</owner> + <summary> + The sync datatype of the recieved invalidation with fresh version. + </summary> +</histogram> + <histogram name="Sync.NonReflectionUpdateFreshnessPossiblySkewed" units="ms"> <owner>mastiz@chromium.org</owner> <owner>melandory@chromium.org</owner> @@ -118754,6 +118795,14 @@ </summary> </histogram> +<histogram name="Sync.RedundantInvalidationPerModelType" enum="SyncModelTypes" + expires_after="M80"> + <owner>melandory@chromium.org</owner> + <summary> + The sync datatype of the recieved invalidation with not-fresh version. + </summary> +</histogram> + <histogram name="Sync.RefreshTokenAvailable" enum="BooleanSuccess"> <obsolete> Deprecated 04/2016 as not useful since it always logged true. @@ -121833,7 +121882,11 @@ </histogram> <histogram base="true" name="TaskScheduler.NumCancelledDelayedTasks" - units="tasks" expires_after="2019-05-01"> + units="tasks"> + <obsolete> + Deprecated as of 03/2019. The number of cancelled delayed tasks found by the + lazy approach is 0 more than 99% of the time. + </obsolete> <owner>adityakeerthi@google.com</owner> <owner>fdoray@chromium.org</owner> <summary> @@ -121889,7 +121942,11 @@ </histogram> <histogram base="true" name="TaskScheduler.PercentCancelledDelayedTasks" - units="tasks" expires_after="2019-05-01"> + units="tasks"> + <obsolete> + Deprecated as of 03/2019. The number of cancelled delayed tasks found by the + lazy approach is 0 more than 99% of the time. + </obsolete> <owner>adityakeerthi@google.com</owner> <owner>fdoray@chromium.org</owner> <summary> @@ -143311,6 +143368,9 @@ </histogram_suffixes> <histogram_suffixes name="OffTheRecordType" separator="."> + <obsolete> + Deprecated March 2019 + </obsolete> <suffix name="NonOTR" label="Non off-the-record profile"/> <suffix name="OTR" label="Off-the-record profile"/> <affected-histogram name="Tab.TabUnderAction"/> @@ -148398,6 +148458,9 @@ </histogram_suffixes> <histogram_suffixes name="TaskSchedulerCancelledDelayedTasks" separator="."> + <obsolete> + Deprecated as of 03/2019. All affected histograms are deprecated. + </obsolete> <suffix name="Browser" label="TaskScheduler for the browser process."/> <suffix name="ContentChild" label="TaskSchedulers for various instantiations of
diff --git a/tools/perf/contrib/media_router_benchmarks/BUILD.gn b/tools/perf/contrib/media_router_benchmarks/BUILD.gn new file mode 100644 index 0000000..5d1554b --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/BUILD.gn
@@ -0,0 +1,13 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +copy("media_router_telemetry_extension") { + sources = [ + "extension/manifest.json", + "extension/script.js", + ] + outputs = [ + "$root_out_dir/media_router/media_router_telemetry_extension/{{source_file_part}}", + ] +}
diff --git a/tools/perf/contrib/media_router_benchmarks/OWNERS b/tools/perf/contrib/media_router_benchmarks/OWNERS new file mode 100644 index 0000000..3010c98 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/OWNERS
@@ -0,0 +1,2 @@ +cliffordcheng@chromium.org +leilei@chromium.org
diff --git a/tools/perf/contrib/media_router_benchmarks/__init__.py b/tools/perf/contrib/media_router_benchmarks/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/__init__.py
diff --git a/tools/perf/contrib/media_router_benchmarks/extension/README.md b/tools/perf/contrib/media_router_benchmarks/extension/README.md new file mode 100644 index 0000000..050e284 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/extension/README.md
@@ -0,0 +1,5 @@ +This is the test extension which is used to get CPU/memory usage for Media +Router performance test. + +`chrome/test/media_router/telemetry/benchmarks/pagesets/cpu_memory_script.js` +shows how to interact with this test extension to get CPU/memory usage.
diff --git a/tools/perf/contrib/media_router_benchmarks/extension/manifest.json b/tools/perf/contrib/media_router_benchmarks/extension/manifest.json new file mode 100644 index 0000000..29f69f75 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/extension/manifest.json
@@ -0,0 +1,19 @@ +{ + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1nP6oOqlQh79uPMoPJQT1aj7z1vM4UkQ3y8rhgnH56FApNWIIr8NqRqSBc1WeCXskdQjctvjW/1ZSYmYAplLziEjlFED2yfCATRl8V5spsZjCqtBw4O8IjzKkEhsNYBlBrpOu0jSLP4Nr/enJvzLwe4tQ80XuLSItJzxF72SoPbxCQCCbm3NKe5dyqZYKmroiLDjwDa8jz3FM6uohfJaWVFzp+fSK1CiKPRxlGvp0Oy5LM03vJFDGwdwJM6nXdy3eM4tIH5arbJ1EfPs5M2AKPNPo55wOLhFjyZzo1TBj9wP1V/r6WmR4Q8XVvpWTIVcRH5VxeOTWoFKYRGQ6OICQIDAQAB", + "description": "This extension helps in retrieving the CPU/memory usage stats for MR extension.", + "name": "MR Test Extension", + "version": "1.0", + "manifest_version": 2, + "externally_connectable": { + "matches": [ + "http://127.0.0.1:*/*" + ] + }, + "background": { + "scripts": ["script.js"], + "persistent": true + }, + "permissions": [ + "processes" + ] +}
diff --git a/tools/perf/contrib/media_router_benchmarks/extension/script.js b/tools/perf/contrib/media_router_benchmarks/extension/script.js new file mode 100644 index 0000000..9c63705 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/extension/script.js
@@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Extension ID: ocihafebdemjoofhbdnamghkfobfgbal +// Collects CPU/memory usage information and posts to the page. +function collectData(port) { + function processCpuListener(processes) { + _postData(processes, port, 'cpu'); + } + + function processMemoryListener(processes) { + _postData(processes, port, 'privateMemory'); + } + + chrome.processes.onUpdated.addListener(processCpuListener); + chrome.processes.onUpdatedWithMemory.addListener(processMemoryListener); + port.onDisconnect.addListener(function() { + chrome.processes.onUpdated.removeListener(processCpuListener); + chrome.processes.onUpdated.removeListener(processMemoryListener); + }); +} + +/** + * Posts the metric data to the page. + * + * @param processes list of current processes. + * @param port the port used for the communication between the page and + * extension. + * @param metric_name the metric name, e.g cpu. + */ +function _postData(processes, port, metric_name) { + let tabPid = port.sender.tab.id; + if (!tabPid) { + return; + } + let tabProcess = ""; + for (let p in processes) { + for (let task in processes[p].tasks) { + if (processes[p].tasks[task].tabId == tabPid) + tabProcess = processes[p].osProcessId; + } + if (tabProcess) + break; + } + if (!tabProcess) { + return; + } + let message = {}; + message[metric_name] = {'current_tab': tabProcess[metric_name]}; + for (let pid in processes) { + let process = processes[pid]; + data = process[metric_name]; + if (['browser', 'gpu', 'extension'].indexOf(process.type) > -1) { + if (process.type == 'extension'){ + for (let index in process.tasks) { + let task = process.tasks[index]; + if (task.title && task.title.indexOf('Chrome Media Router') > -1) { + message[metric_name]['mr_' + process.type] = data; + } + } + } else { + message[metric_name][process.type] = data; + } + } + } + port.postMessage(message); +} + +chrome.runtime.onConnectExternal.addListener(function(port) { + if (port.name == 'collectData') { + collectData(port); + } else { + console.warn('Unknown port, disconnect the port.'); + port.disconnect(); + } +});
diff --git a/tools/perf/contrib/media_router_benchmarks/media_router_base_page.py b/tools/perf/contrib/media_router_benchmarks/media_router_base_page.py new file mode 100644 index 0000000..c90f8cb --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/media_router_base_page.py
@@ -0,0 +1,144 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import logging +import os +import time + +from telemetry import page +from telemetry.core import exceptions + + +class MediaRouterBasePage(page.Page): + """Abstract Cast page for Media Router Telemetry tests.""" + + def ChooseSink(self, tab, sink_name): + """Chooses a specific sink in the list.""" + + tab.ExecuteJavaScript(""" + var sinks = window.document.getElementById("media-router-container"). + shadowRoot.getElementById("sink-list").getElementsByTagName("span"); + for (var i=0; i<sinks.length; i++) { + if(sinks[i].textContent.trim() == {{ sink_name }}) { + sinks[i].click(); + break; + }} + """, + sink_name=sink_name) + + def CloseDialog(self, tab): + """Closes media router dialog.""" + + try: + tab.ExecuteJavaScript( + 'window.document.getElementById("media-router-container").' + + 'shadowRoot.getElementById("container-header").shadowRoot.' + + 'getElementById("close-button").click();') + except (exceptions.DevtoolsTargetCrashException, + exceptions.EvaluateException, + exceptions.TimeoutException): + # Ignore the crash exception, this exception is caused by the js + # code which closes the dialog, it is expected. + # Ignore the evaluate exception, this exception maybe caused by the dialog + # is closed/closing when the JS is executing. + # Ignore the timeout exception, this exception can be caused by finding + # the close-button on a dialog that is already closed. + pass + + + def CloseExistingRoute(self, action_runner, sink_name): + """Closes the existing route if it exists, otherwise does nothing.""" + + action_runner.TapElement(selector='#start_session_button') + action_runner.Wait(5) + for tab in action_runner.tab.browser.tabs: + if tab.url == 'chrome://media-router/': + if self.CheckIfExistingRoute(tab, sink_name): + self.ChooseSink(tab, sink_name) + tab.ExecuteJavaScript( + "window.document.getElementById('media-router-container')." + "shadowRoot.getElementById('route-details').shadowRoot." + "getElementById('close-route-button').click();") + self.CloseDialog(tab) + # Wait for 5s to make sure the route is closed. + action_runner.Wait(5) + + def CheckIfExistingRoute(self, tab, sink_name): + """"Checks if there is existing route for the specific sink.""" + + tab.ExecuteJavaScript(""" + var sinks = window.document.getElementById('media-router-container'). + allSinks; + var sink_id = null; + for (var i=0; i<sinks.length; i++) { + if (sinks[i].name == {{ sink_name }}) { + console.info('sink id: ' + sinks[i].id); + sink_id = sinks[i].id; + break; + } + } + var routes = window.document.getElementById('media-router-container'). + routeList; + for (var i=0; i<routes.length; i++) { + if (!!sink_id && routes[i].sinkId == sink_id) { + window.__telemetry_route_id = routes[i].id; + break; + } + }""", + sink_name=sink_name) + route = tab.EvaluateJavaScript('!!window.__telemetry_route_id') + logging.info('Is there existing route? ' + str(route)) + return route + + def ExecuteAsyncJavaScript(self, action_runner, script, verify_func, + error_message, timeout=5, retry=1): + """Executes async javascript function and waits until it finishes.""" + exception = None + for _ in xrange(retry): + try: + action_runner.ExecuteJavaScript(script) + self._WaitForResult( + action_runner, verify_func, error_message, timeout=timeout) + exception = None + break + except RuntimeError as e: + exception = e + if exception: + raise Exception(exception) + + def WaitUntilDialogLoaded(self, action_runner, tab): + """Waits until dialog is fully loaded.""" + + self._WaitForResult( + action_runner, + lambda: tab.EvaluateJavaScript( + '!!window.document.getElementById(' + '"media-router-container") &&' + 'window.document.getElementById(' + '"media-router-container").sinksToShow_ &&' + 'window.document.getElementById(' + '"media-router-container").sinksToShow_.length'), + 'The dialog is not fully loaded within 15s.', + timeout=15) + + def _WaitForResult(self, action_runner, verify_func, error_message, + timeout=5): + """Waits until the function finishes or timeout.""" + + start_time = time.time() + while (not verify_func() and + time.time() - start_time < timeout): + action_runner.Wait(1) + if not verify_func(): + raise RuntimeError(error_message) + + def _GetOSEnviron(self, environ_variable): + """Gets an OS environment variable on the machine.""" + + if (environ_variable not in os.environ or + not os.environ.get(environ_variable)): + raise RuntimeError( + 'Your test machine is not set up correctly, ' + '%s enviroment variable is missing.', environ_variable) + return os.environ[environ_variable]
diff --git a/tools/perf/contrib/media_router_benchmarks/media_router_benchmarks.py b/tools/perf/contrib/media_router_benchmarks/media_router_benchmarks.py new file mode 100644 index 0000000..656de12 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/media_router_benchmarks.py
@@ -0,0 +1,78 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os + +from core import path_util +from core import perf_benchmark + +from telemetry import benchmark +from telemetry import story +from contrib.media_router_benchmarks import media_router_measurements +from contrib.media_router_benchmarks import media_router_pages + + +@benchmark.Info(emails=['mfoltz@chromium.org', 'cliffordcheng@chromium.org'], + component='Internals>Cast') +class MediaRouterCPUMemoryCast(perf_benchmark.PerfBenchmark): + """Obtains media performance for key user scenarios on desktop.""" + SUPPORTED_PLATFORMS = [story.expectations.ALL_DESKTOP] + options = {'pageset_repeat': 1} + page_set = media_router_pages.MediaRouterCPUMemoryPageSet + + def SetExtraBrowserOptions(self, options): + options.clear_sytem_cache_for_browser_and_profile_on_start = True + # This flag is required to enable the communication between the page and + # the test extension. + options.disable_background_networking = False + + options.AppendExtraBrowserArgs([ + '--load-extension=' + ','.join( + [os.path.join(path_util.GetChromiumSrcDir(), 'out', + 'Release', 'mr_extension', 'release'), + os.path.join(path_util.GetChromiumSrcDir(), 'out', + 'Release', 'media_router', 'media_router_telemetry_extension')]), + '--disable-features=ViewsCastDialog', + '--whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo', + '--media-router=1', + '--enable-stats-collection-bindings' + ]) + + def CreatePageTest(self, options): + return media_router_measurements.MediaRouterCPUMemoryTest() + + @classmethod + def Name(cls): + return 'media_router.cpu_memory' + + +@benchmark.Info(emails=['mfoltz@chromium.org', 'cliffordcheng@chromium.org'], + component='Internals>Cast') +class NoMediaRouterCPUMemory(perf_benchmark.PerfBenchmark): + """Benchmark for CPU and memory usage without Media Router.""" + + SUPPORTED_PLATFORMS = [story.expectations.ALL_DESKTOP] + options = {'pageset_repeat': 1} + page_set = media_router_pages.CPUMemoryPageSet + + def SetExtraBrowserOptions(self, options): + options.clear_sytem_cache_for_browser_and_profile_on_start = True + # This flag is required to enable the communication between the page and + # the test extension. + options.disable_background_networking = False + options.AppendExtraBrowserArgs([ + '--load-extension=' + + os.path.join(path_util.GetChromiumSrcDir(), 'out', + 'Release', 'media_router', 'media_router_telemetry_extension'), + '--disable-features=ViewsCastDialog', + '--media-router=0', + '--enable-stats-collection-bindings' + ]) + + def CreatePageTest(self, options): + return media_router_measurements.MediaRouterCPUMemoryTest() + + @classmethod + def Name(cls): + return 'media_router.cpu_memory.no_media_router'
diff --git a/tools/perf/contrib/media_router_benchmarks/media_router_cpu_memory_metric.py b/tools/perf/contrib/media_router_benchmarks/media_router_cpu_memory_metric.py new file mode 100644 index 0000000..689a1732 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/media_router_cpu_memory_metric.py
@@ -0,0 +1,62 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import logging +import json + +from telemetry.core import exceptions +from telemetry.value import scalar + +from metrics import Metric + + +METRICS = {'privateMemory': {'units': 'MB', 'display_name': 'private_memory'}, + 'cpu': {'units': '%', 'display_name': 'cpu_utilization'}} + + +class MediaRouterCPUMemoryMetric(Metric): + "A metric for media router CPU/Memory usage." + + def Start(self, page, tab): + raise NotImplementedError() + + def Stop(self, page, tab): + raise NotImplementedError() + + def AddResults(self, tab, results): + results_json = None + try: + results_json = tab.EvaluateJavaScript( + 'JSON.stringify(window.perfResults)') + except exceptions.EvaluateException: + pass + # This log gives the detailed information about CPU/memory usage. + logging.info('results_json' + ': ' + str(results_json)) + + if not results_json: + return + perf_results = json.loads(results_json) + for (metric, metric_results) in perf_results.iteritems(): + for (process, process_results) in metric_results.iteritems(): + if not process_results: + continue + avg_result = round(sum(process_results)/len(process_results), 4) + if metric == 'privateMemory': + avg_result = round(avg_result/(1024 * 1024), 2) + logging.info('metric: %s, process: %s, average value: %s' % + (metric, process, str(avg_result))) + results.AddValue(scalar.ScalarValue( + results.current_page, + '%s_%s' % (METRICS.get(metric).get('display_name'), process), + METRICS.get(metric).get('units'), + avg_result)) + + # Calculate MR extension wakeup time + if 'mr_extension' in perf_results['cpu']: + wakeup_percentage = round( + (len(perf_results['cpu']['mr_extension']) * 100 / + len(perf_results['cpu']['browser'])), 2) + results.AddValue(scalar.ScalarValue( + results.current_page, 'mr_extension_wakeup_percentage', + '%', wakeup_percentage))
diff --git a/tools/perf/contrib/media_router_benchmarks/media_router_measurements.py b/tools/perf/contrib/media_router_benchmarks/media_router_measurements.py new file mode 100644 index 0000000..790834c --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/media_router_measurements.py
@@ -0,0 +1,17 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from contrib.media_router_benchmarks import media_router_cpu_memory_metric +from telemetry.page import legacy_page_test + + +class MediaRouterCPUMemoryTest(legacy_page_test.LegacyPageTest): + """Performs a measurement of Media Route CPU/memory usage.""" + + def __init__(self): + super(MediaRouterCPUMemoryTest, self).__init__() + self._metric = media_router_cpu_memory_metric.MediaRouterCPUMemoryMetric() + + def ValidateAndMeasurePage(self, page, tab, results): + self._metric.AddResults(tab, results)
diff --git a/tools/perf/contrib/media_router_benchmarks/media_router_pages.py b/tools/perf/contrib/media_router_benchmarks/media_router_pages.py new file mode 100644 index 0000000..d53e9d6d --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/media_router_pages.py
@@ -0,0 +1,171 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from telemetry import story +from telemetry.page import shared_page_state +from telemetry.util import js_template +from contrib.media_router_benchmarks.media_router_base_page import MediaRouterBasePage + + +SESSION_TIME = 300 # 5 minutes + +class SharedState(shared_page_state.SharedPageState): + """Shared state that restarts the browser for every single story.""" + + def __init__(self, test, finder_options, story_set): + super(SharedState, self).__init__( + test, finder_options, story_set) + + def DidRunStory(self, results): + super(SharedState, self).DidRunStory(results) + self._StopBrowser() + + +class CastIdlePage(MediaRouterBasePage): + """Cast page to open a cast-enabled page and do nothing.""" + + def __init__(self, page_set): + super(CastIdlePage, self).__init__( + page_set=page_set, + url='file://test_site/basic_test.html', + shared_page_state_class=SharedState, + name='basic_test.html') + + def RunPageInteractions(self, action_runner): + # Wait for 5s after Chrome is opened in order to get consistent results. + action_runner.Wait(5) + with action_runner.CreateInteraction('Idle'): + action_runner.ExecuteJavaScript('collectPerfData();') + action_runner.Wait(SESSION_TIME) + + +class CastFlingingPage(MediaRouterBasePage): + """Cast page to fling a video to Chromecast device.""" + + def __init__(self, page_set): + super(CastFlingingPage, self).__init__( + page_set=page_set, + url='file://test_site/basic_test.html#flinging', + shared_page_state_class=SharedState, + name='basic_test.html#flinging') + + def RunPageInteractions(self, action_runner): + sink_name = self._GetOSEnviron('RECEIVER_NAME') + # Wait for 5s after Chrome is opened in order to get consistent results. + action_runner.Wait(5) + with action_runner.CreateInteraction('flinging'): + + self._WaitForResult( + action_runner, + lambda: action_runner.EvaluateJavaScript('initialized'), + 'Failed to initialize', + timeout=30) + self.CloseExistingRoute(action_runner, sink_name) + + # Start session + action_runner.TapElement(selector='#start_session_button') + self._WaitForResult( + action_runner, + lambda: len(action_runner.tab.browser.tabs) >= 2, + 'MR dialog never showed up.') + + for tab in action_runner.tab.browser.tabs: + # Choose sink + if tab.url == 'chrome://media-router/': + self.WaitUntilDialogLoaded(action_runner, tab) + self.ChooseSink(tab, sink_name) + + self._WaitForResult( + action_runner, + lambda: action_runner.EvaluateJavaScript('currentSession'), + 'Failed to start session', + timeout=10) + + # Load Media + self.ExecuteAsyncJavaScript( + action_runner, + js_template.Render( + 'loadMedia({{ url }});', url=self._GetOSEnviron('VIDEO_URL')), + lambda: action_runner.EvaluateJavaScript('currentMedia'), + 'Failed to load media', + timeout=120) + + action_runner.Wait(5) + action_runner.ExecuteJavaScript('collectPerfData();') + action_runner.Wait(SESSION_TIME) + # Stop session + self.ExecuteAsyncJavaScript( + action_runner, + 'stopSession();', + lambda: not action_runner.EvaluateJavaScript('currentSession'), + 'Failed to stop session', + timeout=60, retry=3) + + +class CastMirroringPage(MediaRouterBasePage): + """Cast page to mirror a tab to Chromecast device.""" + + def __init__(self, page_set): + super(CastMirroringPage, self).__init__( + page_set=page_set, + url='file://test_site/mirroring.html', + shared_page_state_class=SharedState, + name='mirroring.html') + + def RunPageInteractions(self, action_runner): + sink_name = self._GetOSEnviron('RECEIVER_NAME') + # Wait for 5s after Chrome is opened in order to get consistent results. + action_runner.Wait(5) + with action_runner.CreateInteraction('mirroring'): + self.CloseExistingRoute(action_runner, sink_name) + + # Start session + action_runner.TapElement(selector='#start_session_button') + self._WaitForResult( + action_runner, + lambda: len(action_runner.tab.browser.tabs) >= 2, + 'MR dialog never showed up.') + + for tab in action_runner.tab.browser.tabs: + # Choose sink + if tab.url == 'chrome://media-router/': + self.WaitUntilDialogLoaded(action_runner, tab) + self.ChooseSink(tab, sink_name) + + # Wait for 5s to make sure the route is created. + action_runner.Wait(5) + action_runner.TapElement(selector='#start_session_button') + self._WaitForResult( + action_runner, + lambda: len(action_runner.tab.browser.tabs) >= 2, + 'MR dialog never showed up.') + + for tab in action_runner.tab.browser.tabs: + if tab.url == 'chrome://media-router/': + self.WaitUntilDialogLoaded(action_runner, tab) + if not self.CheckIfExistingRoute(tab, sink_name): + raise RuntimeError('Failed to start mirroring session.') + action_runner.ExecuteJavaScript('collectPerfData();') + action_runner.Wait(SESSION_TIME) + self.CloseExistingRoute(action_runner, sink_name) + + +class MediaRouterCPUMemoryPageSet(story.StorySet): + """Pageset for media router CPU/memory usage tests.""" + + def __init__(self): + super(MediaRouterCPUMemoryPageSet, self).__init__( + cloud_storage_bucket=story.PARTNER_BUCKET) + self.AddStory(CastIdlePage(self)) + self.AddStory(CastFlingingPage(self)) + self.AddStory(CastMirroringPage(self)) + + +class CPUMemoryPageSet(story.StorySet): + """Pageset to get baseline CPU and memory usage.""" + + def __init__(self): + super(CPUMemoryPageSet, self).__init__( + cloud_storage_bucket=story.PARTNER_BUCKET) + self.AddStory(CastIdlePage(self))
diff --git a/tools/perf/contrib/media_router_benchmarks/test_site/basic_test.html b/tools/perf/contrib/media_router_benchmarks/test_site/basic_test.html new file mode 100644 index 0000000..1d0c9de8 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/test_site/basic_test.html
@@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>MR Integration Basic Test</title> + <script type="text/javascript" src="common.js"></script> + <script type="text/javascript" src="cpu_memory_script.js"></script> + <script type="text/javascript" + src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"> + </script> + </head> + <body> + <button id="start_session_button" onclick="startFlingingSession()"> + Start session + </button> + </body> +</html>
diff --git a/tools/perf/contrib/media_router_benchmarks/test_site/bear-vp9-opus.webm b/tools/perf/contrib/media_router_benchmarks/test_site/bear-vp9-opus.webm new file mode 100644 index 0000000..80355cfa5 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/test_site/bear-vp9-opus.webm Binary files differ
diff --git a/tools/perf/contrib/media_router_benchmarks/test_site/common.js b/tools/perf/contrib/media_router_benchmarks/test_site/common.js new file mode 100644 index 0000000..46e0d8b --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/test_site/common.js
@@ -0,0 +1,101 @@ +/** + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * @fileoverview Common APIs for media router performance tests. + * + */ + +var initialized = false; +var currentSession = null; +var currentMedia = null; + + +window['__onGCastApiAvailable'] = function(loaded, errorInfo) { + if (loaded) { + initializeCastApi(); + } else { + console.log(errorInfo); + } +} + +/** + * Initialize Cast APIs. + */ +function initializeCastApi() { + // Load Cast APIs + console.info('Initializing API'); + var sessionRequest = new chrome.cast.SessionRequest( + chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID); + var apiConfig = new chrome.cast.ApiConfig( + sessionRequest, + null, // session listener + function(availability) { // receiver listener + console.info('Receiver listener: ' + JSON.stringify(availability)); + initialized = true; + }); + chrome.cast.initialize( + apiConfig, + function() { // Successful callback + console.info('Initialize successfully'); + }, + function(error) { // Error callback + console.error('Initialize failed, error: ' + JSON.stringify(error)); + }); +} + +/** + * Start a new session for flinging scenario. + */ +function startFlingingSession() { + console.info('Starting Session'); + chrome.cast.requestSession( + function(session) { // Request session successful callback + console.info('Request session successfully'); + currentSession = session; + }, + function(error) { // Request session Error callback + console.error('Request session failed, error: ' + JSON.stringify(error)); + }); +} + +/** + * Loads the specific video on Chromecast. + * + * @param {string} mediaUrl the url which points to a mp4 video. + */ +function loadMedia(mediaUrl) { + if (!currentSession) { + console.warn('Cannot load media without a live session'); + } + console.info('loading ' + mediaUrl); + var mediaInfo = new chrome.cast.media.MediaInfo(mediaUrl, 'video/mp4'); + var request = new chrome.cast.media.LoadRequest(mediaInfo); + request.autoplay = true; + request.currentTime = 0; + currentSession.loadMedia(request, + function(media) { + console.info('Load media successfully'); + currentMedia = media; + }, + function(error) { // Error callback + console.error('Load media failed, error: ' + JSON.stringify(error)); + }); +} + +/** + * Stops current session. + */ +function stopSession() { + if (currentSession) { + currentSession.stop( + function() { + console.info('Stop session successfully'); + currentSession = null; + }, + function(error) { // Error callback + console.error('Stop session failed, error: ' + JSON.stringify(error)); + }); + } +}
diff --git a/tools/perf/contrib/media_router_benchmarks/test_site/cpu_memory_script.js b/tools/perf/contrib/media_router_benchmarks/test_site/cpu_memory_script.js new file mode 100644 index 0000000..b026bc5 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/test_site/cpu_memory_script.js
@@ -0,0 +1,57 @@ +/** + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * @fileoverview Script to interact with test extension to get CPU/memory usage. + * + */ + + +// MR test extension ID. +var extensionId = 'ocihafebdemjoofhbdnamghkfobfgbal'; + +/** + * The dictionary to store the performance results with the following format: + * key: the metric, e.g. CPU, private memory + * value: map of the performance results for different processes. + * key: process type, e.g. tab, browser, gpu, extension. + * value: list of the performance results per second. Task Manager notifies + * the event listener nearly every second for the latest status of + * each process. + */ +window.perfResults = {}; + +/** + * Connects to the test extension and starts to collect CPU/memory usage data. + */ +function collectPerfData() { + processCpuPort_ = openPort_('collectData'); + if (processCpuPort_) { + processCpuPort_.onMessage.addListener(function(message) { + for (metric in message) { + if (!window.perfResults[metric]) { + window.perfResults[metric] = {}; + } + for (process_type in message[metric]) { + if (!window.perfResults[metric][process_type]) { + window.perfResults[metric][process_type] = [] + } + window.perfResults[metric][process_type].push( + message[metric][process_type]); + } + } + }); + } else { + console.log('Unable to connect to port'); + } +} + +function openPort_(name) { + var rt = window.chrome.runtime; + if (rt && rt.connect) { + console.info('Opening port named ' + name); + return rt.connect(extensionId, {'name': name}); + } + return null; +}
diff --git a/tools/perf/contrib/media_router_benchmarks/test_site/mirroring.html b/tools/perf/contrib/media_router_benchmarks/test_site/mirroring.html new file mode 100644 index 0000000..bddd9a3 --- /dev/null +++ b/tools/perf/contrib/media_router_benchmarks/test_site/mirroring.html
@@ -0,0 +1,21 @@ +<!DOCTYPE HTML> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>MR Perf Test</title> + <script type="text/javascript" src="cpu_memory_script.js"></script> + <script> + function startSession() { + var startSessionRequest = new PresentationRequest(""); + startSessionRequest.start(); + console.log('start session'); + } + </script> + </head> + <body> + <button id="start_session_button" onclick="startSession()"> + Start session + </button> + <video id="video_player" controls autoplay loop src="bear-vp9-opus.webm"> + </video> + </body> +</html>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 9707fbd..2370e19 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -130,6 +130,7 @@ <item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="65327456" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/> <item id="google_url_tracker" hash_code="5492492" type="0" content_hash_code="54474899" os_list="linux,windows" file_path="components/google/core/browser/google_url_tracker.cc"/> <item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/> + <item id="hintsfetcher_gethintsrequest" hash_code="34557599" type="0" content_hash_code="57003380" os_list="linux,windows" file_path="components/previews/content/hints_fetcher.cc"/> <item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/> <item id="history_notice_utils_popup" hash_code="80832574" type="1" second_id="110307337" content_hash_code="30618510" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/> <item id="http_server_error_response" hash_code="32197336" type="0" content_hash_code="61082230" os_list="linux,windows" file_path="net/server/http_server.cc"/>
diff --git a/tools/variations/fieldtrial_to_struct.py b/tools/variations/fieldtrial_to_struct.py index 91a6ffa..20a12f1 100755 --- a/tools/variations/fieldtrial_to_struct.py +++ b/tools/variations/fieldtrial_to_struct.py
@@ -51,10 +51,11 @@ """ return _FieldTrialConfigToDescription(_Load(filename), platforms) -def _CreateExperiment(experiment_data, platforms): +def _CreateExperiment(experiment_data, platforms, is_low_end_device): experiment = { 'name': experiment_data['name'], 'platforms': [_PlatformEnumValue(p) for p in platforms], + 'is_low_end_device': is_low_end_device } forcing_flags_data = experiment_data.get('forcing_flag') if forcing_flags_data: @@ -74,13 +75,21 @@ def _CreateTrial(study_name, experiment_configs, platforms): """Returns the applicable experiments for |study_name| and |platforms|. This iterates through all of the experiment_configs for |study_name| and picks out - the applicable experiments based off of the valid platforms. + the applicable experiments based off of the valid platforms and device + type settings if specified. """ experiments = [] for config in experiment_configs: platform_intersection = [p for p in platforms if p in config['platforms']] + is_low_end_device = 'Study::OPTIONAL_BOOL_MISSING' + if 'is_low_end_device' in config: + is_low_end_device = ('Study::OPTIONAL_BOOL_TRUE' + if config['is_low_end_device'] + else 'Study::OPTIONAL_BOOL_FALSE') + if platform_intersection: - experiments += [_CreateExperiment(e, platform_intersection) + experiments += [_CreateExperiment( + e, platform_intersection, is_low_end_device) for e in config['experiments']] return { 'name': study_name,
diff --git a/tools/variations/fieldtrial_to_struct_unittest.py b/tools/variations/fieldtrial_to_struct_unittest.py index 897416cb..4f0c443 100644 --- a/tools/variations/fieldtrial_to_struct_unittest.py +++ b/tools/variations/fieldtrial_to_struct_unittest.py
@@ -10,6 +10,13 @@ class FieldTrialToStruct(unittest.TestCase): + def FullRelativePath(self, relative_path): + base_path = os.path.dirname(__file__) + if not base_path: + # Handle test being run from the current directory. + base_path = '.' + return base_path + relative_path + def test_FieldTrialToDescription(self): config = { 'Trial1': [ @@ -72,7 +79,8 @@ {'key': 'y', 'value': '2'} ], 'enable_features': ['A', 'B'], - 'disable_features': ['C'] + 'disable_features': ['C'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' }, { 'name': 'Group2', @@ -82,7 +90,8 @@ {'key': 'y', 'value': '4'} ], 'enable_features': ['D', 'E'], - 'disable_features': ['F'] + 'disable_features': ['F'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' }, ], }, @@ -92,6 +101,7 @@ { 'name': 'OtherGroup', 'platforms': ['Study::PLATFORM_WINDOWS'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' } ] }, @@ -101,7 +111,8 @@ { 'name': 'ForcedGroup', 'platforms': ['Study::PLATFORM_WINDOWS'], - 'forcing_flag': "my-forcing-flag" + 'forcing_flag': "my-forcing-flag", + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' } ] }, @@ -116,6 +127,7 @@ 'Trial1': [ { 'platforms': ['windows', 'ios'], + 'is_low_end_device': True, 'experiments': [ { 'name': 'Group1', @@ -172,7 +184,8 @@ {'key': 'y', 'value': '2'} ], 'enable_features': ['A', 'B'], - 'disable_features': ['C'] + 'disable_features': ['C'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_TRUE' }, { 'name': 'Group2', @@ -182,11 +195,13 @@ {'key': 'y', 'value': '4'} ], 'enable_features': ['D', 'E'], - 'disable_features': ['F'] + 'disable_features': ['F'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_TRUE' }, { 'name': 'IOSOnly', 'platforms': ['Study::PLATFORM_IOS'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' }, ], }, @@ -210,6 +225,7 @@ { 'name': 'OtherGroup', 'platforms': ['Study::PLATFORM_MAC'], + 'is_low_end_device': 'Study::OPTIONAL_BOOL_MISSING' }, ], }, @@ -221,10 +237,11 @@ self.assertEqual(expected, result) def test_FieldTrialToStructMain(self): - schema = (os.path.dirname(__file__) + + + schema = self.FullRelativePath( '/../../components/variations/field_trial_config/' 'field_trial_testing_config_schema.json') - unittest_data_dir = os.path.dirname(__file__) + '/unittest_data/' + unittest_data_dir = self.FullRelativePath('/unittest_data/') test_output_filename = 'test_output' fieldtrial_to_struct.main([ '--schema=' + schema,
diff --git a/tools/variations/unittest_data/expected_output.cc b/tools/variations/unittest_data/expected_output.cc index f7cbab7..b51ac07 100644 --- a/tools/variations/unittest_data/expected_output.cc +++ b/tools/variations/unittest_data/expected_output.cc
@@ -10,14 +10,15 @@ #include "test_output.h" -const Study::Platform array_kFieldTrialConfig_platforms_3[] = { +const Study::Platform array_kFieldTrialConfig_platforms_5[] = { Study::PLATFORM_WINDOWS, }; -const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { +const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_3[] = { { "ForcedGroup", - array_kFieldTrialConfig_platforms_3, + array_kFieldTrialConfig_platforms_5, 1, + Study::OPTIONAL_BOOL_MISSING, NULL, 0, NULL, @@ -27,6 +28,40 @@ "my-forcing-flag", }, }; +const Study::Platform array_kFieldTrialConfig_platforms_4[] = { + Study::PLATFORM_WINDOWS, +}; +const Study::Platform array_kFieldTrialConfig_platforms_3[] = { + Study::PLATFORM_WINDOWS, +}; +const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = { + { + "TestGroup1", + array_kFieldTrialConfig_platforms_3, + 1, + Study::OPTIONAL_BOOL_TRUE, + NULL, + 0, + NULL, + 0, + NULL, + 0, + NULL, + }, + { + "TestGroup2", + array_kFieldTrialConfig_platforms_4, + 1, + Study::OPTIONAL_BOOL_FALSE, + NULL, + 0, + NULL, + 0, + NULL, + 0, + NULL, + }, +}; const char* const array_kFieldTrialConfig_enable_features_1[] = { "X", }; @@ -38,6 +73,7 @@ "TestGroup3", array_kFieldTrialConfig_platforms_2, 1, + Study::OPTIONAL_BOOL_MISSING, NULL, 0, array_kFieldTrialConfig_enable_features_1, @@ -92,6 +128,7 @@ "TestGroup2", array_kFieldTrialConfig_platforms_0, 1, + Study::OPTIONAL_BOOL_MISSING, array_kFieldTrialConfig_params, 2, array_kFieldTrialConfig_enable_features, @@ -104,6 +141,7 @@ "TestGroup2-2", array_kFieldTrialConfig_platforms_1, 1, + Study::OPTIONAL_BOOL_MISSING, array_kFieldTrialConfig_params_0, 2, array_kFieldTrialConfig_enable_features_0, @@ -121,6 +159,7 @@ "TestGroup1", array_kFieldTrialConfig_platforms, 1, + Study::OPTIONAL_BOOL_MISSING, NULL, 0, NULL, @@ -147,12 +186,17 @@ 1, }, { - "TrialWithForcingFlag", + "TrialWithDeviceType", array_kFieldTrialConfig_experiments_2, + 2, + }, + { + "TrialWithForcingFlag", + array_kFieldTrialConfig_experiments_3, 1, }, }; const FieldTrialTestingConfig kFieldTrialConfig = { array_kFieldTrialConfig_studies, - 4, + 5, };
diff --git a/tools/variations/unittest_data/expected_output.h b/tools/variations/unittest_data/expected_output.h index 641ff31..8db61103 100644 --- a/tools/variations/unittest_data/expected_output.h +++ b/tools/variations/unittest_data/expected_output.h
@@ -23,6 +23,7 @@ const char* const name; const Study::Platform * platforms; const size_t platforms_size; + const Study::OptionalBool is_low_end_device; const FieldTrialTestingExperimentParams * params; const size_t params_size; const char* const * enable_features;
diff --git a/tools/variations/unittest_data/test_config.json b/tools/variations/unittest_data/test_config.json index 63662d0..525f63e6 100644 --- a/tools/variations/unittest_data/test_config.json +++ b/tools/variations/unittest_data/test_config.json
@@ -46,5 +46,17 @@ } ] } + ], + "TrialWithDeviceType": [ + { + "platforms": ["windows"], + "is_low_end_device": true, + "experiments": [{"name": "TestGroup1"}] + }, + { + "platforms": ["windows"], + "is_low_end_device": false, + "experiments": [{"name": "TestGroup2"}] + } ] }
diff --git a/ui/accessibility/ax_assistant_structure.cc b/ui/accessibility/ax_assistant_structure.cc index 0364e7b..184a843 100644 --- a/ui/accessibility/ax_assistant_structure.cc +++ b/ui/accessibility/ax_assistant_structure.cc
@@ -35,7 +35,7 @@ bool HasOnlyTextChildren(const AXNode* node) { for (auto* child : node->children()) { - if (!child->IsTextNode()) + if (!child->IsText()) return false; } return true; @@ -77,7 +77,7 @@ if (node->child_count() == 0) return true; - if (IsNativeTextControl(node) || node->IsTextNode()) { + if (IsNativeTextControl(node) || node->IsText()) { return true; } @@ -98,7 +98,7 @@ } base::string16 GetInnerText(const AXNode* node) { - if (node->IsTextNode()) { + if (node->IsText()) { return node->data().GetString16Attribute(ax::mojom::StringAttribute::kName); } base::string16 text;
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc index c72588d..5e30350 100644 --- a/ui/accessibility/ax_enum_util.cc +++ b/ui/accessibility/ax_enum_util.cc
@@ -1328,6 +1328,8 @@ return "role"; case ax::mojom::StringAttribute::kRoleDescription: return "roleDescription"; + case ax::mojom::StringAttribute::kTooltip: + return "tooltip"; case ax::mojom::StringAttribute::kUrl: return "url"; case ax::mojom::StringAttribute::kValue: @@ -1384,6 +1386,8 @@ return ax::mojom::StringAttribute::kRole; if (0 == strcmp(string_attribute, "roleDescription")) return ax::mojom::StringAttribute::kRoleDescription; + if (0 == strcmp(string_attribute, "tooltip")) + return ax::mojom::StringAttribute::kTooltip; if (0 == strcmp(string_attribute, "url")) return ax::mojom::StringAttribute::kUrl; if (0 == strcmp(string_attribute, "value")) @@ -2292,8 +2296,6 @@ return "attribute"; case ax::mojom::DescriptionFrom::kContents: return "contents"; - case ax::mojom::DescriptionFrom::kPlaceholder: - return "placeholder"; case ax::mojom::DescriptionFrom::kRelatedElement: return "relatedElement"; } @@ -2310,8 +2312,6 @@ return ax::mojom::DescriptionFrom::kAttribute; if (0 == strcmp(description_from, "contents")) return ax::mojom::DescriptionFrom::kContents; - if (0 == strcmp(description_from, "placeholder")) - return ax::mojom::DescriptionFrom::kPlaceholder; if (0 == strcmp(description_from, "relatedElement")) return ax::mojom::DescriptionFrom::kRelatedElement; return ax::mojom::DescriptionFrom::kNone;
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom index 1de320b..c2637233 100644 --- a/ui/accessibility/ax_enums.mojom +++ b/ui/accessibility/ax_enums.mojom
@@ -470,9 +470,12 @@ kName, kLiveRelevant, kLiveStatus, + // Only if not already exposed in kName (NameFrom::kPlaceholder) kPlaceholder, kRole, kRoleDescription, + // Only if not already exposed in kName (NameFrom::kTitle) + kTooltip, kUrl, kValue, }; @@ -842,7 +845,6 @@ kUninitialized, kAttribute, kContents, - kPlaceholder, kRelatedElement, };
diff --git a/ui/accessibility/ax_language_info.cc b/ui/accessibility/ax_language_info.cc index d04f48c..fa50061 100644 --- a/ui/accessibility/ax_language_info.cc +++ b/ui/accessibility/ax_language_info.cc
@@ -117,7 +117,7 @@ // Detect language for a subtree rooted at the given node // will not check feature flag. static void DetectLanguageForSubtreeInternal(AXNode* node, class AXTree* tree) { - if (node->IsTextNode()) { + if (node->IsText()) { AXLanguageInfoStats* lang_info_stats = tree->language_info_stats.get(); AXLanguageInfo* lang_info = node->GetLanguageInfo(); if (!lang_info) {
diff --git a/ui/accessibility/ax_language_info_unittest.cc b/ui/accessibility/ax_language_info_unittest.cc index 90dc981..2158a5f 100644 --- a/ui/accessibility/ax_language_info_unittest.cc +++ b/ui/accessibility/ax_language_info_unittest.cc
@@ -363,21 +363,21 @@ { AXNode* node3 = tree.GetFromId(3); - EXPECT_TRUE(node3->IsTextNode()); + EXPECT_TRUE(node3->IsText()); EXPECT_NE(node3->GetLanguageInfo(), nullptr); EXPECT_EQ(node3->GetLanguage(), "fr"); } { AXNode* node4 = tree.GetFromId(4); - EXPECT_TRUE(node4->IsTextNode()); + EXPECT_TRUE(node4->IsText()); EXPECT_NE(node4->GetLanguageInfo(), nullptr); EXPECT_EQ(node4->GetLanguage(), "en"); } { AXNode* node5 = tree.GetFromId(5); - EXPECT_TRUE(node5->IsTextNode()); + EXPECT_TRUE(node5->IsText()); EXPECT_NE(node5->GetLanguageInfo(), nullptr); EXPECT_EQ(node5->GetLanguage(), "de"); } @@ -476,7 +476,7 @@ { AXNode* node3 = tree.GetFromId(3); - EXPECT_TRUE(node3->IsTextNode()); + EXPECT_TRUE(node3->IsText()); ASSERT_NE(node3->GetLanguageInfo(), nullptr); ASSERT_GT(node3->GetLanguageInfo()->detected_languages.size(), (unsigned)0); ASSERT_EQ(node3->GetLanguageInfo()->detected_languages[0], "fr"); @@ -486,7 +486,7 @@ { AXNode* node4 = tree.GetFromId(4); - EXPECT_TRUE(node4->IsTextNode()); + EXPECT_TRUE(node4->IsText()); ASSERT_NE(node4->GetLanguageInfo(), nullptr); ASSERT_GT(node4->GetLanguageInfo()->detected_languages.size(), (unsigned)0); ASSERT_EQ(node4->GetLanguageInfo()->detected_languages[0], "en"); @@ -496,7 +496,7 @@ { AXNode* node5 = tree.GetFromId(5); - EXPECT_TRUE(node5->IsTextNode()); + EXPECT_TRUE(node5->IsText()); ASSERT_NE(node5->GetLanguageInfo(), nullptr); ASSERT_GT(node5->GetLanguageInfo()->detected_languages.size(), (unsigned)0); ASSERT_EQ(node5->GetLanguageInfo()->detected_languages[0], "de");
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index 552d8f34..7a61548 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc
@@ -86,12 +86,18 @@ return 0; } -bool AXNode::IsTextNode() const { +bool AXNode::IsText() const { return data().role == ax::mojom::Role::kStaticText || data().role == ax::mojom::Role::kLineBreak || data().role == ax::mojom::Role::kInlineTextBox; } +bool AXNode::IsLineBreak() const { + return data().role == ax::mojom::Role::kLineBreak || + (IsText() && parent() && + parent()->data().role == ax::mojom::Role::kLineBreak); +} + void AXNode::SetData(const AXNodeData& src) { data_ = src; }
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h index a289b7e..29849328 100644 --- a/ui/accessibility/ax_node.h +++ b/ui/accessibility/ax_node.h
@@ -69,7 +69,11 @@ int GetUnignoredIndexInParent() const; // Returns true if the node has any of the text related roles. - bool IsTextNode() const; + bool IsText() const; + + // Returns true if the node has any line break related roles or is the child a + // node with line break related roles. + bool IsLineBreak() const; // Set the node's accessibility data. This may be done during initialization // or later when the node data changes.
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index d490ddb..d0ec573 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -741,6 +741,21 @@ } } +ax::mojom::DescriptionFrom AXNodeData::GetDescriptionFrom() const { + return static_cast<ax::mojom::DescriptionFrom>( + GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom)); +} + +void AXNodeData::SetDescriptionFrom( + ax::mojom::DescriptionFrom description_from) { + if (HasIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom)) + RemoveIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom); + if (description_from != ax::mojom::DescriptionFrom::kNone) { + AddIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom, + static_cast<int32_t>(description_from)); + } +} + ax::mojom::TextPosition AXNodeData::GetTextPosition() const { return static_cast<ax::mojom::TextPosition>( GetIntAttribute(ax::mojom::IntAttribute::kTextPosition)); @@ -1197,6 +1212,9 @@ case ax::mojom::StringAttribute::kRoleDescription: result += " role_description=" + value; break; + case ax::mojom::StringAttribute::kTooltip: + result += " tooltip=" + value; + break; case ax::mojom::StringAttribute::kUrl: result += " url=" + value; break;
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h index 7f7d680..7f7ace0 100644 --- a/ui/accessibility/ax_node_data.h +++ b/ui/accessibility/ax_node_data.h
@@ -167,6 +167,8 @@ void SetInvalidState(ax::mojom::InvalidState invalid_state); ax::mojom::NameFrom GetNameFrom() const; void SetNameFrom(ax::mojom::NameFrom name_from); + ax::mojom::DescriptionFrom GetDescriptionFrom() const; + void SetDescriptionFrom(ax::mojom::DescriptionFrom description_from); ax::mojom::TextPosition GetTextPosition() const; void SetTextPosition(ax::mojom::TextPosition text_position); ax::mojom::Restriction GetRestriction() const;
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc index c9dbd0cb..6b798c9b 100644 --- a/ui/accessibility/ax_node_position.cc +++ b/ui/accessibility/ax_node_position.cc
@@ -24,13 +24,23 @@ if (IsNullPosition()) return base::string16(); - DCHECK(GetAnchor()); + const AXNode* anchor = GetAnchor(); + DCHECK(anchor); base::string16 value = GetAnchor()->data().GetString16Attribute( ax::mojom::StringAttribute::kValue); if (!value.empty()) return value; - return GetAnchor()->data().GetString16Attribute( - ax::mojom::StringAttribute::kName); + + if (anchor->IsText()) { + return anchor->data().GetString16Attribute( + ax::mojom::StringAttribute::kName); + } + + base::string16 text; + for (size_t i = 0, c = AnchorChildCount(); i < c; ++i) + text += CreateChildPositionAt(i)->GetInnerText(); + + return text; } void AXNodePosition::AnchorChild(int child_index, @@ -89,22 +99,13 @@ return nullptr; } -int AXNodePosition::MaxTextOffset() const { - if (IsNullPosition()) - return INVALID_INDEX; - return static_cast<int>(GetInnerText().length()); -} - bool AXNodePosition::IsInWhiteSpace() const { - switch (kind()) { - case AXPositionKind::NULL_POSITION: - return false; - case AXPositionKind::TREE_POSITION: - case AXPositionKind::TEXT_POSITION: - return base::ContainsOnlyChars(GetInnerText(), base::kWhitespaceUTF16); - } - NOTREACHED(); - return false; + if (IsNullPosition()) + return false; + + DCHECK(GetAnchor()); + return GetAnchor()->IsLineBreak() || + base::ContainsOnlyChars(GetInnerText(), base::kWhitespaceUTF16); } std::vector<int32_t> AXNodePosition::GetWordStartOffsets() const {
diff --git a/ui/accessibility/ax_node_position.h b/ui/accessibility/ax_node_position.h index e40fd12..0bc14db9 100644 --- a/ui/accessibility/ax_node_position.h +++ b/ui/accessibility/ax_node_position.h
@@ -18,6 +18,8 @@ namespace ui { +// AXNodePosition includes implementations of AXPosition methods which require +// knowledge of the AXPosition AXNodeType (which is unknown by AXPosition). class AX_EXPORT AXNodePosition : public AXPosition<AXNodePosition, AXNode> { public: AXNodePosition(); @@ -38,7 +40,6 @@ int AnchorIndexInParent() const override; void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override; AXNode* GetNodeInTree(AXTreeID tree_id, int32_t node_id) const override; - int MaxTextOffset() const override; bool IsInWhiteSpace() const override; std::vector<int32_t> GetWordStartOffsets() const override; std::vector<int32_t> GetWordEndOffsets() const override;
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index 36e69d7..ca74036 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -124,10 +124,6 @@ button_.SetHasPopup(ax::mojom::HasPopup::kMenu); button_.SetName("Button"); button_.relative_bounds.bounds = gfx::RectF(20, 20, 200, 30); - button_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts, - std::vector<int32_t>{0}); - button_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, - std::vector<int32_t>{6}); button_.AddIntAttribute(ax::mojom::IntAttribute::kNextOnLineId, check_box_.id); root_.child_ids.push_back(button_.id); @@ -136,10 +132,6 @@ check_box_.SetCheckedState(ax::mojom::CheckedState::kTrue); check_box_.SetName("Check box"); check_box_.relative_bounds.bounds = gfx::RectF(20, 50, 200, 30); - check_box_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts, - std::vector<int32_t>{0, 6}); - check_box_.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds, - std::vector<int32_t>{5, 9}); check_box_.AddIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId, button_.id); root_.child_ids.push_back(check_box_.id); @@ -249,29 +241,173 @@ EXPECT_EQ(AXNodePosition::INVALID_OFFSET, copy_position->text_offset()); TestPositionType text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, text_field_.id, 1 /* text_offset */, + tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); copy_position = text_position->Clone(); ASSERT_NE(nullptr, copy_position); EXPECT_TRUE(copy_position->IsTextPosition()); EXPECT_EQ(text_field_.id, copy_position->anchor_id()); - EXPECT_EQ(1, copy_position->text_offset()); + EXPECT_EQ(0, copy_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, copy_position->affinity()); text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, text_field_.id, 1 /* text_offset */, + tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); copy_position = text_position->Clone(); ASSERT_NE(nullptr, copy_position); EXPECT_TRUE(copy_position->IsTextPosition()); EXPECT_EQ(text_field_.id, copy_position->anchor_id()); - EXPECT_EQ(1, copy_position->text_offset()); + EXPECT_EQ(0, copy_position->text_offset()); EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, copy_position->affinity()); EXPECT_EQ(AXNodePosition::INVALID_INDEX, copy_position->child_index()); } +TEST_F(AXPositionTest, GetInnerTextFromNullPosition) { + TestPositionType text_position = AXNodePosition::CreateNullPosition(); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsNullPosition()); + ASSERT_EQ(base::WideToUTF16(L""), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromRoot) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L"Line 1\nLine 2"), + text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromButton) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, button_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L""), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromCheckbox) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L""), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromTextField) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, text_field_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L"Line 1\nLine 2"), + text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromStaticText) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, static_text1_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L"Line 1"), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromInlineTextBox) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L"Line 1"), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetInnerTextFromLineBreak) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, line_break_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(base::WideToUTF16(L"\n"), text_position->GetInnerText()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromNullPosition) { + TestPositionType text_position = AXNodePosition::CreateNullPosition(); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsNullPosition()); + ASSERT_EQ(AXNodePosition::INVALID_INDEX, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromRoot) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(13, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromButton) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, button_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(0, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromCheckbox) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(0, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromTextfield) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, text_field_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(13, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromStaticText) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, static_text1_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(6, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromInlineTextBox) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(6, text_position->MaxTextOffset()); +} + +TEST_F(AXPositionTest, GetMaxTextOffsetFromLineBreak) { + TestPositionType text_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, line_break_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kUpstream); + ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); + ASSERT_EQ(1, text_position->MaxTextOffset()); +} + TEST_F(AXPositionTest, AtStartOfAnchorWithNullPosition) { TestPositionType null_position = AXNodePosition::CreateNullPosition(); ASSERT_NE(nullptr, null_position); @@ -312,18 +448,21 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtStartOfAnchor()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfAnchor()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfAnchor()); } @@ -355,18 +494,21 @@ tree_.data().tree_id, inline_box1_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtEndOfAnchor()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtEndOfAnchor()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtEndOfAnchor()); } @@ -377,18 +519,21 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtStartOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfLine()); // An "after text" position anchored at the line break should not be the same @@ -397,6 +542,7 @@ tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfLine()); // An upstream affinity should not affect the outcome since there is no soft @@ -405,12 +551,14 @@ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtStartOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box2_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtStartOfLine()); } @@ -419,12 +567,14 @@ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtEndOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtEndOfLine()); // A "before text" position anchored at the line break should visually be the @@ -433,6 +583,7 @@ tree_.data().tree_id, line_break_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtEndOfLine()); // The following position comes after the soft line break, so it should not be @@ -441,18 +592,21 @@ tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtEndOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box2_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_FALSE(text_position->AtEndOfLine()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box2_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); EXPECT_TRUE(text_position->AtEndOfLine()); } @@ -480,10 +634,12 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, inline_box1_position); + ASSERT_TRUE(inline_box1_position->IsTextPosition()); TestPositionType inline_box2_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, inline_box2_position); + ASSERT_TRUE(inline_box2_position->IsTextPosition()); TestPositionType test_position = root_position->LowestCommonAncestor(*null_position.get()); @@ -565,6 +721,7 @@ tree_.data().tree_id, text_field_.id, 12 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->AsTreePosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTreePosition()); @@ -581,6 +738,7 @@ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->AsTreePosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTreePosition()); @@ -594,6 +752,7 @@ tree_.data().tree_id, inline_box2_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->AsTreePosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTreePosition()); @@ -664,6 +823,7 @@ tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->AsTextPosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -727,9 +887,10 @@ // Create a text position pointing to the end of the root (an "after text" // position). TestPositionType text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, root_.id, 28 /* text_offset */, + tree_.data().tree_id, root_.id, 13 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->AsLeafTextPosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -742,6 +903,7 @@ tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->AsLeafTextPosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -751,15 +913,16 @@ EXPECT_EQ(ax::mojom::TextAffinity::kDownstream, test_position->affinity()); text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, text_field_.id, 1 /* text_offset */, + tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->AsLeafTextPosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(tree_.data().tree_id, test_position->tree_id()); EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); - EXPECT_EQ(1, test_position->text_offset()); + EXPECT_EQ(0, test_position->text_offset()); // Even though upstream affinity doesn't make sense on a leaf node, there is // no need to reset it to downstream. EXPECT_EQ(ax::mojom::TextAffinity::kUpstream, test_position->affinity()); @@ -769,9 +932,10 @@ // leaf text position to be placed after the text of the first inline text // box. text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, root_.id, 21 /* text_offset */, + tree_.data().tree_id, root_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->AsLeafTextPosition(); ASSERT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -802,7 +966,7 @@ // Create a text position on the root, pointing to the line break character // inside the text field. text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, root_.id, 21 /* text_offset */, + tree_.data().tree_id, root_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); test_position = text_position->AsLeafTextPosition(); @@ -887,6 +1051,7 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreatePositionAtStartOfAnchor(); EXPECT_NE(nullptr, test_position); @@ -899,6 +1064,7 @@ tree_.data().tree_id, inline_box1_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreatePositionAtStartOfAnchor(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -941,6 +1107,7 @@ tree_.data().tree_id, inline_box1_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreatePositionAtEndOfAnchor(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -952,6 +1119,7 @@ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreatePositionAtEndOfAnchor(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -994,6 +1162,7 @@ tree_.data().tree_id, static_text1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreateChildPositionAt(0); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -1004,6 +1173,7 @@ tree_.data().tree_id, static_text2_.id, 4 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreateChildPositionAt(1); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsNullPosition()); @@ -1041,14 +1211,15 @@ // Create a position that points at the end of the first line, right after the // check box. TestPositionType text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, check_box_.id, 9 /* text_offset */, + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreateParentPosition(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(root_.id, test_position->anchor_id()); - EXPECT_EQ(15, test_position->text_offset()); + EXPECT_EQ(0, test_position->text_offset()); // Since the same text offset in the root could be used to point to the // beginning of the second line, affinity should have been adjusted to // upstream. @@ -1058,6 +1229,7 @@ tree_.data().tree_id, inline_box2_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreateParentPosition(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -1100,23 +1272,25 @@ EXPECT_EQ(check_box_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); - // The text offset on the root points to the text coming from inside the check - // box. - check_box_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, root_.id, 6 /* text_offset */, + // The text offset on the root points to the text coming from inside the text + // field's first inline text box. + TestPositionType root_position = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); - ASSERT_NE(nullptr, check_box_position); - test_position = check_box_position->CreateNextTextAnchorPosition(); + ASSERT_NE(nullptr, root_position); + ASSERT_TRUE(root_position->IsTextPosition()); + test_position = root_position->CreateNextTextAnchorPosition(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(tree_.data().tree_id, test_position->tree_id()); - EXPECT_EQ(check_box_.id, test_position->anchor_id()); + EXPECT_EQ(inline_box1_.id, test_position->anchor_id()); EXPECT_EQ(0, test_position->text_offset()); TestPositionType button_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, button_.id, 1 /* text_offset */, + tree_.data().tree_id, button_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, button_position); + ASSERT_TRUE(button_position->IsTextPosition()); test_position = button_position->CreateNextTextAnchorPosition(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -1165,6 +1339,7 @@ tree_.data().tree_id, inline_box2_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreatePreviousTextAnchorPosition(); EXPECT_NE(nullptr, test_position); @@ -1222,9 +1397,10 @@ // The text offset on the root points to the text coming from inside the check // box. TestPositionType check_box_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, check_box_.id, 6 /* text_offset */, + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, check_box_position); + ASSERT_TRUE(check_box_position->IsTextPosition()); test_position = check_box_position->CreatePreviousTextAnchorPosition(); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); @@ -1251,6 +1427,7 @@ tree_.data().tree_id, inline_box1_.id, 4 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); @@ -1262,6 +1439,7 @@ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); @@ -1296,15 +1474,16 @@ EXPECT_EQ(1, test_position->text_offset()); text_position = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, check_box_.id, 9 /* text_offset */, + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(check_box_.id, test_position->anchor_id()); - EXPECT_EQ(9, test_position->text_offset()); + EXPECT_EQ(0, test_position->text_offset()); test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); @@ -1316,6 +1495,7 @@ tree_.data().tree_id, text_field_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreateNextCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); @@ -1331,6 +1511,7 @@ tree_.data().tree_id, inline_box2_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); TestPositionType test_position = text_position->CreatePreviousCharacterPosition( AXBoundaryBehavior::CrossBoundary); @@ -1343,6 +1524,7 @@ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreatePreviousCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); @@ -1380,6 +1562,7 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreatePreviousCharacterPosition( AXBoundaryBehavior::StopAtAnchorBoundary); EXPECT_NE(nullptr, test_position); @@ -1391,12 +1574,13 @@ EXPECT_NE(nullptr, test_position); EXPECT_TRUE(test_position->IsTextPosition()); EXPECT_EQ(check_box_.id, test_position->anchor_id()); - EXPECT_EQ(8, test_position->text_offset()); + EXPECT_EQ(0, test_position->text_offset()); text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, text_field_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position); + ASSERT_TRUE(text_position->IsTextPosition()); test_position = text_position->CreatePreviousCharacterPosition( AXBoundaryBehavior::CrossBoundary); EXPECT_NE(nullptr, test_position); @@ -1493,34 +1677,40 @@ tree_.data().tree_id, inline_box1_.id, 15 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsNullPosition()); TestPositionType text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, text_field_.id, -1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsNullPosition()); EXPECT_EQ(*text_position1, *text_position2); text_position1 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_EQ(*text_position1, *text_position2); - // Affinities should match. + // Affinities should not matter. text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position2); - EXPECT_NE(*text_position1, *text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); + EXPECT_EQ(*text_position1, *text_position2); // Text offsets should match. text_position1 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); EXPECT_NE(*text_position1, *text_position2); // Two "after text" positions on the same node should be equivalent. @@ -1528,23 +1718,78 @@ tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_EQ(*text_position1, *text_position2); - // Two text positions that are consequtive, one "before text" and one "after + // Two text positions that are consecutive, one "before text" and one "after // text". text_position1 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); - EXPECT_NE(*text_position1, *text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); + EXPECT_EQ(*text_position1, *text_position2); +} + +TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetSameAnchorId) { + TestPositionType text_position_one = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_one); + ASSERT_TRUE(text_position_one->IsTextPosition()); + + TestPositionType text_position_two = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_two); + ASSERT_TRUE(text_position_two->IsTextPosition()); + + ASSERT_TRUE(*text_position_one == *text_position_two); + ASSERT_TRUE(*text_position_two == *text_position_one); +} + +TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetDifferentAnchorIdRoot) { + TestPositionType text_position_one = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, root_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_one); + ASSERT_TRUE(text_position_one->IsTextPosition()); + + TestPositionType text_position_two = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_two); + ASSERT_TRUE(text_position_two->IsTextPosition()); + + ASSERT_TRUE(*text_position_one == *text_position_two); + ASSERT_TRUE(*text_position_two == *text_position_one); +} + +TEST_F(AXPositionTest, OperatorEqualsSameTextOffsetDifferentAnchorIdLeaf) { + TestPositionType text_position_one = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, button_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_one); + ASSERT_TRUE(text_position_one->IsTextPosition()); + + TestPositionType text_position_two = AXNodePosition::CreateTextPosition( + tree_.data().tree_id, check_box_.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_NE(nullptr, text_position_two); + ASSERT_TRUE(text_position_two->IsTextPosition()); + + ASSERT_TRUE(*text_position_one == *text_position_two); + ASSERT_TRUE(*text_position_two == *text_position_one); } TEST_F(AXPositionTest, OperatorsLessThanAndGreaterThan) { @@ -1590,10 +1835,12 @@ tree_.data().tree_id, inline_box1_.id, 2 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); TestPositionType text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_GT(*text_position1, *text_position2); EXPECT_LT(*text_position2, *text_position1); @@ -1602,6 +1849,7 @@ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_GT(*text_position1, *text_position2); EXPECT_LT(*text_position2, *text_position1); @@ -1610,11 +1858,13 @@ tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); // A "before text" position. text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kUpstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_GT(*text_position1, *text_position2); EXPECT_LT(*text_position2, *text_position1); @@ -1623,10 +1873,12 @@ tree_.data().tree_id, text_field_.id, 6 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_GT(*text_position1, *text_position2); EXPECT_LT(*text_position2, *text_position1); @@ -1635,10 +1887,12 @@ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position1); + ASSERT_TRUE(text_position1->IsTextPosition()); text_position2 = AXNodePosition::CreateTextPosition( tree_.data().tree_id, line_break_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); + ASSERT_TRUE(text_position2->IsTextPosition()); EXPECT_GT(*text_position1, *text_position2); EXPECT_LT(*text_position2, *text_position1); @@ -1647,8 +1901,8 @@ tree_.data().tree_id, line_break_.id, 1 /* text_offset */, ax::mojom::TextAffinity::kDownstream); ASSERT_NE(nullptr, text_position2); - EXPECT_GT(*text_position1, *text_position2); - EXPECT_LT(*text_position2, *text_position1); + ASSERT_TRUE(text_position2->IsTextPosition()); + EXPECT_EQ(*text_position1, *text_position2); } // @@ -1659,6 +1913,7 @@ TestPositionType text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, GetParam().start_node_id_, GetParam().start_offset_, ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position->IsTextPosition()); for (const std::string& expectation : GetParam().expectations) { text_position = GetParam().TestMethod.Run(text_position); EXPECT_NE(nullptr, text_position); @@ -1670,6 +1925,7 @@ TestPositionType text_position = AXNodePosition::CreateTextPosition( tree_.data().tree_id, GetParam().start_node_id_, GetParam().start_offset_, ax::mojom::TextAffinity::kUpstream); + ASSERT_TRUE(text_position->IsTextPosition()); for (const std::string& expectation : GetParam().expectations) { text_position = GetParam().TestMethod.Run(text_position); EXPECT_NE(nullptr, text_position); @@ -1691,24 +1947,12 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + {"TextPosition anchor_id=1 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", + "TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=1 text_offset=12 " - "affinity=downstream annotated_text=ButtonCheck <b>oxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=20 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "<1>\nLine 2", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>", + "affinity=downstream annotated_text=Line 1\nLine <2>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( @@ -1756,27 +2000,14 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + {"TextPosition anchor_id=1 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", + "TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=1 text_offset=12 " - "affinity=downstream annotated_text=ButtonCheck <b>oxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=20 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "<1>\nLine 2", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>"}}, + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -1823,11 +2054,9 @@ ROOT_ID, 0 /* text_offset */, {"TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -1868,28 +2097,15 @@ AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=20 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "<1>\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=12 " - "affinity=downstream annotated_text=ButtonCheck <b>oxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=1 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordStartPosition( @@ -1905,12 +2121,6 @@ "affinity=downstream annotated_text=Line <1>\nLine 2", "TextPosition anchor_id=4 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1\nLine 2", - "TextPosition anchor_id=3 text_offset=6 " - "affinity=downstream annotated_text=Check <b>ox", - "TextPosition anchor_id=3 text_offset=0 " - "affinity=downstream annotated_text=<C>heck box", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordStartPosition( @@ -1920,12 +2130,6 @@ 5 /* text_offset */, {"TextPosition anchor_id=5 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1", - "TextPosition anchor_id=3 text_offset=6 " - "affinity=downstream annotated_text=Check <b>ox", - "TextPosition anchor_id=3 text_offset=0 " - "affinity=downstream annotated_text=<C>heck box", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordStartPosition( @@ -1939,12 +2143,6 @@ "affinity=downstream annotated_text=Line <1>", "TextPosition anchor_id=6 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1", - "TextPosition anchor_id=3 text_offset=6 " - "affinity=downstream annotated_text=Check <b>ox", - "TextPosition anchor_id=3 text_offset=0 " - "affinity=downstream annotated_text=<C>heck box", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -1956,31 +2154,17 @@ AXBoundaryBehavior::StopAtAnchorBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=20 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "<1>\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=12 " - "affinity=downstream annotated_text=ButtonCheck <b>oxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=1 text_offset=5 " + "affinity=downstream annotated_text=Line <1>\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordStartPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2027,13 +2211,11 @@ AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>", - "TextPosition anchor_id=1 text_offset=27 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine <2>"}}, + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=1 text_offset=12 " + "affinity=downstream annotated_text=Line 1\nLine <2>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordStartPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2073,27 +2255,14 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + {"TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", "TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=19 " - "affinity=downstream annotated_text=ButtonCheck boxLine< " - ">1\nLine 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=26 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine< >2", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>", + "affinity=downstream annotated_text=Line 1\nLine< >2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordEndPosition( @@ -2145,30 +2314,16 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + {"TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", "TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=19 " - "affinity=downstream annotated_text=ButtonCheck boxLine< " - ">1\nLine 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=26 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine< >2", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>"}}, + "affinity=downstream annotated_text=Line 1\nLine< >2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2217,13 +2372,11 @@ AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), ROOT_ID, - 7 /* text_offset after the first character of "Check". */, - {"TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2"}}, + 0 /* text_offset */, + {"TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2262,25 +2415,13 @@ AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=26 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine< >2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=19 " - "affinity=downstream annotated_text=ButtonCheck boxLine< " - ">1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2", + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=Line 1\nLine< >2", "TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -2294,12 +2435,6 @@ "affinity=downstream annotated_text=Line 1<\n>Line 2", "TextPosition anchor_id=4 text_offset=4 " "affinity=downstream annotated_text=Line< >1\nLine 2", - "TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", - "TextPosition anchor_id=3 text_offset=5 " - "affinity=downstream annotated_text=Check< >box", - "TextPosition anchor_id=2 text_offset=6 " - "affinity=downstream annotated_text=Button<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -2309,12 +2444,6 @@ 5 /* text_offset */, {"TextPosition anchor_id=5 text_offset=4 " "affinity=downstream annotated_text=Line< >1", - "TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", - "TextPosition anchor_id=3 text_offset=5 " - "affinity=downstream annotated_text=Check< >box", - "TextPosition anchor_id=2 text_offset=6 " - "affinity=downstream annotated_text=Button<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -2326,12 +2455,6 @@ "affinity=downstream annotated_text=Line 1<>", "TextPosition anchor_id=6 text_offset=4 " "affinity=downstream annotated_text=Line< >1", - "TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", - "TextPosition anchor_id=3 text_offset=5 " - "affinity=downstream annotated_text=Check< >box", - "TextPosition anchor_id=2 text_offset=6 " - "affinity=downstream annotated_text=Button<>", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -2343,28 +2466,17 @@ AXBoundaryBehavior::StopAtAnchorBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=26 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine< >2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=19 " - "affinity=downstream annotated_text=ButtonCheck boxLine< " - ">1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=11 " - "affinity=downstream annotated_text=ButtonCheck< >boxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=6 " - "affinity=downstream annotated_text=Button<C>heck boxLine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + 13 /* text_offset at end of root. */, + { + "TextPosition anchor_id=1 text_offset=11 " + "affinity=downstream annotated_text=Line 1\nLine< >2", + "TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=4 " + "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + }}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2407,10 +2519,9 @@ AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>"}}, + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2448,12 +2559,8 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", + {"TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( @@ -2491,15 +2598,10 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>"}}, + {"TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2538,8 +2640,9 @@ ROOT_ID, 0 /* text_offset */, {"TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2547,6 +2650,8 @@ TEXT_FIELD_ID, 0 /* text_offset */, {"TextPosition anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "TextPosition anchor_id=4 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( @@ -2575,16 +2680,11 @@ AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, - 28 /* text_offset at the end of root. */, - {"TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", + 13 /* text_offset at the end of root. */, + {"TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineStartPosition( @@ -2596,8 +2696,6 @@ "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=4 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1\nLine 2", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineStartPosition( @@ -2607,8 +2705,6 @@ 5 /* text_offset */, {"TextPosition anchor_id=5 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineStartPosition( @@ -2620,8 +2716,6 @@ "affinity=downstream annotated_text=<L>ine 2", "TextPosition anchor_id=6 text_offset=0 " "affinity=downstream annotated_text=<L>ine 1", - "TextPosition anchor_id=2 text_offset=0 " - "affinity=downstream annotated_text=<B>utton", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -2633,19 +2727,13 @@ AXBoundaryBehavior::StopAtAnchorBoundary); }), ROOT_ID, - 28 /* text_offset at the end of root. */, - {"TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=downstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", + 13 /* text_offset at the end of root. */, + {"TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2", + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineStartPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2688,13 +2776,11 @@ AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), ROOT_ID, - 28 /* text_offset at the end of root. */, - {"TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2", - "TextPosition anchor_id=1 text_offset=22 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\n<L>ine 2"}}, + 13 /* text_offset at the end of root. */, + {"TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=1 text_offset=7 " + "affinity=downstream annotated_text=Line 1\n<L>ine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineStartPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2736,15 +2822,10 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine 1" - "<\n>Line 2", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>", + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineEndPosition( @@ -2788,18 +2869,12 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine 1" - "<\n>Line 2", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>", - "TextPosition anchor_id=1 text_offset=28 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1\nLine 2<>"}}, + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2843,12 +2918,10 @@ }), ROOT_ID, 0 /* text_offset */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2"}}, + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -2884,22 +2957,15 @@ CreatePreviousLineEndPositionWithBoundaryBehaviorCrossBoundary, AXPositionTestWithParam, testing::Values( - // Note that for the first two tests we can't go past the line ending at - // "Line 1" to test for "NullPosition'", because the text position at - // the beginning of the soft line break is equivalent to the position at - // the end of the line's text and so an infinite recursion will occur. TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2"}}, + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); @@ -2908,39 +2974,29 @@ 13 /* text_offset at end of text field */, {"TextPosition anchor_id=4 text_offset=6 " "affinity=downstream annotated_text=Line 1<\n>Line 2", - "TextPosition anchor_id=4 text_offset=6 " - "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, + "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); }), ROOT_ID, - 20 /* text_offset on the last character of "line 1". */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", - "NullPosition"}}, + 5 /* text_offset on the last character of "Line 1". */, + {"NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 5 /* text_offset on the last character of "Line 1". */, - {"TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", - "NullPosition"}}, + {"NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); }), INLINE_BOX2_ID, 4 /* text_offset */, - {"TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>", - "TextPosition anchor_id=6 text_offset=6 " + {"TextPosition anchor_id=6 text_offset=6 " "affinity=downstream annotated_text=Line 1<>", - "TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( @@ -2948,12 +3004,8 @@ }), INLINE_BOX2_ID, 0 /* text_offset */, - {"TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>", - "TextPosition anchor_id=6 text_offset=6 " + {"TextPosition anchor_id=6 text_offset=6 " "affinity=downstream annotated_text=Line 1<>", - "TextPosition anchor_id=3 text_offset=9 " - "affinity=downstream annotated_text=Check box<>", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -2969,13 +3021,11 @@ AXBoundaryBehavior::StopAtAnchorBoundary); }), ROOT_ID, - 28 /* text_offset at end of root. */, - {"TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2"}}, + 13 /* text_offset at end of root. */, + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -2984,20 +3034,18 @@ 13 /* text_offset at end of text field */, {"TextPosition anchor_id=4 text_offset=6 " "affinity=downstream annotated_text=Line 1<\n>Line 2", - "TextPosition anchor_id=4 text_offset=6 " - "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, + "TextPosition anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); }), ROOT_ID, - 20 /* text_offset on the last character of "line 1". */, - {"TextPosition anchor_id=1 text_offset=15 " - "affinity=upstream annotated_text=ButtonCheck box<L>ine " - "1\nLine 2", + 5 /* text_offset on the last character of "Line 1". */, + {"TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "TextPosition anchor_id=1 text_offset=0 " - "affinity=downstream annotated_text=<B>uttonCheck boxLine " - "1\nLine 2"}}, + "affinity=downstream annotated_text=<L>ine 1\nLine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopAtAnchorBoundary); @@ -3015,6 +3063,8 @@ INLINE_BOX2_ID, 4 /* text_offset */, {"TextPosition anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition anchor_id=9 text_offset=0 " "affinity=downstream annotated_text=<L>ine 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( @@ -3023,6 +3073,8 @@ INLINE_BOX2_ID, 0 /* text_offset */, {"TextPosition anchor_id=9 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 2", + "TextPosition anchor_id=9 text_offset=0 " "affinity=downstream annotated_text=<L>ine 2"}})); INSTANTIATE_TEST_SUITE_P( @@ -3034,13 +3086,11 @@ AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), ROOT_ID, - 27 /* text_offset one before the end of root. */, - {"TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2", - "TextPosition anchor_id=1 text_offset=21 " - "affinity=downstream annotated_text=ButtonCheck boxLine " - "1<\n>Line 2"}}, + 12 /* text_offset one before the end of root. */, + {"TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=6 " + "affinity=downstream annotated_text=Line 1<\n>Line 2"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); @@ -3057,20 +3107,20 @@ }), INLINE_BOX2_ID, 4 /* text_offset */, - {"TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>", - "TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>"}}, + {"TextPosition anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), INLINE_BOX2_ID, 0 /* text_offset */, - {"TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>", - "TextPosition anchor_id=7 text_offset=0 " - "affinity=downstream annotated_text=<\n>"}})); + {"TextPosition anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>", + "TextPosition anchor_id=6 text_offset=6 " + "affinity=downstream annotated_text=Line 1<>"}})); // // Tests for |AXRange|. @@ -3079,15 +3129,16 @@ // TODO(nektar): Move these tests to their own file. TEST_F(AXPositionTest, AXRangeGetTextWithWholeObjects) { - base::string16 all_text = base::UTF8ToUTF16("ButtonCheck boxLine 1\nLine 2"); + base::string16 all_text = base::UTF8ToUTF16("Line 1\nLine 2"); // Create a range starting from the button object and ending at the last // character of the root, i.e. at the last character of the second line in the // text field. TestPositionType start = AXNodePosition::CreateTreePosition( tree_.data().tree_id, root_.id, 0 /* child_index */); TestPositionType end = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, root_.id, 28 /* text_offset */, + tree_.data().tree_id, root_.id, 13 /* text_offset */, ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(end->IsTextPosition()); AXRange<AXPosition<AXNodePosition, AXNode>> forward_range(start->Clone(), end->Clone()); EXPECT_EQ(all_text, forward_range.GetText()); @@ -3097,15 +3148,17 @@ } TEST_F(AXPositionTest, AXRangeGetTextWithTextOffsets) { - base::string16 most_text = base::UTF8ToUTF16("tonCheck boxLine 1\nLine"); - // Create a range starting from the third character in the button object and - // ending two characters before the end of the root. + base::string16 most_text = base::UTF8ToUTF16("Line 1\nLine"); + // Create a range starting from the button object and ending two characters + // before the end of the root. TestPositionType start = AXNodePosition::CreateTextPosition( - tree_.data().tree_id, button_.id, 3 /* text_offset */, + tree_.data().tree_id, button_.id, 0 /* text_offset */, ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(start->IsTextPosition()); TestPositionType end = AXNodePosition::CreateTextPosition( tree_.data().tree_id, static_text2_.id, 4 /* text_offset */, ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(end->IsTextPosition()); AXRange<AXPosition<AXNodePosition, AXNode>> forward_range(start->Clone(), end->Clone()); EXPECT_EQ(most_text, forward_range.GetText());
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 0a6bb57..6579e216 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -14,6 +14,7 @@ #include <vector> #include "base/containers/stack.h" +#include "base/optional.h" #include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" @@ -298,6 +299,15 @@ NOTREACHED(); return false; case AXPositionKind::TEXT_POSITION: + // Text positions on objects with no text should not be considered at + // end of line because the empty position may share a text offset with + // a non-empty text position in which case the end of line iterators + // must move to the line end of the non-empty content. Specified next + // line IDs are ignored. + if (!text_position->MaxTextOffset()) { + return false; + } + // If affinity has been used to specify whether the caret is at the end // of a line or at the start of the next one, this should have been // reflected in the leaf text position we got. In other cases, we @@ -695,32 +705,38 @@ return clone; } - const std::vector<int32_t> word_starts = - text_position->GetWordStartOffsets(); + std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); auto iterator = std::upper_bound(word_starts.begin(), word_starts.end(), static_cast<int32_t>(text_position->text_offset_)); - if (iterator == word_starts.end()) { - // Ignore any nodes with no text or no word boundaries. - do { - text_position = text_position->CreateNextTextAnchorPosition(); - } while (!text_position->IsNullPosition() && - (!text_position->MaxTextOffset() || - text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; + do { + if (iterator == word_starts.end()) { + // Ignore any nodes with no text or no word boundaries. + do { + text_position = text_position->CreateNextTextAnchorPosition(); + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); + return text_position; + } + } while (!text_position->MaxTextOffset() || + text_position->GetWordStartOffsets().empty()); + + word_starts = text_position->GetWordStartOffsets(); + DCHECK(!word_starts.empty()); + iterator = + std::upper_bound(word_starts.begin(), word_starts.end(), + static_cast<int32_t>(text_position->text_offset_)); + text_position->text_offset_ = static_cast<int>(word_starts[0]); + } else { + text_position->text_offset_ = static_cast<int>(*iterator); + text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; } - const std::vector<int32_t> updated_word_starts = - text_position->GetWordStartOffsets(); - DCHECK(!updated_word_starts.empty()); - text_position->text_offset_ = static_cast<int>(updated_word_starts[0]); - } else { - text_position->text_offset_ = static_cast<int>(*iterator); - text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; - } + // Continue searching for the next word start until the next logical text + // position is reached. + } while (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position); // If the word boundary is in the same subtree, return a position rooted // at the current position. This is necessary because we don't want to @@ -750,43 +766,40 @@ return clone; } - if (text_position->AtStartOfAnchor()) { - text_position = text_position->CreatePreviousTextAnchorPosition(); - text_position = text_position->CreatePositionAtEndOfAnchor(); - } - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; - } - - const std::vector<int32_t> word_starts = - text_position->GetWordStartOffsets(); + std::vector<int32_t> word_starts = text_position->GetWordStartOffsets(); auto iterator = std::lower_bound(word_starts.begin(), word_starts.end(), static_cast<int32_t>(text_position->text_offset_)); - if (word_starts.empty() || iterator == word_starts.begin()) { - // Ignore any nodes with no text or no word boundaries. - do { - text_position = text_position->CreatePreviousTextAnchorPosition(); - } while (!text_position->IsNullPosition() && - (!text_position->MaxTextOffset() || - text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; + do { + if (word_starts.empty() || iterator == word_starts.begin()) { + // Ignore any nodes with no text or no word boundaries. + do { + text_position = text_position->CreatePreviousTextAnchorPosition() + ->CreatePositionAtEndOfAnchor(); + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); + return text_position; + } + } while (!text_position->MaxTextOffset() || + text_position->GetWordStartOffsets().empty()); + + word_starts = text_position->GetWordStartOffsets(); + DCHECK(!word_starts.empty()); + iterator = + std::upper_bound(word_starts.begin(), word_starts.end(), + static_cast<int32_t>(text_position->text_offset_)); + text_position->text_offset_ = + static_cast<int>(*(word_starts.end() - 1)); + } else { + text_position->text_offset_ = static_cast<int>(*(--iterator)); + text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; } - const std::vector<int32_t> updated_word_starts = - text_position->GetWordStartOffsets(); - DCHECK(!updated_word_starts.empty()); - text_position->text_offset_ = - static_cast<int>(*(updated_word_starts.end() - 1)); - } else { - text_position->text_offset_ = static_cast<int>(*(--iterator)); - text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; - } + // Continue searching for the previous word start until the next logical + // text position is reached. + } while (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position); // If the word boundary is in the same subtree, return a position rooted // at the current position. This is necessary because we don't want to @@ -823,39 +836,38 @@ return clone; } - if (text_position->AtEndOfAnchor()) - text_position = text_position->CreateNextTextAnchorPosition(); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; - } - - const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); + std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); auto iterator = std::upper_bound(word_ends.begin(), word_ends.end(), static_cast<int32_t>(text_position->text_offset_)); - if (iterator == word_ends.end()) { - // Ignore any nodes with no text or no word boundaries. - do { - text_position = text_position->CreateNextTextAnchorPosition(); - } while (!text_position->IsNullPosition() && - (!text_position->MaxTextOffset() || - text_position->GetWordEndOffsets().empty())); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; + do { + if (iterator == word_ends.end()) { + // Ignore any nodes with no text or no word boundaries. + do { + text_position = text_position->CreateNextTextAnchorPosition(); + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); + return text_position; + } + } while (!text_position->MaxTextOffset() || + text_position->GetWordEndOffsets().empty()); + + word_ends = text_position->GetWordEndOffsets(); + DCHECK(!word_ends.empty()); + iterator = + std::upper_bound(word_ends.begin(), word_ends.end(), + static_cast<int32_t>(text_position->text_offset_)); + text_position->text_offset_ = static_cast<int>(word_ends[0]); + } else { + text_position->text_offset_ = static_cast<int>(*iterator); + text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; } - const std::vector<int32_t> updated_word_ends = - text_position->GetWordEndOffsets(); - DCHECK(!updated_word_ends.empty()); - text_position->text_offset_ = static_cast<int>(updated_word_ends[0]); - } else { - text_position->text_offset_ = static_cast<int>(*iterator); - text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; - } + // Continue searching for the next word end until the next logical text + // position is reached. + } while (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position); // If the word boundary is in the same subtree, return a position rooted // at the current position. This is necessary because we don't want to @@ -892,42 +904,39 @@ return clone; } - if (text_position->AtStartOfAnchor()) { - text_position = text_position->CreatePreviousTextAnchorPosition(); - text_position = text_position->CreatePositionAtEndOfAnchor(); - } - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; - } - - const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); + std::vector<int32_t> word_ends = text_position->GetWordEndOffsets(); auto iterator = std::lower_bound(word_ends.begin(), word_ends.end(), static_cast<int32_t>(text_position->text_offset_)); - if (word_ends.empty() || iterator == word_ends.begin()) { - // Ignore any nodes with no text or no word boundaries. - do { - text_position = text_position->CreatePreviousTextAnchorPosition(); - } while (!text_position->IsNullPosition() && - (!text_position->MaxTextOffset() || - text_position->GetWordStartOffsets().empty())); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; + do { + if (word_ends.empty() || iterator == word_ends.begin()) { + // Ignore any nodes with no text or no word boundaries. + do { + text_position = text_position->CreatePreviousTextAnchorPosition() + ->CreatePositionAtEndOfAnchor(); + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); + return text_position; + } + } while (!text_position->MaxTextOffset() || + text_position->GetWordStartOffsets().empty()); + + word_ends = text_position->GetWordEndOffsets(); + DCHECK(!word_ends.empty()); + iterator = + std::lower_bound(word_ends.begin(), word_ends.end(), + static_cast<int32_t>(text_position->text_offset_)); + text_position->text_offset_ = static_cast<int>(*(word_ends.end() - 1)); + } else { + text_position->text_offset_ = static_cast<int>(*(--iterator)); + text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; } - const std::vector<int32_t> updated_word_ends = - text_position->GetWordEndOffsets(); - DCHECK(!updated_word_ends.empty()); - text_position->text_offset_ = - static_cast<int>(*(updated_word_ends.end() - 1)); - } else { - text_position->text_offset_ = static_cast<int>(*(--iterator)); - text_position->affinity_ = ax::mojom::TextAffinity::kDownstream; - } + // Continue searching for the previous word end until the next logical + // text position is reached. + } while (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position); // If the word boundary is in the same subtree, return a position rooted // at the current position. This is necessary because we don't want to @@ -961,13 +970,18 @@ do { text_position = text_position->CreateNextTextAnchorPosition(); - } while (!text_position->AtStartOfLine() && - !text_position->IsNullPosition()); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; - } + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); + return text_position; + } + + // Continue searching for the next line start until the next logical text + // position is reached. + } while ( + !text_position->AtStartOfLine() || + (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position)); // If the line boundary is in the same subtree, return a position rooted at // the current position. @@ -997,21 +1011,25 @@ return clone; } - if (text_position->AtStartOfAnchor()) { - text_position = text_position->CreatePreviousTextAnchorPosition(); - } else { - text_position = text_position->CreatePositionAtStartOfAnchor(); - } + do { + if (text_position->AtStartOfAnchor()) { + text_position = text_position->CreatePreviousTextAnchorPosition(); + } else { + text_position = text_position->CreatePositionAtStartOfAnchor(); + } - while (!text_position->AtStartOfLine() && - !text_position->IsNullPosition()) { - text_position = text_position->CreatePreviousTextAnchorPosition(); - } - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; - } + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); + return text_position; + } + + // Continue searching for the previous line start until the next logical + // text position is reached. + } while ( + !text_position->AtStartOfLine() || + (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position)); // If the line boundary is in the same subtree, return a position rooted at // the current position. @@ -1049,29 +1067,31 @@ return clone; } - if (text_position->AtEndOfAnchor()) { - text_position = text_position->CreateNextTextAnchorPosition() - ->CreatePositionAtEndOfAnchor(); - } else { - text_position = text_position->CreatePositionAtEndOfAnchor(); - } + do { + if (text_position->AtEndOfAnchor()) { + text_position = text_position->CreateNextTextAnchorPosition() + ->CreatePositionAtEndOfAnchor(); + } else { + text_position = text_position->CreatePositionAtEndOfAnchor(); + } - while (!text_position->AtEndOfLine() && !text_position->IsNullPosition()) { - text_position = text_position->CreateNextTextAnchorPosition(); - if (text_position->AtEndOfLine()) - break; - text_position = text_position->CreatePositionAtEndOfAnchor(); - } - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; - } + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtEndOfAnchor(); + return text_position; + } + + // Continue searching for the next line end until the next logical text + // position is reached. + } while ( + !text_position->AtEndOfLine() || + (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position)); // If the line boundary is in the same subtree, return a position rooted at - // the current position. - // This is necessary because we don't want to return any position that might - // be in the shadow DOM if the original position was not. + // the current position. This is necessary because we don't want to return + // any position that might be in the shadow DOM if the original position was + // not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); if (GetAnchor() == common_ancestor->GetAnchor()) { @@ -1109,20 +1129,23 @@ do { text_position = text_position->CreatePreviousTextAnchorPosition() ->CreatePositionAtEndOfAnchor(); - if (text_position->AtEndOfLine()) - break; - text_position = text_position->CreatePositionAtStartOfAnchor(); - } while (!text_position->AtEndOfLine() && !text_position->IsNullPosition()); - if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; - } + if (text_position->IsNullPosition()) { + if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) + return CreatePositionAtStartOfAnchor(); + return text_position; + } + + // Continue searching for the previous line end until the next logical + // text position is reached. + } while ( + !text_position->AtEndOfLine() || + (boundary_behavior != AXBoundaryBehavior::StopIfAlreadyAtBoundary && + *this == *text_position)); // If the line boundary is in the same subtree, return a position rooted at - // the current position. - // This is necessary because we don't want to return any position that might - // be in the shadow DOM if the original position was not. + // the current position. This is necessary because we don't want to return + // any position that might be in the shadow DOM if the original position was + // not. AXPositionInstance common_ancestor = text_position->LowestCommonAncestor(*this); if (GetAnchor() == common_ancestor->GetAnchor()) { @@ -1199,14 +1222,108 @@ return leaf; } + // Returns an optional integer indicating the logical order of this position + // compared to another position or returns an empty optional if the positions + // are not comparable. Any text position at the same character location is + // logically equivalent although they may be on different anchors or have + // different text offsets. Positions are not comparable when one position is + // null and the other is not or if the positions do not have any common + // ancestor. + // 0: if this position is logically equivalent to the other position + // <0: if this position is logically less than the other position + // >0: if this position is logically greater than the other position + base::Optional<int> CompareTo( + const AXPosition<AXPositionType, AXNodeType>& other) const { + if (this->IsNullPosition() && other.IsNullPosition()) + return base::Optional<int>(0); + if (this->IsNullPosition() || other.IsNullPosition()) + return base::Optional<int>(base::nullopt); + + // It is potentially costly to compute the parent position of a text + // position, whilst computing the parent position of a tree position is + // really inexpensive. In order to find the lowest common ancestor, + // especially if that ancestor is all the way up to the root of the tree, + // this will need to be done repeatedly. We avoid the performance hit by + // converting both positions to tree positions and only falling back to text + // positions if both are text positions and the lowest common ancestor is + // not one of their anchors. Essentially, the question we need to answer is: + // "When are two non equivalent positions going to have the same lowest + // common ancestor position when converted to tree positions?" The answer is + // when they are both text positions and they either have the same anchor, + // or one is the ancestor of the other. + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> this_tree_position = + this->AsTreePosition(); + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + other_tree_position = other.AsTreePosition(); + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + this_tree_position_ancestor = + this_tree_position->LowestCommonAncestor(*other_tree_position); + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + other_tree_position_ancestor = + other_tree_position->LowestCommonAncestor(*this_tree_position); + DCHECK_EQ(this_tree_position_ancestor->GetAnchor(), + other_tree_position_ancestor->GetAnchor()); + if (this_tree_position_ancestor->IsNullPosition()) + return base::Optional<int>(base::nullopt); + DCHECK(this_tree_position_ancestor->IsTreePosition() && + other_tree_position_ancestor->IsTreePosition()); + + // Attempt to avoid recomputing the lowest common ancestor because we may + // already have its anchor in which case just find the text offset. + if (this->IsTextPosition() && other.IsTextPosition()) { + // This text position's anchor is the common ancestor of the other text + // position's anchor. + if (this->GetAnchor() == other_tree_position_ancestor->GetAnchor()) { + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + other_text_position = other.Clone(); + while (other_text_position->GetAnchor() != this->GetAnchor()) + other_text_position = other_text_position->CreateParentPosition(); + return base::Optional<int>(this->text_offset_ - + other_text_position->text_offset_); + } + + // The other text position's anchor is the common ancestor of this text + // position's anchor. + if (other.GetAnchor() == this_tree_position_ancestor->GetAnchor()) { + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + this_text_position = this->Clone(); + while (this_text_position->GetAnchor() != other.GetAnchor()) + this_text_position = this_text_position->CreateParentPosition(); + return base::Optional<int>(this_text_position->text_offset_ - + other.text_offset_); + } + + // All optimizations failed. Fall back to comparing text positions with + // the common text position ancestor. + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + this_text_position_ancestor = this->LowestCommonAncestor(other); + std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> + other_text_position_ancestor = other.LowestCommonAncestor(*this); + DCHECK(this_text_position_ancestor->IsTextPosition()); + DCHECK(other_text_position_ancestor->IsTextPosition()); + DCHECK_EQ(this_text_position_ancestor->GetAnchor(), + other_text_position_ancestor->GetAnchor()); + return base::Optional<int>(this_text_position_ancestor->text_offset_ - + other_text_position_ancestor->text_offset_); + } + + return base::Optional<int>(this_tree_position_ancestor->child_index() - + other_tree_position_ancestor->child_index()); + } + + // Returns the length of the text that is present inside the anchor node, + // including any text found in descendant text nodes. + int MaxTextOffset() const { + if (IsNullPosition()) + return INVALID_INDEX; + return static_cast<int>(GetInnerText().length()); + } + // Abstract methods. // Returns the text that is present inside the anchor node, including any text // found in descendant nodes. virtual base::string16 GetInnerText() const = 0; - // Returns the length of the text that is present inside the anchor node, - // including any text found in descendant text nodes. - virtual int MaxTextOffset() const = 0; protected: AXPosition() = default; @@ -1312,94 +1429,57 @@ template <class AXPositionType, class AXNodeType> bool operator==(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - if (first.IsNullPosition() && second.IsNullPosition()) - return true; - return first.tree_id() == second.tree_id() && - first.anchor_id() == second.anchor_id() && - first.child_index() == second.child_index() && - first.text_offset() == second.text_offset() && - first.affinity() == second.affinity(); + return first.CompareTo(second) == 0; + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() == 0; + return false; } template <class AXPositionType, class AXNodeType> bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - return !(first == second); + return first.CompareTo(second) != 0; + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() != 0; + return false; } template <class AXPositionType, class AXNodeType> bool operator<(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - if (first.IsNullPosition() || second.IsNullPosition()) - return false; - - // It is potentially costly to compute the parent position of a text position, - // whilst computing the parent position of a tree position is really - // inexpensive. In order to find the lowest common ancestor, especially if - // that ancestor is all the way up to the root of the tree, this will need to - // be done repeatedly. We avoid the performance hit by converting both - // positions to tree positions and only falling back to text positions if both - // are text positions and the lowest common ancestor is not one of their - // anchors. Essentially, the question we need to answer is: "When are two non - // equivalent positions going to have the same lowest common ancestor position - // when converted to tree positions?" The answer is when they are both text - // positions and they either have the same anchor, or one is the ancestor of - // the other. - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> tree_first = - first.AsTreePosition(); - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> tree_second = - second.AsTreePosition(); - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> first_ancestor = - tree_first->LowestCommonAncestor(*tree_second); - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> second_ancestor = - tree_second->LowestCommonAncestor(*tree_first); - DCHECK_EQ(first_ancestor->GetAnchor(), second_ancestor->GetAnchor()); - if (first_ancestor->IsNullPosition()) - return false; - DCHECK(first_ancestor->IsTreePosition() && second_ancestor->IsTreePosition()); - - if (first.IsTextPosition() && second.IsTextPosition()) { - // We avoid recomputing lowest common ancestor, because we already have its - // anchor. We just need its text offset. - if (first.GetAnchor() == first_ancestor->GetAnchor()) { - // If both positions have the same anchor, or if the first is an ancestor - // of the second. - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> text_second = - second.Clone(); - while (text_second->GetAnchor() != first.GetAnchor()) - text_second = text_second->CreateParentPosition(); - return first.text_offset() < text_second->text_offset(); - } else if (second.GetAnchor() == second_ancestor->GetAnchor()) { - // If the second position is an ancestor of the first. - std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> text_first = - first.Clone(); - while (text_first->GetAnchor() != second.GetAnchor()) - text_first = text_first->CreateParentPosition(); - return text_first->text_offset() < second.text_offset(); - } - } - - return first_ancestor->child_index() < second_ancestor->child_index(); + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() < 0; + return false; } template <class AXPositionType, class AXNodeType> bool operator<=(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - return first == second || first < second; + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() <= 0; + return false; } template <class AXPositionType, class AXNodeType> bool operator>(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - if (first.IsNullPosition() || second.IsNullPosition()) - return false; - return !(first <= second); + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() > 0; + return false; } template <class AXPositionType, class AXNodeType> bool operator>=(const AXPosition<AXPositionType, AXNodeType>& first, const AXPosition<AXPositionType, AXNodeType>& second) { - return first == second || first > second; + const base::Optional<int> compare_to_optional = first.CompareTo(second); + if (compare_to_optional.has_value()) + return compare_to_optional.value() >= 0; + return false; } template <class AXPositionType, class AXNodeType>
diff --git a/ui/accessibility/ax_range.h b/ui/accessibility/ax_range.h index 3f859ce8..0910208c 100644 --- a/ui/accessibility/ax_range.h +++ b/ui/accessibility/ax_range.h
@@ -98,7 +98,7 @@ do { text += start->GetInnerText(); start = start->CreateNextTextAnchorPosition(); - } while (!start->IsNullPosition() && *start <= *end); + } while (!start->IsNullPosition() && *start < *end); if (static_cast<size_t>(start_offset) > text.length()) return base::string16();
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc index 63a05e91..df753014 100644 --- a/ui/accessibility/ax_role_properties.cc +++ b/ui/accessibility/ax_role_properties.cc
@@ -28,8 +28,17 @@ } } -bool IsClickable(const ax::mojom::Role role) { - switch (role) { +bool IsClickable(const AXNodeData& data) { + // If it has a custom default action verb except for + // ax::mojom::DefaultActionVerb::kClickAncestor, it's definitely clickable. + // ax::mojom::DefaultActionVerb::kClickAncestor is used when an element with a + // click listener is present in its ancestry chain. + if (data.HasIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb) && + (data.GetDefaultActionVerb() != + ax::mojom::DefaultActionVerb::kClickAncestor)) + return true; + + switch (data.role) { case ax::mojom::Role::kButton: case ax::mojom::Role::kCheckBox: case ax::mojom::Role::kColorWell: @@ -173,6 +182,15 @@ } } +bool IsInvokable(const AXNodeData& data) { + // A control is "invokable" if it initiates an action when activated but + // does not maintain any state. A control that maintains state when activated + // would be considered a toggle or expand-collapse element - these elements + // are "clickable" but not "invokable". + return IsClickable(data) && !SupportsExpandCollapse(data) && + !SupportsToggle(data.role); +} + bool IsItemLike(const ax::mojom::Role role) { switch (role) { case ax::mojom::Role::kArticle:
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h index dddec99..abbc2a9 100644 --- a/ui/accessibility/ax_role_properties.h +++ b/ui/accessibility/ax_role_properties.h
@@ -11,17 +11,18 @@ namespace ui { -// This file contains various helper functions that determine whether a specific -// accessibility role meets certain criteria. +// This file contains various helper functions that determine whether an +// accessibility node data or a specific accessibility role meets certain +// criteria. // // Please keep these functions in alphabetic order. // Checks if the given role is an alert or alert-dialog type. AX_EXPORT bool IsAlert(const ax::mojom::Role role); -// Checks if the given role should belong to a control that can respond to -// clicks. -AX_EXPORT bool IsClickable(const ax::mojom::Role role); +// Checks if the given ax node data should belong to a control that can respond +// to clicks. +AX_EXPORT bool IsClickable(const AXNodeData& data); // Returns true if the provided role belongs to a cell or a table header. AX_EXPORT bool IsCellOrTableHeader(const ax::mojom::Role role); @@ -45,6 +46,9 @@ // Returns true if the provided role belongs to an image, graphic, canvas, etc. AX_EXPORT bool IsImage(const ax::mojom::Role role); +// Returns true if the provided ax node data is invokable. +AX_EXPORT bool IsInvokable(const AXNodeData& data); + // Returns true if the provided role is item-like, specifically if it can hold // pos_in_set and set_size values. AX_EXPORT bool IsItemLike(const ax::mojom::Role role);
diff --git a/ui/accessibility/ax_role_properties_unittest.cc b/ui/accessibility/ax_role_properties_unittest.cc index 180a427..71e005e 100644 --- a/ui/accessibility/ax_role_properties_unittest.cc +++ b/ui/accessibility/ax_role_properties_unittest.cc
@@ -2,47 +2,224 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <unordered_set> + #include "testing/gtest/include/gtest/gtest.h" +#include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_role_properties.h" namespace ui { -TEST(AXRolePropertiesTest, TestSupportsExpandCollapse) { +TEST(AXRolePropertiesTest, TestIsClickable) { + // Test for ax node data attribute with a custom default action verb. + AXNodeData data_default_action_verb; + + for (int action_verb_idx = + static_cast<int>(ax::mojom::DefaultActionVerb::kMinValue); + action_verb_idx <= + static_cast<int>(ax::mojom::DefaultActionVerb::kMaxValue); + action_verb_idx++) { + data_default_action_verb.SetDefaultActionVerb( + static_cast<ax::mojom::DefaultActionVerb>(action_verb_idx)); + bool is_clickable = IsClickable(data_default_action_verb); + + SCOPED_TRACE(testing::Message() + << "ax::mojom::DefaultActionVerb=" + << ToString(data_default_action_verb.GetDefaultActionVerb()) + << ", Actual: isClickable=" << is_clickable + << ", Expected: isClickable=" << !is_clickable); + + if (data_default_action_verb.GetDefaultActionVerb() == + ax::mojom::DefaultActionVerb::kClickAncestor || + data_default_action_verb.GetDefaultActionVerb() == + ax::mojom::DefaultActionVerb::kNone) + EXPECT_FALSE(is_clickable); + else + EXPECT_TRUE(is_clickable); + } + + // Test for iterating through all roles and validate if a role is clickable. + std::unordered_set<ax::mojom::Role> roles_expected_is_clickable = { + ax::mojom::Role::kButton, + ax::mojom::Role::kCheckBox, + ax::mojom::Role::kColorWell, + ax::mojom::Role::kDisclosureTriangle, + ax::mojom::Role::kDocBackLink, + ax::mojom::Role::kDocBiblioRef, + ax::mojom::Role::kDocGlossRef, + ax::mojom::Role::kDocNoteRef, + ax::mojom::Role::kLink, + ax::mojom::Role::kListBoxOption, + ax::mojom::Role::kMenuButton, + ax::mojom::Role::kMenuItem, + ax::mojom::Role::kMenuItemCheckBox, + ax::mojom::Role::kMenuItemRadio, + ax::mojom::Role::kMenuListOption, + ax::mojom::Role::kMenuListPopup, + ax::mojom::Role::kPopUpButton, + ax::mojom::Role::kRadioButton, + ax::mojom::Role::kSwitch, + ax::mojom::Role::kTab, + ax::mojom::Role::kToggleButton}; + AXNodeData data; - // Test for ax node data attributes/state that support expand collapse. - data.role = ax::mojom::Role::kGenericContainer; - data.SetHasPopup(ax::mojom::HasPopup::kTrue); - EXPECT_TRUE(SupportsExpandCollapse(data)); + for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue); + role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) { + data.role = static_cast<ax::mojom::Role>(role_idx); + bool is_clickable = IsClickable(data); - data.SetHasPopup(ax::mojom::HasPopup::kFalse); - EXPECT_FALSE(SupportsExpandCollapse(data)); + SCOPED_TRACE(testing::Message() + << "ax::mojom::Role=" << ToString(data.role) + << ", Actual: isClickable=" << is_clickable + << ", Expected: isClickable=" << !is_clickable); - data.AddState(ax::mojom::State::kExpanded); - EXPECT_TRUE(SupportsExpandCollapse(data)); - data.RemoveState(ax::mojom::State::kExpanded); + if (roles_expected_is_clickable.find(data.role) != + roles_expected_is_clickable.end()) + EXPECT_TRUE(is_clickable); + else + EXPECT_FALSE(is_clickable); + } +} - data.AddState(ax::mojom::State::kCollapsed); - EXPECT_TRUE(SupportsExpandCollapse(data)); - data.RemoveState(ax::mojom::State::kCollapsed); +TEST(AXRolePropertiesTest, TestIsInvokable) { + // Test for iterating through all roles and validate if a role is invokable. + // A role is invokable if it is clickable and supports neither expand collpase + // nor toggle. + AXNodeData data; + for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue); + role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) { + data.role = static_cast<ax::mojom::Role>(role_idx); + bool supports_expand_collapse = SupportsExpandCollapse(data); + bool supports_toggle = SupportsToggle(data.role); + bool is_clickable = IsClickable(data); + bool is_invokable = IsInvokable(data); - // Test for roles that support expand collapse. - data.role = ax::mojom::Role::kComboBoxGrouping; - EXPECT_TRUE(SupportsExpandCollapse(data)); + SCOPED_TRACE(testing::Message() + << "ax::mojom::Role=" << ToString(data.role) + << ", isClickable=" << is_clickable + << ", supportsToggle=" << supports_toggle + << ", supportsExpandCollapse=" << supports_expand_collapse + << ", Actual: isInvokable=" << is_invokable + << ", Expected: isInvokable=" << !is_invokable); - data.role = ax::mojom::Role::kComboBoxMenuButton; - EXPECT_TRUE(SupportsExpandCollapse(data)); + if (is_clickable && !supports_toggle && !supports_expand_collapse) + EXPECT_TRUE(is_invokable); + else + EXPECT_FALSE(is_invokable); + } +} - data.role = ax::mojom::Role::kDisclosureTriangle; - EXPECT_TRUE(SupportsExpandCollapse(data)); +TEST(AXRolePropertiesTest, TestSupportsExpandCollapse) { + // Test for iterating through all hasPopup attributes and validate if a + // hasPopup attribute supports expand collapse. + AXNodeData data_has_popup; - data.role = ax::mojom::Role::kTextFieldWithComboBox; - EXPECT_TRUE(SupportsExpandCollapse(data)); + for (int has_popup_idx = static_cast<int>(ax::mojom::HasPopup::kMinValue); + has_popup_idx <= static_cast<int>(ax::mojom::HasPopup::kMaxValue); + has_popup_idx++) { + data_has_popup.SetHasPopup(static_cast<ax::mojom::HasPopup>(has_popup_idx)); + bool supports_expand_collapse = SupportsExpandCollapse(data_has_popup); - data.role = ax::mojom::Role::kTreeItem; - EXPECT_TRUE(SupportsExpandCollapse(data)); + SCOPED_TRACE(testing::Message() << "ax::mojom::HasPopup=" + << ToString(data_has_popup.GetHasPopup()) + << ", Actual: supportsExpandCollapse=" + << supports_expand_collapse + << ", Expected: supportsExpandCollapse=" + << !supports_expand_collapse); + + if (data_has_popup.GetHasPopup() == ax::mojom::HasPopup::kFalse) + EXPECT_FALSE(supports_expand_collapse); + else + EXPECT_TRUE(supports_expand_collapse); + } + + // Test for iterating through all states and validate if a state supports + // expand collapse. + AXNodeData data_state; + + for (int state_idx = static_cast<int>(ax::mojom::State::kMinValue); + state_idx <= static_cast<int>(ax::mojom::State::kMaxValue); + state_idx++) { + ax::mojom::State state = static_cast<ax::mojom::State>(state_idx); + + // skipping kNone here because AXNodeData::AddState, RemoveState forbids + // kNone to be added/removed and would fail DCHECK. + if (state == ax::mojom::State::kNone) + continue; + + data_state.AddState(state); + + bool supports_expand_collapse = SupportsExpandCollapse(data_state); + + SCOPED_TRACE(testing::Message() << "ax::mojom::State=" << ToString(state) + << ", Actual: supportsExpandCollapse=" + << supports_expand_collapse + << ", Expected: supportsExpandCollapse=" + << !supports_expand_collapse); + + if (data_state.HasState(ax::mojom::State::kExpanded) || + data_state.HasState(ax::mojom::State::kCollapsed)) + EXPECT_TRUE(supports_expand_collapse); + else + EXPECT_FALSE(supports_expand_collapse); + + data_state.RemoveState(state); + } + + // Test for iterating through all roles and validate if a role supports expand + // collapse. + AXNodeData data; + + std::unordered_set<ax::mojom::Role> roles_expected_supports_expand_collapse = + {ax::mojom::Role::kComboBoxGrouping, ax::mojom::Role::kComboBoxMenuButton, + ax::mojom::Role::kDisclosureTriangle, + ax::mojom::Role::kTextFieldWithComboBox, ax::mojom::Role::kTreeItem}; + + for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue); + role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) { + data.role = static_cast<ax::mojom::Role>(role_idx); + bool supports_expand_collapse = SupportsExpandCollapse(data); + + SCOPED_TRACE(testing::Message() << "ax::mojom::Role=" << ToString(data.role) + << ", Actual: supportsExpandCollapse=" + << supports_expand_collapse + << ", Expected: supportsExpandCollapse=" + << !supports_expand_collapse); + + if (roles_expected_supports_expand_collapse.find(data.role) != + roles_expected_supports_expand_collapse.end()) + EXPECT_TRUE(supports_expand_collapse); + else + EXPECT_FALSE(supports_expand_collapse); + } +} + +TEST(AXRolePropertiesTest, TestSupportsToggle) { + // Test for iterating through all roles and validate if a role supports + // toggle. + std::unordered_set<ax::mojom::Role> roles_expected_supports_toggle = { + ax::mojom::Role::kCheckBox, ax::mojom::Role::kMenuItemCheckBox, + ax::mojom::Role::kSwitch, ax::mojom::Role::kToggleButton}; + + for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue); + role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) { + ax::mojom::Role role = static_cast<ax::mojom::Role>(role_idx); + bool supports_toggle = SupportsToggle(role); + + SCOPED_TRACE(testing::Message() + << "ax::mojom::Role=" << ToString(role) + << ", Actual: supportsToggle=" << supports_toggle + << ", Expected: supportsToggle=" << !supports_toggle); + + if (roles_expected_supports_toggle.find(role) != + roles_expected_supports_toggle.end()) + EXPECT_TRUE(supports_toggle); + else + EXPECT_FALSE(supports_toggle); + } } } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index d360060..abf5cbf 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -35,6 +35,22 @@ #include "ui/accessibility/platform/ax_platform_node_delegate_base.h" #include "ui/gfx/geometry/rect_conversions.h" +#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 12, 0) +#define ATK_212 +#endif + +#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 16, 0) +#define ATK_216 +#endif + +#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 26, 0) +#define ATK_226 +#endif + +#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 30, 0) +#define ATK_230 +#endif + namespace ui { namespace { @@ -181,8 +197,10 @@ return AXPlatformNodeDelegate::Screen; case ATK_XY_WINDOW: return AXPlatformNodeDelegate::Window; +#ifdef ATK_230 case ATK_XY_PARENT: return AXPlatformNodeDelegate::Parent; +#endif // ATK_230 default: return AXPlatformNodeDelegate::Screen; } @@ -341,18 +359,6 @@ "footnote", // ATK_ROLE_FOOTNOTE = 122. }; -#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 12, 0) -#define ATK_212 -#endif - -#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 16, 0) -#define ATK_216 -#endif - -#if defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 26, 0) -#define ATK_226 -#endif - #if defined(ATK_216) constexpr AtkRole kStaticRole = ATK_ROLE_STATIC; constexpr AtkRole kSubscriptRole = ATK_ROLE_SUBSCRIPT;
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index 577bf26..9710c02 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -1138,4 +1138,246 @@ base::ReplaceChars(*output, ";", "\\;", output); } +AXPlatformNodeBase* AXPlatformNodeBase::GetHyperlinkFromHypertextOffset( + int offset) { + std::map<int32_t, int32_t>::iterator iterator = + hypertext_.hyperlink_offset_to_index.find(offset); + if (iterator == hypertext_.hyperlink_offset_to_index.end()) + return nullptr; + + int32_t index = iterator->second; + DCHECK_GE(index, 0); + DCHECK_LT(index, static_cast<int32_t>(hypertext_.hyperlinks.size())); + int32_t id = hypertext_.hyperlinks[index]; + auto* hyperlink = + static_cast<AXPlatformNodeBase*>(AXPlatformNodeBase::GetFromUniqueId(id)); + if (!hyperlink) + return nullptr; + return hyperlink; +} + +int32_t AXPlatformNodeBase::GetHyperlinkIndexFromChild( + AXPlatformNodeBase* child) { + if (hypertext_.hyperlinks.empty()) + return -1; + + auto iterator = std::find(hypertext_.hyperlinks.begin(), + hypertext_.hyperlinks.end(), child->GetUniqueId()); + if (iterator == hypertext_.hyperlinks.end()) + return -1; + + return static_cast<int32_t>(iterator - hypertext_.hyperlinks.begin()); +} + +int32_t AXPlatformNodeBase::GetHypertextOffsetFromHyperlinkIndex( + int32_t hyperlink_index) { + for (auto& offset_index : hypertext_.hyperlink_offset_to_index) { + if (offset_index.second == hyperlink_index) + return offset_index.first; + } + return -1; +} + +int32_t AXPlatformNodeBase::GetHypertextOffsetFromChild( + AXPlatformNodeBase* child) { + // TODO(dougt) DCHECK(child.owner()->PlatformGetParent() == owner()); + + // Handle the case when we are dealing with a text-only child. + // Note that this object might be a platform leaf, e.g. an ARIA searchbox. + // Also, text-only children should not be present at tree roots and so no + // cross-tree traversal is necessary. + if (child->IsTextOnlyObject()) { + int32_t hypertext_offset = 0; + int32_t index_in_parent = child->GetDelegate()->GetIndexInParent(); + DCHECK_GE(index_in_parent, 0); + DCHECK_LT(index_in_parent, + static_cast<int32_t>(GetDelegate()->GetChildCount())); + for (uint32_t i = 0; i < static_cast<uint32_t>(index_in_parent); ++i) { + auto* sibling = static_cast<AXPlatformNodeBase*>( + FromNativeViewAccessible(GetDelegate()->ChildAtIndex(i))); + DCHECK(sibling); + if (sibling->IsTextOnlyObject()) { + hypertext_offset += (int32_t)sibling->GetText().size(); + } else { + ++hypertext_offset; + } + } + return hypertext_offset; + } + + int32_t hyperlink_index = GetHyperlinkIndexFromChild(child); + if (hyperlink_index < 0) + return -1; + + return GetHypertextOffsetFromHyperlinkIndex(hyperlink_index); +} + +int32_t AXPlatformNodeBase::GetHypertextOffsetFromDescendant( + AXPlatformNodeBase* descendant) { + auto* parent_object = static_cast<AXPlatformNodeBase*>( + FromNativeViewAccessible(descendant->GetDelegate()->GetParent())); + while (parent_object && parent_object != this) { + descendant = parent_object; + parent_object = static_cast<AXPlatformNodeBase*>( + FromNativeViewAccessible(descendant->GetParent())); + } + if (!parent_object) + return -1; + + return parent_object->GetHypertextOffsetFromChild(descendant); +} + +int AXPlatformNodeBase::GetHypertextOffsetFromEndpoint( + AXPlatformNodeBase* endpoint_object, + int endpoint_offset) { + // There are three cases: + // 1. Either the selection endpoint is inside this object or is an ancestor + // of of this object. endpoint_offset should be returned. + // 2. The selection endpoint is a pure descendant of this object. The offset + // of the character corresponding to the subtree in which the endpoint is + // located should be returned. + // 3. The selection endpoint is in a completely different part of the tree. + // Either 0 or text_length should be returned depending on the direction + // that one needs to travel to find the endpoint. + + // Case 1. + // + // IsDescendantOf includes the case when endpoint_object == this. + if (IsDescendantOf(endpoint_object)) + return endpoint_offset; + + AXPlatformNodeBase* common_parent = this; + int32_t index_in_common_parent = GetDelegate()->GetIndexInParent(); + while (common_parent && !endpoint_object->IsDescendantOf(common_parent)) { + index_in_common_parent = common_parent->GetDelegate()->GetIndexInParent(); + common_parent = static_cast<AXPlatformNodeBase*>( + FromNativeViewAccessible(common_parent->GetParent())); + } + if (!common_parent) + return -1; + + DCHECK_GE(index_in_common_parent, 0); + DCHECK(!(common_parent->IsTextOnlyObject())); + + // Case 2. + // + // We already checked in case 1 if our endpoint is inside this object. + // We can safely assume that it is a descendant or in a completely different + // part of the tree. + if (common_parent == this) { + int32_t hypertext_offset = + GetHypertextOffsetFromDescendant(endpoint_object); + auto* parent = static_cast<AXPlatformNodeBase*>( + FromNativeViewAccessible(endpoint_object->GetParent())); + if (parent == this && endpoint_object->IsTextOnlyObject()) { + hypertext_offset += endpoint_offset; + } + + return hypertext_offset; + } + + // Case 3. + // + // We can safely assume that the endpoint is in another part of the tree or + // at common parent, and that this object is a descendant of common parent. + int32_t endpoint_index_in_common_parent = -1; + for (int i = 0; i < common_parent->GetDelegate()->GetChildCount(); ++i) { + auto* child = static_cast<AXPlatformNodeBase*>(FromNativeViewAccessible( + common_parent->GetDelegate()->ChildAtIndex(i))); + DCHECK(child); + if (endpoint_object->IsDescendantOf(child)) { + endpoint_index_in_common_parent = + child->GetDelegate()->GetIndexInParent(); + break; + } + } + DCHECK_GE(endpoint_index_in_common_parent, 0); + + if (endpoint_index_in_common_parent < index_in_common_parent) + return 0; + if (endpoint_index_in_common_parent > index_in_common_parent) + return static_cast<int32_t>(GetText().size()); + + NOTREACHED(); + return -1; +} + +int AXPlatformNodeBase::GetSelectionAnchor() { + int32_t anchor_id = GetDelegate()->GetTreeData().sel_anchor_object_id; + AXPlatformNodeBase* anchor_object = + static_cast<AXPlatformNodeBase*>(GetDelegate()->GetFromNodeID(anchor_id)); + if (!anchor_object) + return -1; + + int anchor_offset = int{GetDelegate()->GetTreeData().sel_anchor_offset}; + return GetHypertextOffsetFromEndpoint(anchor_object, anchor_offset); +} + +int AXPlatformNodeBase::GetSelectionFocus() { + int32_t focus_id = GetDelegate()->GetTreeData().sel_focus_object_id; + AXPlatformNodeBase* focus_object = + static_cast<AXPlatformNodeBase*>(GetDelegate()->GetFromNodeID(focus_id)); + if (!focus_object) + return -1; + + int focus_offset = int{GetDelegate()->GetTreeData().sel_focus_offset}; + return GetHypertextOffsetFromEndpoint(focus_object, focus_offset); +} + +void AXPlatformNodeBase::GetSelectionOffsets(int* selection_start, + int* selection_end) { + DCHECK(selection_start && selection_end); + + if (IsPlainTextField() && + GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, + selection_start) && + GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, selection_end)) { + return; + } + + *selection_start = GetSelectionAnchor(); + *selection_end = GetSelectionFocus(); + if (*selection_start < 0 || *selection_end < 0) + return; + + // There are three cases when a selection would start and end on the same + // character: + // 1. Anchor and focus are both in a subtree that is to the right of this + // object. + // 2. Anchor and focus are both in a subtree that is to the left of this + // object. + // 3. Anchor and focus are in a subtree represented by a single embedded + // object character. + // Only case 3 refers to a valid selection because cases 1 and 2 fall + // outside this object in their entirety. + // Selections that span more than one character are by definition inside + // this object, so checking them is not necessary. + if (*selection_start == *selection_end && !HasCaret()) { + *selection_start = -1; + *selection_end = -1; + return; + } + + // The IA2 Spec says that if the largest of the two offsets falls on an + // embedded object character and if there is a selection in that embedded + // object, it should be incremented by one so that it points after the + // embedded object character. + // This is a signal to AT software that the embedded object is also part of + // the selection. + int* largest_offset = + (*selection_start <= *selection_end) ? selection_end : selection_start; + AXPlatformNodeBase* hyperlink = + GetHyperlinkFromHypertextOffset(*largest_offset); + if (!hyperlink) + return; + + int hyperlink_selection_start, hyperlink_selection_end; + hyperlink->GetSelectionOffsets(&hyperlink_selection_start, + &hyperlink_selection_end); + if (hyperlink_selection_start >= 0 && hyperlink_selection_end >= 0 && + hyperlink_selection_start != hyperlink_selection_end) { + ++(*largest_offset); + } +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h index 3ac7e189..a1e0360 100644 --- a/ui/accessibility/platform/ax_platform_node_base.h +++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -307,6 +307,42 @@ // embedded element character. void UpdateComputedHypertext(); + // Selection helper functions. + // The following functions retrieve the endpoints of the current selection. + // First they check for a local selection found on the current control, e.g. + // when querying the selection on a textarea. + // If not found they retrieve the global selection found on the current frame. + int GetSelectionAnchor(); + int GetSelectionFocus(); + + // Retrieves the selection offsets in the way required by the IA2 APIs. + // selection_start and selection_end are -1 when there is no selection active + // on this object. + // The greatest of the two offsets is one past the last character of the + // selection.) + void GetSelectionOffsets(int* selection_start, int* selection_end); + + // Returns the hyperlink at the given text position, or nullptr if no + // hyperlink can be found. + AXPlatformNodeBase* GetHyperlinkFromHypertextOffset(int offset); + + // Functions for retrieving offsets for hyperlinks and hypertext. + // Return -1 in case of failure. + int32_t GetHyperlinkIndexFromChild(AXPlatformNodeBase* child); + int32_t GetHypertextOffsetFromHyperlinkIndex(int32_t hyperlink_index); + int32_t GetHypertextOffsetFromChild(AXPlatformNodeBase* child); + int32_t GetHypertextOffsetFromDescendant(AXPlatformNodeBase* descendant); + + // If the selection endpoint is either equal to or an ancestor of this object, + // returns endpoint_offset. + // If the selection endpoint is a descendant of this object, returns its + // offset. Otherwise, returns either 0 or the length of the hypertext + // depending on the direction of the selection. + // Returns -1 in case of unexpected failure, e.g. the selection endpoint + // cannot be found in the accessibility tree. + int GetHypertextOffsetFromEndpoint(AXPlatformNodeBase* endpoint_object, + int endpoint_offset); + int32_t GetPosInSet() const; int32_t GetSetSize() const;
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index b78406c91..d535430d 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -318,7 +318,7 @@ // Returns true if |action| should be added implicitly for |data|. bool HasImplicitAction(const ui::AXNodeData& data, ax::mojom::Action action) { - return action == ax::mojom::Action::kDoDefault && ui::IsClickable(data.role); + return action == ax::mojom::Action::kDoDefault && ui::IsClickable(data); } // For roles that show a menu for the default action, ensure "show menu" also
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc index 35782408..89d9996c 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win.cc
@@ -43,30 +43,34 @@ STDMETHODIMP AXPlatformNodeTextProviderWin::GetSelection( SAFEARRAY** selection) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GETSELECTION); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextProviderWin::GetVisibleRanges( SAFEARRAY** visible_ranges) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GETVISIBLERANGES); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextProviderWin::RangeFromChild( IRawElementProviderSimple* child, ITextRangeProvider** range) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_RANGEFROMCHILD); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextProviderWin::RangeFromPoint( UiaPoint uia_point, ITextRangeProvider** range) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_RANGEFROMPOINT); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextProviderWin::get_DocumentRange( ITextRangeProvider** range) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GET_DOCUMENTRANGE); UIA_VALIDATE_TEXTPROVIDER_CALL(); - DVLOG(1) << __func__; *range = nullptr; @@ -103,6 +107,7 @@ STDMETHODIMP AXPlatformNodeTextProviderWin::get_SupportedTextSelection( enum SupportedTextSelection* text_selection) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GET_SUPPORTEDTEXTSELECTION); UIA_VALIDATE_TEXTPROVIDER_CALL(); *text_selection = SupportedTextSelection_Single; @@ -115,11 +120,13 @@ STDMETHODIMP AXPlatformNodeTextProviderWin::GetActiveComposition( ITextRangeProvider** range) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTEDIT_GETACTIVECOMPOSITION); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextProviderWin::GetConversionTarget( ITextRangeProvider** range) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTEDIT_GETCONVERSIONTARGET); return E_NOTIMPL; }
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index ebf36ce..4b2364a 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -47,6 +47,7 @@ // STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Clone( ITextRangeProvider** clone) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_CLONE); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); *clone = nullptr; @@ -56,6 +57,7 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Compare( ITextRangeProvider* other, BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_COMPARE); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); CComPtr<AXPlatformNodeTextRangeProviderWin> other_provider; @@ -77,6 +79,7 @@ ITextRangeProvider* other, TextPatternRangeEndpoint other_endpoint, int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_COMPAREENDPOINTS); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); CComPtr<AXPlatformNodeTextRangeProviderWin> other_provider; @@ -105,6 +108,7 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::ExpandToEnclosingUnit( TextUnit unit) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_EXPANDTOENCLOSINGUNIT); return E_NOTIMPL; } @@ -113,6 +117,7 @@ VARIANT val, BOOL backward, ITextRangeProvider** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_FINDATTRIBUTE); return E_NOTIMPL; } @@ -121,17 +126,20 @@ BOOL backwards, BOOL ignore_case, ITextRangeProvider** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_FINDTEXT); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetAttributeValue( TEXTATTRIBUTEID attribute_id, VARIANT* value) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_GETATTRIBUTEVALUE); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetBoundingRectangles( SAFEARRAY** rectangles) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_GETBOUNDINGRECTANGLES); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); *rectangles = nullptr; @@ -187,6 +195,7 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetEnclosingElement( IRawElementProviderSimple** element) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_GETENCLOSINGELEMENT); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); AXPositionInstance common_ancestor = start_->LowestCommonAncestor(*end_); @@ -202,6 +211,7 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetText(int max_count, BSTR* text) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_GETTEXT); UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); // -1 is a valid value that signifies that the caller wants complete text. @@ -227,6 +237,7 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Move(TextUnit unit, int count, int* units_moved) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_MOVE); return E_NOTIMPL; } @@ -235,6 +246,7 @@ TextUnit unit, int count, int* units_moved) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_MOVEENDPOINTBYUNIT); return E_NOTIMPL; } @@ -242,29 +254,57 @@ TextPatternRangeEndpoint this_endpoint, ITextRangeProvider* other, TextPatternRangeEndpoint other_endpoint) { - return E_NOTIMPL; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_MOVEENPOINTBYRANGE); + UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); + + CComPtr<AXPlatformNodeTextRangeProviderWin> other_provider; + if (other->QueryInterface(&other_provider) != S_OK) { + return UIA_E_INVALIDOPERATION; + } + + const AXPositionInstance& other_provider_endpoint = + (other_endpoint == TextPatternRangeEndpoint_Start) + ? other_provider->start_ + : other_provider->end_; + + if (this_endpoint == TextPatternRangeEndpoint_Start) { + start_ = other_provider_endpoint->Clone(); + if (*start_ > *end_) + end_ = start_->Clone(); + } else { + end_ = other_provider_endpoint->Clone(); + if (*start_ > *end_) + start_ = end_->Clone(); + } + + return S_OK; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Select() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_SELECT); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::AddToSelection() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_ADDTOSELECTION); return UIA_E_INVALIDOPERATION; // not supporting disjoint text selections } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::RemoveFromSelection() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_REMOVEFROMSELECTION); return UIA_E_INVALIDOPERATION; // not supporting disjoint text selections } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::ScrollIntoView( BOOL align_to_top) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_SCROLLINTOVIEW); return E_NOTIMPL; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::GetChildren( SAFEARRAY** children) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_GETCHILDREN); return E_NOTIMPL; }
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index ebfd585..3a98c93 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -185,7 +185,7 @@ text_data.id = 2; text_data.role = ax::mojom::Role::kStaticText; text_data.SetName("some text"); - root_data.child_ids.push_back(2); + root_data.child_ids = {2}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -223,10 +223,10 @@ ComPtr<AXPlatformNodeTextRangeProviderWin> clone_range; text_range_provider->QueryInterface(IID_PPV_ARGS(&original_range)); - text_range_provider->QueryInterface(IID_PPV_ARGS(&clone_range)); + text_range_provider_clone->QueryInterface(IID_PPV_ARGS(&clone_range)); - EXPECT_EQ(GetStart(original_range.Get()), GetStart(clone_range.Get())); - EXPECT_EQ(GetEnd(original_range.Get()), GetEnd(clone_range.Get())); + EXPECT_EQ(*GetStart(original_range.Get()), *GetStart(clone_range.Get())); + EXPECT_EQ(*GetEnd(original_range.Get()), *GetEnd(clone_range.Get())); EXPECT_EQ(GetOwner(original_range.Get()), GetOwner(clone_range.Get())); // Clear original text range provider. @@ -255,8 +255,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); - root_data.child_ids.push_back(3); + root_data.child_ids = {2, 3}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -329,8 +328,8 @@ TextPatternRangeEndpoint_Start, &result)); EXPECT_EQ(1, result); - // Compare the endpoints of "some text" and "more text". "more text" comes - // after "some text", so the endpoints of "some text" precede those of + // Compare the endpoints of "some text" and "more text". The position at the + // end of "some text" is logically equivalent to the position at the start of // "more text". EXPECT_HRESULT_SUCCEEDED(text_range_provider->CompareEndpoints( TextPatternRangeEndpoint_Start, more_text_range_provider.Get(), @@ -340,13 +339,15 @@ EXPECT_HRESULT_SUCCEEDED(text_range_provider->CompareEndpoints( TextPatternRangeEndpoint_End, more_text_range_provider.Get(), TextPatternRangeEndpoint_Start, &result)); - EXPECT_EQ(-1, result); + EXPECT_EQ(0, result); - // Compare the endpoints of "some text" with those of the entire document. + // Compare the endpoints of "some text" with those of the entire document. The + // position at the start of "some text" is logically equivalent to the + // position at the start of the document. EXPECT_HRESULT_SUCCEEDED(text_range_provider->CompareEndpoints( TextPatternRangeEndpoint_Start, document_text_range_provider.Get(), TextPatternRangeEndpoint_Start, &result)); - EXPECT_EQ(1, result); + EXPECT_EQ(0, result); EXPECT_HRESULT_SUCCEEDED(text_range_provider->CompareEndpoints( TextPatternRangeEndpoint_End, document_text_range_provider.Get(), @@ -392,6 +393,10 @@ EXPECT_HRESULT_SUCCEEDED( document_provider->get_DocumentRange(&text_range_provider)); + ComPtr<ITextRangeProvider> text_range_provider_clone; + EXPECT_UIA_ELEMENTNOTAVAILABLE( + text_range_provider->Clone(&text_range_provider_clone)); + BOOL compare_result; EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->Compare( text_range_provider.Get(), &compare_result)); @@ -400,6 +405,10 @@ EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->CompareEndpoints( TextPatternRangeEndpoint_Start, text_range_provider.Get(), TextPatternRangeEndpoint_Start, &compare_endpoints_result)); + + EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, text_range_provider.Get(), + TextPatternRangeEndpoint_Start)); } // Test for when this provider is valid, but the other provider is not an @@ -447,6 +456,10 @@ TextPatternRangeEndpoint_Start, other_provider_different_type.Get(), TextPatternRangeEndpoint_Start, &compare_endpoints_result)); + EXPECT_UIA_INVALIDOPERATION(this_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, other_provider_different_type.Get(), + TextPatternRangeEndpoint_Start)); + AXNodePosition::SetTreeForTesting(nullptr); } } @@ -465,8 +478,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); - root_data.child_ids.push_back(3); + root_data.child_ids = {2, 3}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -560,8 +572,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); - root_data.child_ids.push_back(3); + root_data.child_ids = {2, 3}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -644,7 +655,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); + root_data.child_ids = {2}; Init(root_data, text_data); @@ -685,8 +696,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); - root_data.child_ids.push_back(3); + root_data.child_ids = {2, 3}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -759,8 +769,7 @@ ui::AXNodeData root_data; root_data.id = 1; root_data.role = ax::mojom::Role::kRootWebArea; - root_data.child_ids.push_back(2); - root_data.child_ids.push_back(3); + root_data.child_ids = {2, 3}; ui::AXTreeUpdate update; ui::AXTreeData tree_data; @@ -813,4 +822,237 @@ EXPECT_EQ(text_node_raw.Get(), enclosing_element.Get()); } +TEST_F(AXPlatformNodeTextRangeProviderTest, + TestITextRangeProviderMoveEndpointByRange) { + ui::AXNodeData text_data; + text_data.id = 2; + text_data.role = ax::mojom::Role::kStaticText; + text_data.SetName("some text"); + + ui::AXNodeData more_text_data; + more_text_data.id = 3; + more_text_data.role = ax::mojom::Role::kStaticText; + more_text_data.SetName("more text"); + + ui::AXNodeData root_data; + root_data.id = 1; + root_data.role = ax::mojom::Role::kRootWebArea; + root_data.child_ids = {2, 3}; + + ui::AXTreeUpdate update; + ui::AXTreeData tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_data.id; + update.nodes.push_back(root_data); + update.nodes.push_back(text_data); + update.nodes.push_back(more_text_data); + + Init(update); + + AXNode* root_node = GetRootNode(); + AXNodePosition::SetTreeForTesting(tree_.get()); + AXNode* text_node = root_node->children()[0]; + AXNode* more_text_node = root_node->children()[1]; + + // Text range for the document, which contains text "some textmore text". + ComPtr<IRawElementProviderSimple> root_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(root_node); + ComPtr<ITextProvider> document_provider; + EXPECT_HRESULT_SUCCEEDED( + root_node_raw->GetPatternProvider(UIA_TextPatternId, &document_provider)); + ComPtr<ITextRangeProvider> document_text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> document_text_range; + + // Text range related to "some text". + ComPtr<IRawElementProviderSimple> text_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(text_node); + ComPtr<ITextProvider> text_provider; + EXPECT_HRESULT_SUCCEEDED( + text_node_raw->GetPatternProvider(UIA_TextPatternId, &text_provider)); + ComPtr<ITextRangeProvider> text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> text_range; + + // Text range related to "more text". + ComPtr<IRawElementProviderSimple> more_text_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(more_text_node); + ComPtr<ITextProvider> more_text_provider; + EXPECT_HRESULT_SUCCEEDED(more_text_node_raw->GetPatternProvider( + UIA_TextPatternId, &more_text_provider)); + ComPtr<ITextRangeProvider> more_text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> more_text_range; + + // Move the start of document text range "some textmore text" to the end of + // itself. + // The start of document text range "some textmore text" is at the end of + // itself. + // + // Before: + // |s e| + // "some textmore text" + // After: + // |s + // e| + // "some textmore text" + + // Get the textRangeProvider for the document, which contains text + // "some textmore text". + EXPECT_HRESULT_SUCCEEDED( + document_provider->get_DocumentRange(&document_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, document_text_range_provider.Get(), + TextPatternRangeEndpoint_End)); + + document_text_range_provider->QueryInterface( + IID_PPV_ARGS(&document_text_range)); + EXPECT_EQ(*GetStart(document_text_range.Get()), + *GetEnd(document_text_range.Get())); + + // Move the end of document text range "some textmore text" to the start of + // itself. + // The end of document text range "some textmore text" is at the start of + // itself. + // + // Before: + // |s e| + // "some textmore text" + // After: + // |s + // e| + // "some textmore text" + + // Get the textRangeProvider for the document, which contains text + // "some textmore text". + EXPECT_HRESULT_SUCCEEDED( + document_provider->get_DocumentRange(&document_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, document_text_range_provider.Get(), + TextPatternRangeEndpoint_End)); + + document_text_range_provider->QueryInterface( + IID_PPV_ARGS(&document_text_range)); + EXPECT_EQ(*GetStart(document_text_range.Get()), + *GetEnd(document_text_range.Get())); + + // Move the start of document text range "some textmore text" to the start + // of text range "more text". The start of document text range "some + // textmore text" is at the start of text range "more text". The end of + // document range does not change. + // + // Before: + // |s e| + // "some textmore text" + // After: + // |s e| + // "some textmore text" + + // Get the textRangeProvider for the document, which contains text + // "some textmore text". + EXPECT_HRESULT_SUCCEEDED( + document_provider->get_DocumentRange(&document_text_range_provider)); + // Get the textRangeProvider for more_text_node which contains "more text". + EXPECT_HRESULT_SUCCEEDED( + more_text_provider->get_DocumentRange(&more_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, more_text_range_provider.Get(), + TextPatternRangeEndpoint_Start)); + + document_text_range_provider->QueryInterface( + IID_PPV_ARGS(&document_text_range)); + more_text_range_provider->QueryInterface(IID_PPV_ARGS(&more_text_range)); + EXPECT_EQ(*GetStart(document_text_range.Get()), + *GetStart(more_text_range.Get())); + + // Move the end of document text range "some textmore text" to the end of + // text range "some text". + // The end of document text range "some textmore text" is at the end of text + // range "some text". The start of document range does not change. + // + // Before: + // |s e| + // "some textmore text" + // After: + // |s e| + // "some textmore text" + + // Get the textRangeProvider for the document, which contains text + // "some textmore text". + EXPECT_HRESULT_SUCCEEDED( + document_provider->get_DocumentRange(&document_text_range_provider)); + // Get the textRangeProvider for text_node which contains "some text". + EXPECT_HRESULT_SUCCEEDED( + text_provider->get_DocumentRange(&text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(document_text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_End, text_range_provider.Get(), + TextPatternRangeEndpoint_End)); + + document_text_range_provider->QueryInterface( + IID_PPV_ARGS(&document_text_range)); + text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range)); + EXPECT_EQ(*GetEnd(document_text_range.Get()), *GetEnd(text_range.Get())); + + // Move the end of text range "more text" to the start of + // text range "some text". Since the order of the endpoints being moved + // (those of "more text") have to be ensured, both endpoints of "more text" + // is at the start of "some text". + // + // Before: + // |s e| + // "some textmore text" + // After: + // e| + // |s + // "some textmore text" + + // Get the textRangeProvider for text_node which contains "some text". + EXPECT_HRESULT_SUCCEEDED( + text_provider->get_DocumentRange(&text_range_provider)); + // Get the textRangeProvider for more_text_node which contains "more text". + EXPECT_HRESULT_SUCCEEDED( + more_text_provider->get_DocumentRange(&more_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(more_text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_End, text_range_provider.Get(), + TextPatternRangeEndpoint_Start)); + + text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range)); + more_text_range_provider->QueryInterface(IID_PPV_ARGS(&more_text_range)); + EXPECT_EQ(*GetEnd(more_text_range.Get()), *GetStart(text_range.Get())); + EXPECT_EQ(*GetStart(more_text_range.Get()), *GetStart(text_range.Get())); + + // Move the start of text range "some text" to the end of text range + // "more text". Since the order of the endpoints being moved (those + // of "some text") have to be ensured, both endpoints of "some text" is at + // the end of "more text". + // + // Before: + // |s e| + // "some textmore text" + // After: + // |s + // e| + // "some textmore text" + + // Get the textRangeProvider for text_node which contains "some text". + EXPECT_HRESULT_SUCCEEDED( + text_provider->get_DocumentRange(&text_range_provider)); + // Get the textRangeProvider for more_text_node which contains "more text". + EXPECT_HRESULT_SUCCEEDED( + more_text_provider->get_DocumentRange(&more_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(text_range_provider->MoveEndpointByRange( + TextPatternRangeEndpoint_Start, more_text_range_provider.Get(), + TextPatternRangeEndpoint_End)); + + text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range)); + more_text_range_provider->QueryInterface(IID_PPV_ARGS(&more_text_range)); + EXPECT_EQ(*GetStart(text_range.Get()), *GetEnd(more_text_range.Get())); + EXPECT_EQ(*GetEnd(text_range.Get()), *GetEnd(more_text_range.Get())); +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 0320de4..87e9ff0 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -1580,6 +1580,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::Collapse() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_EXPANDCOLLAPSE_COLLAPSE); UIA_VALIDATE_CALL(); if (GetData().GetRestriction() == ax::mojom::Restriction::kDisabled) return UIA_E_ELEMENTNOTAVAILABLE; @@ -1595,6 +1596,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::Expand() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_EXPANDCOLLAPSE_EXPAND); UIA_VALIDATE_CALL(); if (GetData().GetRestriction() == ax::mojom::Restriction::kDisabled) return UIA_E_ELEMENTNOTAVAILABLE; @@ -1611,6 +1613,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_ExpandCollapseState( ExpandCollapseState* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM( + UMA_API_EXPANDCOLLAPSE_GET_EXPANDCOLLAPSESTATE); UIA_VALIDATE_CALL_1_ARG(result); const AXNodeData& data = GetData(); if (data.HasState(ax::mojom::State::kExpanded)) { @@ -1628,12 +1632,14 @@ // IFACEMETHODIMP AXPlatformNodeWin::get_Column(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_COLUMN); UIA_VALIDATE_CALL_1_ARG(result); *result = GetTableColumn(); return S_OK; } IFACEMETHODIMP AXPlatformNodeWin::get_ColumnSpan(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_COLUMNSPAN); UIA_VALIDATE_CALL_1_ARG(result); *result = GetTableColumnSpan(); return S_OK; @@ -1641,6 +1647,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_ContainingGrid( IRawElementProviderSimple** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_CONTAININGGRID); UIA_VALIDATE_CALL_1_ARG(result); AXPlatformNodeBase* table = GetTable(); @@ -1654,12 +1661,14 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_Row(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_ROW); UIA_VALIDATE_CALL_1_ARG(result); *result = GetTableRow(); return S_OK; } IFACEMETHODIMP AXPlatformNodeWin::get_RowSpan(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRIDITEM_GET_ROWSPAN); UIA_VALIDATE_CALL_1_ARG(result); *result = GetTableRowSpan(); return S_OK; @@ -1672,6 +1681,7 @@ IFACEMETHODIMP AXPlatformNodeWin::GetItem(int row, int column, IRawElementProviderSimple** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRID_GETITEM); UIA_VALIDATE_CALL_1_ARG(result); AXPlatformNodeBase* cell = GetTableCell(row, column); @@ -1685,6 +1695,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_RowCount(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRID_GET_ROWCOUNT); UIA_VALIDATE_CALL_1_ARG(result); base::Optional<int32_t> row_count = GetTableAriaRowCount(); @@ -1696,6 +1707,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_ColumnCount(int* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GRID_GET_COLUMNCOUNT); UIA_VALIDATE_CALL_1_ARG(result); base::Optional<int32_t> column_count = GetTableAriaColumnCount(); @@ -1707,10 +1719,29 @@ } // +// IInvokeProvider implementation. +// + +IFACEMETHODIMP AXPlatformNodeWin::Invoke() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_INVOKE_INVOKE); + UIA_VALIDATE_CALL(); + + if (GetData().GetRestriction() == ax::mojom::Restriction::kDisabled) + return UIA_E_ELEMENTNOTENABLED; + + AXActionData action_data; + action_data.action = ax::mojom::Action::kDoDefault; + GetDelegate()->AccessibilityPerformAction(action_data); + + return S_OK; +} + +// // IScrollItemProvider implementation. // IFACEMETHODIMP AXPlatformNodeWin::ScrollIntoView() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLLITEM_SCROLLINTOVIEW); UIA_VALIDATE_CALL(); gfx::Rect r = gfx::ToEnclosingRect(GetData().relative_bounds.bounds); r -= r.OffsetFromOrigin(); @@ -1730,6 +1761,7 @@ IFACEMETHODIMP AXPlatformNodeWin::Scroll(ScrollAmount horizontal_amount, ScrollAmount vertical_amount) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_SCROLL); UIA_VALIDATE_CALL(); if (!IsScrollable()) return E_FAIL; @@ -1746,6 +1778,7 @@ IFACEMETHODIMP AXPlatformNodeWin::SetScrollPercent(double horizontal_percent, double vertical_percent) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_SETSCROLLPERCENT); UIA_VALIDATE_CALL(); if (!IsScrollable()) return E_FAIL; @@ -1768,12 +1801,14 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_HorizontallyScrollable(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_HORIZONTALLYSCROLLABLE); UIA_VALIDATE_CALL_1_ARG(result); *result = IsHorizontallyScrollable(); return S_OK; } IFACEMETHODIMP AXPlatformNodeWin::get_HorizontalScrollPercent(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_HORIZONTALSCROLLPERCENT); UIA_VALIDATE_CALL_1_ARG(result); if (!IsHorizontallyScrollable()) { *result = UIA_ScrollPatternNoScroll; @@ -1790,6 +1825,7 @@ // Horizontal size of the viewable region as a percentage of the total content // area. IFACEMETHODIMP AXPlatformNodeWin::get_HorizontalViewSize(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_HORIZONTALVIEWSIZE); UIA_VALIDATE_CALL_1_ARG(result); if (!IsHorizontallyScrollable()) { *result = 100.; @@ -1806,12 +1842,14 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_VerticallyScrollable(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_VERTICALLYSCROLLABLE); UIA_VALIDATE_CALL_1_ARG(result); *result = IsVerticallyScrollable(); return S_OK; } IFACEMETHODIMP AXPlatformNodeWin::get_VerticalScrollPercent(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_VERTICALSCROLLPERCENT); UIA_VALIDATE_CALL_1_ARG(result); if (!IsVerticallyScrollable()) { *result = UIA_ScrollPatternNoScroll; @@ -1828,6 +1866,7 @@ // Vertical size of the viewable region as a percentage of the total content // area. IFACEMETHODIMP AXPlatformNodeWin::get_VerticalViewSize(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_GET_VERTICALVIEWSIZE); UIA_VALIDATE_CALL_1_ARG(result); if (!IsVerticallyScrollable()) { *result = 100.0; @@ -1873,18 +1912,22 @@ } IFACEMETHODIMP AXPlatformNodeWin::AddToSelection() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTIONITEM_ADDTOSELECTION); return ISelectionItemProviderSetSelected(true); } IFACEMETHODIMP AXPlatformNodeWin::RemoveFromSelection() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTIONITEM_REMOVEFROMSELECTION); return ISelectionItemProviderSetSelected(false); } IFACEMETHODIMP AXPlatformNodeWin::Select() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTIONITEM_SELECT); return ISelectionItemProviderSetSelected(true); } IFACEMETHODIMP AXPlatformNodeWin::get_IsSelected(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTIONITEM_GET_ISSELECTED); UIA_VALIDATE_CALL_1_ARG(result); if (!IsSelectionItemSupported()) @@ -1922,6 +1965,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_SelectionContainer( IRawElementProviderSimple** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTIONITEM_GET_SELECTIONCONTAINER); UIA_VALIDATE_CALL_1_ARG(result); auto* node_win = static_cast<AXPlatformNodeWin*>(GetSelectionContainer()); @@ -1938,6 +1982,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::GetSelection(SAFEARRAY** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTION_GETSELECTION); UIA_VALIDATE_CALL_1_ARG(result); std::vector<AXPlatformNodeWin*> selected_children; @@ -1969,12 +2014,14 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_CanSelectMultiple(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTION_GET_CANSELECTMULTIPLE); UIA_VALIDATE_CALL_1_ARG(result); *result = GetData().HasState(ax::mojom::State::kMultiselectable); return S_OK; } IFACEMETHODIMP AXPlatformNodeWin::get_IsSelectionRequired(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SELECTION_GET_ISSELECTIONREQUIRED); UIA_VALIDATE_CALL_1_ARG(result); *result = GetData().HasState(ax::mojom::State::kRequired); return S_OK; @@ -1985,6 +2032,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::GetColumnHeaderItems(SAFEARRAY** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLEITEM_GETCOLUMNHEADERITEMS); UIA_VALIDATE_CALL_1_ARG(result); if (!IsCellOrTableHeader(GetData().role) || !GetTable()) @@ -1999,6 +2047,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::GetRowHeaderItems(SAFEARRAY** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLEITEM_GETROWHEADERITEMS); UIA_VALIDATE_CALL_1_ARG(result); if (!IsCellOrTableHeader(GetData().role) || !GetTable()) @@ -2017,6 +2066,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::GetColumnHeaders(SAFEARRAY** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLE_GETCOLUMNHEADERS); UIA_VALIDATE_CALL_1_ARG(result); if (!GetTable()) @@ -2028,6 +2078,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::GetRowHeaders(SAFEARRAY** result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLE_GETROWHEADERS); UIA_VALIDATE_CALL_1_ARG(result); if (!GetTable()) @@ -2040,6 +2091,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_RowOrColumnMajor( RowOrColumnMajor* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TABLE_GET_ROWORCOLUMNMAJOR); UIA_VALIDATE_CALL_1_ARG(result); // Tables and ARIA grids are always in row major order @@ -2053,6 +2105,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::Toggle() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TOGGLE_TOGGLE); UIA_VALIDATE_CALL(); AXActionData action_data; action_data.action = ax::mojom::Action::kDoDefault; @@ -2063,6 +2116,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_ToggleState(ToggleState* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TOGGLE_GET_TOGGLESTATE); UIA_VALIDATE_CALL_1_ARG(result); const auto checked_state = GetData().GetCheckedState(); if (checked_state == ax::mojom::CheckedState::kTrue) { @@ -2080,6 +2134,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::SetValue(LPCWSTR value) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_VALUE_SETVALUE); UIA_VALIDATE_CALL(); if (!value) return E_INVALIDARG; @@ -2093,6 +2148,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_IsReadOnly(BOOL* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_VALUE_GET_ISREADONLY); UIA_VALIDATE_CALL_1_ARG(result); int restriction; if (GetIntAttribute(ax::mojom::IntAttribute::kRestriction, &restriction)) { @@ -2104,6 +2160,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_Value(BSTR* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_VALUE_GET_VALUE); UIA_VALIDATE_CALL_1_ARG(result); if (GetStringAttributeAsBstr(ax::mojom::StringAttribute::kValue, result)) return S_OK; @@ -2116,38 +2173,38 @@ IFACEMETHODIMP AXPlatformNodeWin::SetVisualState( WindowVisualState window_visual_state) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_SETVISUALSTATE); UIA_VALIDATE_CALL(); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::Close() { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_CLOSE); UIA_VALIDATE_CALL(); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::WaitForInputIdle(int milliseconds, BOOL* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_WAITFORINPUTIDLE); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::get_CanMaximize(BOOL* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_CANMAXIMIZE); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::get_CanMinimize(BOOL* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_CANMINIMIZE); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::get_IsModal(BOOL* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_ISMODAL); UIA_VALIDATE_CALL_1_ARG(result); *result = GetBoolAttribute(ax::mojom::BoolAttribute::kModal); @@ -2157,20 +2214,20 @@ IFACEMETHODIMP AXPlatformNodeWin::get_WindowVisualState( WindowVisualState* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_WINDOWVISUALSTATE); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::get_WindowInteractionState( WindowInteractionState* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_WINDOWINTERACTIONSTATE); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } IFACEMETHODIMP AXPlatformNodeWin::get_IsTopmost(BOOL* result) { - DVLOG(1) << __func__; + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_WINDOW_GET_ISTOPMOST); UIA_VALIDATE_CALL_1_ARG(result); return UIA_E_NOTSUPPORTED; } @@ -2180,6 +2237,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::SetValue(double value) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_SETVALUE); UIA_VALIDATE_CALL(); AXActionData data; data.action = ax::mojom::Action::kSetValue; @@ -2190,6 +2248,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_LargeChange(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_GET_LARGECHANGE); UIA_VALIDATE_CALL_1_ARG(result); float attribute; if (GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, @@ -2201,6 +2260,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_Maximum(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_GET_MAXIMUM); UIA_VALIDATE_CALL_1_ARG(result); float attribute; if (GetFloatAttribute(ax::mojom::FloatAttribute::kMaxValueForRange, @@ -2212,6 +2272,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_Minimum(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_GET_MINIMUM); UIA_VALIDATE_CALL_1_ARG(result); float attribute; if (GetFloatAttribute(ax::mojom::FloatAttribute::kMinValueForRange, @@ -2223,6 +2284,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_SmallChange(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_GET_SMALLCHANGE); UIA_VALIDATE_CALL_1_ARG(result); float attribute; if (GetFloatAttribute(ax::mojom::FloatAttribute::kStepValueForRange, @@ -2234,6 +2296,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::get_Value(double* result) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_RANGEVALUE_GET_VALUE); UIA_VALIDATE_CALL_1_ARG(result); float attribute; if (GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, @@ -3439,6 +3502,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::GetRuntimeId(SAFEARRAY** runtime_id) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RUNTIME_ID); UIA_VALIDATE_CALL_1_ARG(runtime_id); int id_array[] = {UiaAppendRuntimeId, GetUniqueId()}; @@ -3459,6 +3523,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_BoundingRectangle( UiaRect* bounding_rectangle) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_BOUNDINGRECTANGLE); UIA_VALIDATE_CALL_1_ARG(bounding_rectangle); gfx::Rect bounds = delegate_->GetUnclippedScreenBoundsRect(); @@ -3471,6 +3536,7 @@ IFACEMETHODIMP AXPlatformNodeWin::GetEmbeddedFragmentRoots( SAFEARRAY** embedded_fragment_roots) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GETEMBEDDEDFRAGMENTROOTS); UIA_VALIDATE_CALL_1_ARG(embedded_fragment_roots); *embedded_fragment_roots = nullptr; @@ -3478,6 +3544,7 @@ } IFACEMETHODIMP AXPlatformNodeWin::SetFocus() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SETFOCUS); UIA_VALIDATE_CALL(); AXActionData action_data; @@ -3488,6 +3555,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_FragmentRoot( IRawElementProviderFragmentRoot** fragment_root) { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_FRAGMENTROOT); UIA_VALIDATE_CALL_1_ARG(fragment_root); gfx::AcceleratedWidget widget = @@ -3587,8 +3655,11 @@ case UIA_TransformPatternId: break; - // TODO(suproteem): Add checks for control role. case UIA_InvokePatternId: + if (IsInvokable(data)) { + AddRef(); + *result = static_cast<IInvokeProvider*>(this); + } break; case UIA_SelectionItemPatternId: @@ -3757,6 +3828,23 @@ &result->bstrVal); break; + case UIA_HelpTextPropertyId: + if (HasStringAttribute(ax::mojom::StringAttribute::kPlaceholder)) { + V_VT(result) = VT_BSTR; + GetStringAttributeAsBstr(ax::mojom::StringAttribute::kPlaceholder, + &V_BSTR(result)); + } else if (data.GetNameFrom() == ax::mojom::NameFrom::kPlaceholder || + data.GetNameFrom() == ax::mojom::NameFrom::kTitle) { + V_VT(result) = VT_BSTR; + GetStringAttributeAsBstr(ax::mojom::StringAttribute::kName, + &V_BSTR(result)); + } else if (HasStringAttribute(ax::mojom::StringAttribute::kTooltip)) { + V_VT(result) = VT_BSTR; + GetStringAttributeAsBstr(ax::mojom::StringAttribute::kTooltip, + &V_BSTR(result)); + } + break; + case UIA_IsContentElementPropertyId: case UIA_IsControlElementPropertyId: result->vt = VT_BOOL; @@ -3988,7 +4076,6 @@ // Covered by MSAA. case UIA_BoundingRectanglePropertyId: - case UIA_HelpTextPropertyId: case UIA_NativeWindowHandlePropertyId: case UIA_ProcessIdPropertyId: break; @@ -4043,6 +4130,7 @@ // IFACEMETHODIMP AXPlatformNodeWin::ShowContextMenu() { + WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SHOWCONTEXTMENU); UIA_VALIDATE_CALL(); ui::AXActionData action_data; @@ -6485,170 +6573,6 @@ return false; } -AXPlatformNodeWin* AXPlatformNodeWin::GetHyperlinkFromHypertextOffset( - int offset) { - std::map<int32_t, int32_t>::iterator iterator = - hypertext_.hyperlink_offset_to_index.find(offset); - if (iterator == hypertext_.hyperlink_offset_to_index.end()) - return nullptr; - - int32_t index = iterator->second; - DCHECK_GE(index, 0); - DCHECK_LT(index, static_cast<int32_t>(hypertext_.hyperlinks.size())); - int32_t id = hypertext_.hyperlinks[index]; - auto* hyperlink = - static_cast<AXPlatformNodeWin*>(AXPlatformNodeWin::GetFromUniqueId(id)); - if (!hyperlink) - return nullptr; - return hyperlink; -} - -int32_t AXPlatformNodeWin::GetHyperlinkIndexFromChild( - AXPlatformNodeWin* child) { - if (hypertext_.hyperlinks.empty()) - return -1; - - auto iterator = std::find(hypertext_.hyperlinks.begin(), - hypertext_.hyperlinks.end(), child->GetUniqueId()); - if (iterator == hypertext_.hyperlinks.end()) - return -1; - - return static_cast<int32_t>(iterator - hypertext_.hyperlinks.begin()); -} - -int32_t AXPlatformNodeWin::GetHypertextOffsetFromHyperlinkIndex( - int32_t hyperlink_index) { - for (auto& offset_index : hypertext_.hyperlink_offset_to_index) { - if (offset_index.second == hyperlink_index) - return offset_index.first; - } - return -1; -} - -int32_t AXPlatformNodeWin::GetHypertextOffsetFromChild( - AXPlatformNodeWin* child) { - // TODO(dougt) DCHECK(child.owner()->PlatformGetParent() == owner()); - - // Handle the case when we are dealing with a text-only child. - // Note that this object might be a platform leaf, e.g. an ARIA searchbox. - // Also, text-only children should not be present at tree roots and so no - // cross-tree traversal is necessary. - if (child->IsTextOnlyObject()) { - int32_t hypertext_offset = 0; - int32_t index_in_parent = child->GetDelegate()->GetIndexInParent(); - DCHECK_GE(index_in_parent, 0); - DCHECK_LT(index_in_parent, - static_cast<int32_t>(GetDelegate()->GetChildCount())); - for (uint32_t i = 0; i < static_cast<uint32_t>(index_in_parent); ++i) { - auto* sibling = static_cast<AXPlatformNodeWin*>( - FromNativeViewAccessible(GetDelegate()->ChildAtIndex(i))); - DCHECK(sibling); - if (sibling->IsTextOnlyObject()) { - hypertext_offset += (int32_t)sibling->GetText().size(); - } else { - ++hypertext_offset; - } - } - return hypertext_offset; - } - - int32_t hyperlink_index = GetHyperlinkIndexFromChild(child); - if (hyperlink_index < 0) - return -1; - - return GetHypertextOffsetFromHyperlinkIndex(hyperlink_index); -} - -int32_t AXPlatformNodeWin::GetHypertextOffsetFromDescendant( - AXPlatformNodeWin* descendant) { - auto* parent_object = static_cast<AXPlatformNodeWin*>( - FromNativeViewAccessible(descendant->GetDelegate()->GetParent())); - while (parent_object && parent_object != this) { - descendant = parent_object; - parent_object = static_cast<AXPlatformNodeWin*>( - FromNativeViewAccessible(descendant->GetParent())); - } - if (!parent_object) - return -1; - - return parent_object->GetHypertextOffsetFromChild(descendant); -} - -int AXPlatformNodeWin::GetHypertextOffsetFromEndpoint( - AXPlatformNodeWin* endpoint_object, - int endpoint_offset) { - // There are three cases: - // 1. Either the selection endpoint is inside this object or is an ancestor - // of of this object. endpoint_offset should be returned. - // 2. The selection endpoint is a pure descendant of this object. The offset - // of the character corresponding to the subtree in which the endpoint is - // located should be returned. - // 3. The selection endpoint is in a completely different part of the tree. - // Either 0 or text_length should be returned depending on the direction - // that one needs to travel to find the endpoint. - - // Case 1. - // - // IsDescendantOf includes the case when endpoint_object == this. - if (IsDescendantOf(endpoint_object)) - return endpoint_offset; - - AXPlatformNodeWin* common_parent = this; - int32_t index_in_common_parent = GetDelegate()->GetIndexInParent(); - while (common_parent && !endpoint_object->IsDescendantOf(common_parent)) { - index_in_common_parent = common_parent->GetDelegate()->GetIndexInParent(); - common_parent = static_cast<AXPlatformNodeWin*>( - FromNativeViewAccessible(common_parent->GetParent())); - } - if (!common_parent) - return -1; - - DCHECK_GE(index_in_common_parent, 0); - DCHECK(!(common_parent->IsTextOnlyObject())); - - // Case 2. - // - // We already checked in case 1 if our endpoint is inside this object. - // We can safely assume that it is a descendant or in a completely different - // part of the tree. - if (common_parent == this) { - int32_t hypertext_offset = - GetHypertextOffsetFromDescendant(endpoint_object); - auto* parent = static_cast<AXPlatformNodeWin*>( - FromNativeViewAccessible(endpoint_object->GetParent())); - if (parent == this && endpoint_object->IsTextOnlyObject()) { - hypertext_offset += endpoint_offset; - } - - return hypertext_offset; - } - - // Case 3. - // - // We can safely assume that the endpoint is in another part of the tree or - // at common parent, and that this object is a descendant of common parent. - int32_t endpoint_index_in_common_parent = -1; - for (int i = 0; i < common_parent->GetDelegate()->GetChildCount(); ++i) { - auto* child = static_cast<AXPlatformNodeWin*>( - common_parent->GetDelegate()->ChildAtIndex(i)); - DCHECK(child); - if (endpoint_object->IsDescendantOf(child)) { - endpoint_index_in_common_parent = - child->GetDelegate()->GetIndexInParent(); - break; - } - } - DCHECK_GE(endpoint_index_in_common_parent, 0); - - if (endpoint_index_in_common_parent < index_in_common_parent) - return 0; - if (endpoint_index_in_common_parent > index_in_common_parent) - return (int32_t)GetText().size(); - - NOTREACHED(); - return -1; -} - bool AXPlatformNodeWin::IsSameHypertextCharacter(size_t old_char_index, size_t new_char_index) { if (old_char_index >= old_hypertext_.hypertext.size() || @@ -6763,80 +6687,4 @@ *new_len = new_text.size() - common_prefix - common_suffix; } -int AXPlatformNodeWin::GetSelectionAnchor() { - int32_t anchor_id = GetDelegate()->GetTreeData().sel_anchor_object_id; - AXPlatformNodeWin* anchor_object = - static_cast<AXPlatformNodeWin*>(GetDelegate()->GetFromNodeID(anchor_id)); - if (!anchor_object) - return -1; - - int anchor_offset = int{GetDelegate()->GetTreeData().sel_anchor_offset}; - return GetHypertextOffsetFromEndpoint(anchor_object, anchor_offset); -} - -int AXPlatformNodeWin::GetSelectionFocus() { - int32_t focus_id = GetDelegate()->GetTreeData().sel_focus_object_id; - AXPlatformNodeWin* focus_object = - static_cast<AXPlatformNodeWin*>(GetDelegate()->GetFromNodeID(focus_id)); - if (!focus_object) - return -1; - - int focus_offset = int{GetDelegate()->GetTreeData().sel_focus_offset}; - return GetHypertextOffsetFromEndpoint(focus_object, focus_offset); -} - -void AXPlatformNodeWin::GetSelectionOffsets(int* selection_start, - int* selection_end) { - DCHECK(selection_start && selection_end); - - if (IsPlainTextField() && - GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart, - selection_start) && - GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, selection_end)) { - return; - } - - *selection_start = GetSelectionAnchor(); - *selection_end = GetSelectionFocus(); - if (*selection_start < 0 || *selection_end < 0) - return; - - // There are three cases when a selection would start and end on the same - // character: - // 1. Anchor and focus are both in a subtree that is to the right of this - // object. - // 2. Anchor and focus are both in a subtree that is to the left of this - // object. - // 3. Anchor and focus are in a subtree represented by a single embedded - // object character. - // Only case 3 refers to a valid selection because cases 1 and 2 fall - // outside this object in their entirety. - // Selections that span more than one character are by definition inside - // this object, so checking them is not necessary. - if (*selection_start == *selection_end && !HasCaret()) { - *selection_start = -1; - *selection_end = -1; - return; - } - - // The IA2 Spec says that if the largest of the two offsets falls on an - // embedded object character and if there is a selection in that embedded - // object, it should be incremented by one so that it points after the - // embedded object character. - // This is a signal to AT software that the embedded object is also part of - // the selection. - int* largest_offset = - (*selection_start <= *selection_end) ? selection_end : selection_start; - AXPlatformNodeWin* hyperlink = - GetHyperlinkFromHypertextOffset(*largest_offset); - if (!hyperlink) - return; - - LONG n_selections = 0; - HRESULT hr = hyperlink->get_nSelections(&n_selections); - DCHECK(SUCCEEDED(hr)); - if (n_selections > 0) - ++(*largest_offset); -} - } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h index 3cbae56..1c96403e 100644 --- a/ui/accessibility/platform/ax_platform_node_win.h +++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -186,6 +186,94 @@ UMA_API_TABLECELL_GET_ROW_INDEX = 155, UMA_API_UNSELECT_COLUMN = 156, UMA_API_UNSELECT_ROW = 157, + UMA_API_GET_BOUNDINGRECTANGLE = 158, + UMA_API_GET_FRAGMENTROOT = 159, + UMA_API_GETEMBEDDEDFRAGMENTROOTS = 160, + UMA_API_NAVIGATE = 161, + UMA_API_SETFOCUS = 162, + UMA_API_SHOWCONTEXTMENU = 163, + UMA_API_EXPANDCOLLAPSE_COLLAPSE = 164, + UMA_API_EXPANDCOLLAPSE_EXPAND = 165, + UMA_API_EXPANDCOLLAPSE_GET_EXPANDCOLLAPSESTATE = 166, + UMA_API_GRIDITEM_GET_COLUMN = 167, + UMA_API_GRIDITEM_GET_COLUMNSPAN = 168, + UMA_API_GRIDITEM_GET_CONTAININGGRID = 169, + UMA_API_GRIDITEM_GET_ROW = 170, + UMA_API_GRIDITEM_GET_ROWSPAN = 171, + UMA_API_GRID_GETITEM = 172, + UMA_API_GRID_GET_ROWCOUNT = 173, + UMA_API_GRID_GET_COLUMNCOUNT = 174, + UMA_API_INVOKE_INVOKE = 175, + UMA_API_RANGEVALUE_SETVALUE = 176, + UMA_API_RANGEVALUE_GET_LARGECHANGE = 177, + UMA_API_RANGEVALUE_GET_MAXIMUM = 178, + UMA_API_RANGEVALUE_GET_MINIMUM = 179, + UMA_API_RANGEVALUE_GET_SMALLCHANGE = 180, + UMA_API_RANGEVALUE_GET_VALUE = 181, + UMA_API_SCROLLITEM_SCROLLINTOVIEW = 182, + UMA_API_SCROLL_SCROLL = 183, + UMA_API_SCROLL_SETSCROLLPERCENT = 184, + UMA_API_SCROLL_GET_HORIZONTALLYSCROLLABLE = 185, + UMA_API_SCROLL_GET_HORIZONTALSCROLLPERCENT = 186, + UMA_API_SCROLL_GET_HORIZONTALVIEWSIZE = 187, + UMA_API_SCROLL_GET_VERTICALLYSCROLLABLE = 188, + UMA_API_SCROLL_GET_VERTICALSCROLLPERCENT = 189, + UMA_API_SCROLL_GET_VERTICALVIEWSIZE = 190, + UMA_API_SELECTIONITEM_ADDTOSELECTION = 191, + UMA_API_SELECTIONITEM_REMOVEFROMSELECTION = 192, + UMA_API_SELECTIONITEM_SELECT = 193, + UMA_API_SELECTIONITEM_GET_ISSELECTED = 194, + UMA_API_SELECTIONITEM_GET_SELECTIONCONTAINER = 195, + UMA_API_SELECTION_GETSELECTION = 196, + UMA_API_SELECTION_GET_CANSELECTMULTIPLE = 197, + UMA_API_SELECTION_GET_ISSELECTIONREQUIRED = 198, + UMA_API_TABLEITEM_GETCOLUMNHEADERITEMS = 199, + UMA_API_TABLEITEM_GETROWHEADERITEMS = 200, + UMA_API_TABLE_GETCOLUMNHEADERS = 201, + UMA_API_TABLE_GETROWHEADERS = 202, + UMA_API_TABLE_GET_ROWORCOLUMNMAJOR = 203, + UMA_API_TEXT_GETSELECTION = 204, + UMA_API_TEXT_GETVISIBLERANGES = 205, + UMA_API_TEXT_RANGEFROMCHILD = 206, + UMA_API_TEXT_RANGEFROMPOINT = 207, + UMA_API_TEXT_GET_DOCUMENTRANGE = 208, + UMA_API_TEXT_GET_SUPPORTEDTEXTSELECTION = 209, + UMA_API_TEXTCHILD_GET_TEXTCONTAINER = 210, + UMA_API_TEXTCHILD_GET_TEXTRANGE = 211, + UMA_API_TEXTEDIT_GETACTIVECOMPOSITION = 212, + UMA_API_TEXTEDIT_GETCONVERSIONTARGET = 213, + UMA_API_TEXTRANGE_CLONE = 214, + UMA_API_TEXTRANGE_COMPARE = 215, + UMA_API_TEXTRANGE_COMPAREENDPOINTS = 216, + UMA_API_TEXTRANGE_EXPANDTOENCLOSINGUNIT = 217, + UMA_API_TEXTRANGE_FINDATTRIBUTE = 218, + UMA_API_TEXTRANGE_FINDTEXT = 219, + UMA_API_TEXTRANGE_GETATTRIBUTEVALUE = 220, + UMA_API_TEXTRANGE_GETBOUNDINGRECTANGLES = 221, + UMA_API_TEXTRANGE_GETENCLOSINGELEMENT = 222, + UMA_API_TEXTRANGE_GETTEXT = 223, + UMA_API_TEXTRANGE_MOVE = 224, + UMA_API_TEXTRANGE_MOVEENDPOINTBYUNIT = 225, + UMA_API_TEXTRANGE_MOVEENPOINTBYRANGE = 226, + UMA_API_TEXTRANGE_SELECT = 227, + UMA_API_TEXTRANGE_ADDTOSELECTION = 228, + UMA_API_TEXTRANGE_REMOVEFROMSELECTION = 229, + UMA_API_TEXTRANGE_SCROLLINTOVIEW = 230, + UMA_API_TEXTRANGE_GETCHILDREN = 231, + UMA_API_TOGGLE_TOGGLE = 232, + UMA_API_TOGGLE_GET_TOGGLESTATE = 233, + UMA_API_VALUE_SETVALUE = 234, + UMA_API_VALUE_GET_ISREADONLY = 235, + UMA_API_VALUE_GET_VALUE = 236, + UMA_API_WINDOW_SETVISUALSTATE = 237, + UMA_API_WINDOW_CLOSE = 238, + UMA_API_WINDOW_WAITFORINPUTIDLE = 239, + UMA_API_WINDOW_GET_CANMAXIMIZE = 240, + UMA_API_WINDOW_GET_CANMINIMIZE = 241, + UMA_API_WINDOW_GET_ISMODAL = 242, + UMA_API_WINDOW_GET_WINDOWVISUALSTATE = 243, + UMA_API_WINDOW_GET_WINDOWINTERACTIONSTATE = 244, + UMA_API_WINDOW_GET_ISTOPMOST = 245, // This must always be the last enum. It's okay for its value to // increase, but none of the other enum values may change. @@ -248,6 +336,7 @@ public IExpandCollapseProvider, public IGridItemProvider, public IGridProvider, + public IInvokeProvider, public IRangeValueProvider, public IRawElementProviderFragment, public IRawElementProviderSimple2, @@ -262,6 +351,8 @@ public IValueProvider, public IWindowProvider, public AXPlatformNodeBase { + using IDispatchImpl::Invoke; + public: BEGIN_COM_MAP(AXPlatformNodeWin) // TODO(nektar): Change the following to COM_INTERFACE_ENTRY(IDispatch). @@ -283,6 +374,7 @@ COM_INTERFACE_ENTRY(IExpandCollapseProvider) COM_INTERFACE_ENTRY(IGridItemProvider) COM_INTERFACE_ENTRY(IGridProvider) + COM_INTERFACE_ENTRY(IInvokeProvider) COM_INTERFACE_ENTRY(IRangeValueProvider) COM_INTERFACE_ENTRY(IRawElementProviderFragment) COM_INTERFACE_ENTRY(IRawElementProviderSimple) @@ -501,6 +593,12 @@ IFACEMETHODIMP get_ColumnCount(int* result) override; // + // IInvokeProvider methods. + // + + IFACEMETHODIMP Invoke() override; + + // // IScrollItemProvider methods. // @@ -936,23 +1034,6 @@ // some point post conversion, we can probably move these to be private // methods. // - // - // Selection helper functions. - // The following functions retrieve the endpoints of the current selection. - // First they check for a local selection found on the current control, e.g. - // when querying the selection on a textarea. - // If not found they retrieve the global selection found on the current frame. - int GetSelectionAnchor(); - int GetSelectionFocus(); - - // Retrieves the selection offsets in the way required by the IA2 APIs. - // selection_start and selection_end are -1 when there is no selection active - // on this object. - // The greatest of the two offsets is one past the last character of the - // selection.) - void GetSelectionOffsets(int* selection_start, int* selection_end); - - // // Helper methods for IA2 hyperlinks. // // Hyperlink is an IA2 misnomer. It refers to objects embedded within other @@ -961,26 +1042,6 @@ // Returns true if the current object is an IA2 hyperlink. bool IsHyperlink(); - // Returns the hyperlink at the given text position, or nullptr if no - // hyperlink can be found. - AXPlatformNodeWin* GetHyperlinkFromHypertextOffset(int offset); - - // Functions for retrieving offsets for hyperlinks and hypertext. - // Return -1 in case of failure. - int32_t GetHyperlinkIndexFromChild(AXPlatformNodeWin* child); - int32_t GetHypertextOffsetFromHyperlinkIndex(int32_t hyperlink_index); - int32_t GetHypertextOffsetFromChild(AXPlatformNodeWin* child); - int32_t GetHypertextOffsetFromDescendant(AXPlatformNodeWin* descendant); - - // If the selection endpoint is either equal to or an ancestor of this object, - // returns endpoint_offset. - // If the selection endpoint is a descendant of this object, returns its - // offset. Otherwise, returns either 0 or the length of the hypertext - // depending on the direction of the selection. - // Returns -1 in case of unexpected failure, e.g. the selection endpoint - // cannot be found in the accessibility tree. - int GetHypertextOffsetFromEndpoint(AXPlatformNodeWin* endpoint_object, - int endpoint_offset); bool IsSameHypertextCharacter(size_t old_char_index, size_t new_char_index); void ComputeHypertextRemovedAndInserted(size_t* start, size_t* old_len,
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index 11124fe..c1319fc6 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -3577,6 +3577,80 @@ EXPECT_UIA_BSTR_EQ(referenced_element, UIA_NamePropertyId, L"Name"); } +TEST_F(AXPlatformNodeWinTest, TestGetPropertyValue_HelpText) { + AXNodeData root; + root.id = 1; + root.role = ax::mojom::Role::kNone; + + // Test Placeholder StringAttribute is exposed + AXNodeData input1; + input1.id = 2; + input1.role = ax::mojom::Role::kTextField; + input1.SetName("name-from-title"); + input1.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom, + static_cast<int>(ax::mojom::NameFrom::kTitle)); + input1.AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder, + "placeholder"); + root.child_ids.push_back(input1.id); + + // Test NameFrom Title is exposed + AXNodeData input2; + input2.id = 3; + input2.role = ax::mojom::Role::kTextField; + input2.SetName("name-from-title"); + input2.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom, + static_cast<int>(ax::mojom::NameFrom::kTitle)); + root.child_ids.push_back(input2.id); + + // Test NameFrom Placeholder is exposed + AXNodeData input3; + input3.id = 4; + input3.role = ax::mojom::Role::kTextField; + input3.SetName("name-from-placeholder"); + input3.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom, + static_cast<int>(ax::mojom::NameFrom::kPlaceholder)); + root.child_ids.push_back(input3.id); + + // Test Title StringAttribute is exposed + AXNodeData input4; + input4.id = 5; + input4.role = ax::mojom::Role::kTextField; + input4.SetName("name-from-attribute"); + input4.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom, + static_cast<int>(ax::mojom::NameFrom::kAttribute)); + input4.AddStringAttribute(ax::mojom::StringAttribute::kTooltip, "tooltip"); + root.child_ids.push_back(input4.id); + + // Test NameFrom (other), without explicit + // Title / Placeholder StringAttribute is not exposed + AXNodeData input5; + input5.id = 6; + input5.role = ax::mojom::Role::kTextField; + input5.SetName("name-from-attribute"); + input5.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom, + static_cast<int>(ax::mojom::NameFrom::kAttribute)); + root.child_ids.push_back(input5.id); + + Init(root, input1, input2, input3, input4, input5); + + auto* root_node = GetRootNode(); + EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>( + root_node->children()[0]), + UIA_HelpTextPropertyId, L"placeholder"); + EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>( + root_node->children()[1]), + UIA_HelpTextPropertyId, L"name-from-title"); + EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>( + root_node->children()[2]), + UIA_HelpTextPropertyId, L"name-from-placeholder"); + EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>( + root_node->children()[3]), + UIA_HelpTextPropertyId, L"tooltip"); + EXPECT_UIA_VALUE_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>( + root_node->children()[4]), + UIA_HelpTextPropertyId, ScopedVariant::kEmptyVariant); +} + TEST_F(AXPlatformNodeWinTest, TestUIAGetProviderOptions) { AXNodeData root_data; Init(root_data); @@ -4444,8 +4518,14 @@ checkbox.role = ax::mojom::Role::kCheckBox; root.child_ids.push_back(checkbox_id); + ui::AXNodeData link; + int32_t link_id = 8; + link.id = link_id; + link.role = ax::mojom::Role::kLink; + root.child_ids.push_back(link_id); + Init(root, text_field_with_combo_box, table, table_cell, meter, - group_with_scroll, grid, checkbox); + group_with_scroll, grid, checkbox, link); EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId, UIA_TextEditPatternId, UIA_TextPatternId}), @@ -4479,6 +4559,10 @@ EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId, UIA_TogglePatternId}), GetSupportedPatternsFromNodeId(checkbox_id)); + + EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId, + UIA_InvokePatternId}), + GetSupportedPatternsFromNodeId(link_id)); } TEST_F(AXPlatformNodeWinTest, TestGetPatternProviderExpandCollapsePattern) { @@ -4599,7 +4683,73 @@ EXPECT_NE(nullptr, expandcollapse_provider.Get()); } -TEST_F(AXPlatformNodeWinTest, TestIExpandCollapsePatternProvider_Action) { +TEST_F(AXPlatformNodeWinTest, TestGetPatternProviderInvokePattern) { + ui::AXNodeData root; + root.id = 0; + + ui::AXNodeData link; + ui::AXNodeData generic_container; + ui::AXNodeData combo_box_grouping; + ui::AXNodeData check_box; + + link.id = 1; + generic_container.id = 2; + combo_box_grouping.id = 3; + check_box.id = 4; + + root.child_ids.push_back(1); + root.child_ids.push_back(2); + root.child_ids.push_back(3); + root.child_ids.push_back(4); + + // Role link is clickable and neither supports expand collapse nor supports + // toggle. It should support invoke pattern. + link.role = ax::mojom::Role::kLink; + + // Role generic container is not clickable. It should not support invoke + // pattern. + generic_container.role = ax::mojom::Role::kGenericContainer; + + // Role combo box grouping supports expand collapse. It should not support + // invoke pattern. + combo_box_grouping.role = ax::mojom::Role::kComboBoxGrouping; + + // Role check box supports toggle. It should not support invoke pattern. + check_box.role = ax::mojom::Role::kCheckBox; + + Init(root, link, generic_container, combo_box_grouping, check_box); + + // Role link is clickable and neither supports expand collapse nor supports + // toggle. It should support invoke pattern. + ComPtr<IRawElementProviderSimple> raw_element_provider_simple = + GetIRawElementProviderSimpleFromChildIndex(0); + ComPtr<IInvokeProvider> invoke_provider; + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_NE(nullptr, invoke_provider.Get()); + + // Role generic container is not clickable. It should not support invoke + // pattern. + raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1); + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_EQ(nullptr, invoke_provider.Get()); + + // Role combo box grouping supports expand collapse. It should not support + // invoke pattern. + raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(2); + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_EQ(nullptr, invoke_provider.Get()); + + // Role check box supports toggle. It should not support invoke pattern. + raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(3); + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_EQ(nullptr, invoke_provider.Get()); +} + +TEST_F(AXPlatformNodeWinTest, TestIExpandCollapsePatternProviderAction) { ui::AXNodeData root; root.id = 0; @@ -4694,6 +4844,47 @@ EXPECT_EQ(ExpandCollapseState_LeafNode, state); } +TEST_F(AXPlatformNodeWinTest, TestIInvokeProviderInvoke) { + ui::AXNodeData root; + root.id = 0; + + ui::AXNodeData button; + ui::AXNodeData button_disabled; + + button.id = 1; + button_disabled.id = 2; + + root.child_ids.push_back(1); + root.child_ids.push_back(2); + + // generic button can be invoked. + button.role = ax::mojom::Role::kButton; + + // disabled button, cannot be invoked. + button_disabled.role = ax::mojom::Role::kButton; + button_disabled.SetRestriction(ax::mojom::Restriction::kDisabled); + + Init(root, button, button_disabled); + AXNode* button_node = GetRootNode()->children()[0]; + + // generic button can be invoked. + ComPtr<IRawElementProviderSimple> raw_element_provider_simple = + GetIRawElementProviderSimpleFromChildIndex(0); + ComPtr<IInvokeProvider> invoke_provider; + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_NE(nullptr, invoke_provider.Get()); + EXPECT_HRESULT_SUCCEEDED(invoke_provider->Invoke()); + EXPECT_EQ(button_node, TestAXNodeWrapper::GetNodeFromLastDefaultAction()); + + // disabled button, cannot be invoked. + raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1); + EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider( + UIA_InvokePatternId, &invoke_provider)); + EXPECT_NE(nullptr, invoke_provider.Get()); + EXPECT_UIA_ELEMENTNOTENABLED(invoke_provider->Invoke()); +} + TEST_F(AXPlatformNodeWinTest, TestISelectionItemProviderNotSupported) { AXNodeData root; root.id = 1;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc index a686615..f4dd499 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -33,6 +33,10 @@ // A global indicating the last node which ShowContextMenu was called from. AXNode* g_node_from_last_show_context_menu; +// A global indicating the last node which accessibility perform action +// default action was called from. +AXNode* g_node_from_last_default_action; + // A simple implementation of AXTreeObserver to catch when AXNodes are // deleted so we can delete their wrappers. class TestAXTreeObserver : public AXTreeObserver { @@ -76,6 +80,11 @@ return g_node_from_last_show_context_menu; } +// static +const AXNode* TestAXNodeWrapper::GetNodeFromLastDefaultAction() { + return g_node_from_last_default_action; +} + TestAXNodeWrapper::~TestAXNodeWrapper() { platform_node_->Destroy(); } @@ -376,6 +385,7 @@ ReplaceBoolAttribute(ax::mojom::BoolAttribute::kSelected, !current_value); } + g_node_from_last_default_action = node_; return true; case ax::mojom::Action::kSetSelection:
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h index 7eb76d0..1271d8e4 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.h +++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -35,6 +35,10 @@ // Get the last node which ShowContextMenu was called from for testing. static const AXNode* GetNodeFromLastShowContextMenu(); + // Get the last node which AccessibilityPerformAction default action was + // called from for testing. + static const AXNode* GetNodeFromLastDefaultAction(); + ~TestAXNodeWrapper() override; AXPlatformNode* ax_platform_node() const { return platform_node_; }
diff --git a/ui/android/java/res_night/values-night/colors.xml b/ui/android/java/res_night/values-night/colors.xml index 29967f1..2323756 100644 --- a/ui/android/java/res_night/values-night/colors.xml +++ b/ui/android/java/res_night/values-night/colors.xml
@@ -8,6 +8,7 @@ <color name="default_text_color">@color/default_text_color_light</color> <color name="default_text_color_inverse">@color/default_text_color_dark</color> <color name="default_text_color_secondary">@color/modern_grey_500</color> + <color name="default_text_color_blue">@color/modern_blue_300</color> <color name="default_text_color_link">@color/modern_blue_300</color> <color name="disabled_text_color">@color/white_alpha_38</color>
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java index 75b03f4..9e5732d 100644 --- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -21,8 +21,10 @@ import android.os.Process; import android.util.SparseArray; import android.util.TypedValue; +import android.view.Display; import android.view.View; import android.view.Window; +import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import org.chromium.base.ActivityState; @@ -45,8 +47,10 @@ import org.chromium.ui.widget.Toast; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; /** * The window base class that has the minimum functionality. @@ -124,6 +128,9 @@ private boolean mPendingVSyncRequest; private boolean mVSyncPaused; + // List of display modes with the same dimensions as the current mode but varying refresh rate. + private List<Display.Mode> mSupportedRefreshRateModes; + /** * An interface to notify listeners that a context menu is closed. */ @@ -240,6 +247,10 @@ mIntentErrors = new HashMap<>(); mDisplayAndroid = display; mDisplayAndroid.addObserver(this); + + // Multiple refresh rate support is only available on M+. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) recomputeSupportedRefreshRates(); + // Temporary solution for flaky tests, see https://crbug.com/767624 for context try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { mVSyncMonitor = @@ -664,7 +675,9 @@ private long getNativePointer() { if (mNativeWindowAndroid == 0) { mNativeWindowAndroid = nativeInit(mDisplayAndroid.getDisplayId(), - getMouseWheelScrollFactor(), getWindowIsWideColorGamut()); + getMouseWheelScrollFactor(), getWindowIsWideColorGamut(), getRefreshRate(), + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? getSupportedRefreshRates() + : null); nativeSetVSyncPaused(mNativeWindowAndroid, mVSyncPaused); } return mNativeWindowAndroid; @@ -861,13 +874,90 @@ if (mNativeWindowAndroid != 0) nativeOnUpdateRefreshRate(mNativeWindowAndroid, refreshRate); } - @CalledByNative + @Override + @TargetApi(Build.VERSION_CODES.M) + public void onCurrentModeChanged(Display.Mode currentMode) { + recomputeSupportedRefreshRates(); + } + + @Override + @TargetApi(Build.VERSION_CODES.M) + public void onDisplayModesChanged(List<Display.Mode> supportedModes) { + recomputeSupportedRefreshRates(); + } + + @SuppressLint("NewApi") // This should only be called if Display.Mode is available. + @TargetApi(Build.VERSION_CODES.M) + private void recomputeSupportedRefreshRates() { + Display.Mode currentMode = mDisplayAndroid.getCurrentMode(); + assert currentMode != null; + + List<Display.Mode> supportedModes = mDisplayAndroid.getSupportedModes(); + assert supportedModes != null; + assert supportedModes.size() > 0; + + List<Display.Mode> supportedRefreshRateModes = new ArrayList<Display.Mode>(); + for (int i = 0; i < supportedModes.size(); ++i) { + if (currentMode.equals(supportedModes.get(i))) { + supportedRefreshRateModes.add(supportedModes.get(i)); + continue; + } + + // Only advertise refresh rates which wouldn't change other configurations on the + // Display. + if (currentMode.getPhysicalWidth() == supportedModes.get(i).getPhysicalWidth() + && currentMode.getPhysicalHeight() == supportedModes.get(i).getPhysicalHeight() + && currentMode.getRefreshRate() != supportedModes.get(i).getRefreshRate()) { + supportedRefreshRateModes.add(supportedModes.get(i)); + continue; + } + } + + boolean changed = !supportedRefreshRateModes.equals(mSupportedRefreshRateModes); + if (changed) { + mSupportedRefreshRateModes = supportedRefreshRateModes; + if (mNativeWindowAndroid != 0) { + nativeOnSupportedRefreshRatesUpdated( + mNativeWindowAndroid, getSupportedRefreshRates()); + } + } + } + private float getRefreshRate() { return mDisplayAndroid.getRefreshRate(); } - private native long nativeInit( - int displayId, float scrollFactor, boolean windowIsWideColorGamut); + @SuppressLint("NewApi") + // mSupportedRefreshRateModes should only be set if Display.Mode is available. + @TargetApi(Build.VERSION_CODES.M) + private float[] getSupportedRefreshRates() { + if (mSupportedRefreshRateModes == null) return null; + + float[] supportedRefreshRates = new float[mSupportedRefreshRateModes.size()]; + for (int i = 0; i < mSupportedRefreshRateModes.size(); ++i) + supportedRefreshRates[i] = mSupportedRefreshRateModes.get(i).getRefreshRate(); + return supportedRefreshRates; + } + + @SuppressLint("NewApi") // This should only be called if Display.Mode is available. + @CalledByNative + private void setPreferredRefreshRate(float preferredRefreshRate) { + for (int i = 0; i < mSupportedRefreshRateModes.size(); ++i) { + if (preferredRefreshRate != mSupportedRefreshRateModes.get(i).getRefreshRate()) + continue; + + Window window = getWindow(); + WindowManager.LayoutParams params = window.getAttributes(); + params.preferredDisplayModeId = mSupportedRefreshRateModes.get(i).getModeId(); + window.setAttributes(params); + return; + } + + assert false : "Must use one of the supported refresh rates"; + } + + private native long nativeInit(int displayId, float scrollFactor, + boolean windowIsWideColorGamut, float refreshRate, float[] supportedRefreshRates); private native void nativeOnVSync(long nativeWindowAndroid, long vsyncTimeMicros, long vsyncPeriodMicros); @@ -878,4 +968,6 @@ private native void nativeOnUpdateRefreshRate(long nativeWindowAndroid, float refreshRate); private native void nativeDestroy(long nativeWindowAndroid); private native void nativeOnCursorVisibilityChanged(long nativeWindowAndroid, boolean visible); + private native void nativeOnSupportedRefreshRatesUpdated( + long nativeWindowAndroid, float[] supportedRefreshRates); }
diff --git a/ui/android/java/src/org/chromium/ui/display/DisplayAndroid.java b/ui/android/java/src/org/chromium/ui/display/DisplayAndroid.java index 9e1765b7c..da962b3 100644 --- a/ui/android/java/src/org/chromium/ui/display/DisplayAndroid.java +++ b/ui/android/java/src/org/chromium/ui/display/DisplayAndroid.java
@@ -4,11 +4,13 @@ package org.chromium.ui.display; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Point; import android.view.Display; import android.view.Surface; +import java.util.List; import java.util.WeakHashMap; /** @@ -43,6 +45,20 @@ * @param refreshRate the display's refresh rate in frames per second. */ default void onRefreshRateChanged(float refreshRate) {} + + /** + * Called whenever the attached display's supported Display.Modes are changed. + * + * @param supportedModes the array of supported modes. + */ + default void onDisplayModesChanged(List<Display.Mode> supportedModes) {} + + /** + * Called whenever the attached display's current mode is changed. + * + * @param currentMode the current display mode. + */ + default void onCurrentModeChanged(Display.Mode currentMode) {} } private static final DisplayAndroidObserver[] EMPTY_OBSERVER_ARRAY = @@ -58,6 +74,8 @@ private int mBitsPerComponent; private int mRotation; private float mRefreshRate; + private Display.Mode mCurrentDisplayMode; + private List<Display.Mode> mDisplayModes; protected boolean mIsDisplayWideColorGamut; protected boolean mIsDisplayServerWideColorGamut; @@ -192,6 +210,20 @@ return mRefreshRate; } + /* + * @return Display.Modes supported by this Display. + */ + public List<Display.Mode> getSupportedModes() { + return mDisplayModes; + } + + /* + * @return Current Display.Mode for the display. + */ + public Display.Mode getCurrentMode() { + return mCurrentDisplayMode; + } + /** * Add observer. Note repeat observers will be called only one. * Observers are held only weakly by Display. @@ -219,15 +251,17 @@ } public void updateIsDisplayServerWideColorGamut(Boolean isDisplayServerWideColorGamut) { - update(null, null, null, null, null, null, isDisplayServerWideColorGamut, null); + update(null, null, null, null, null, null, isDisplayServerWideColorGamut, null, null, null); } /** * Update the display to the provided parameters. Null values leave the parameter unchanged. */ + @SuppressLint("NewApi") protected void update(Point size, Float dipScale, Integer bitsPerPixel, Integer bitsPerComponent, Integer rotation, Boolean isDisplayWideColorGamut, - Boolean isDisplayServerWideColorGamut, Float refreshRate) { + Boolean isDisplayServerWideColorGamut, Float refreshRate, Display.Mode currentMode, + List<Display.Mode> supportedModes) { boolean sizeChanged = size != null && !mSize.equals(size); // Intentional comparison of floats: we assume that if scales differ, they differ // significantly. @@ -241,10 +275,15 @@ boolean isDisplayServerWideColorGamutChanged = isDisplayServerWideColorGamut != null && mIsDisplayServerWideColorGamut != isDisplayServerWideColorGamut; boolean isRefreshRateChanged = refreshRate != null && mRefreshRate != refreshRate; + boolean displayModesChanged = supportedModes != null + && (mDisplayModes == null ? true : mDisplayModes.equals(supportedModes)); + boolean currentModeChanged = + currentMode != null && !currentMode.equals(mCurrentDisplayMode); boolean changed = sizeChanged || dipScaleChanged || bitsPerPixelChanged || bitsPerComponentChanged || rotationChanged || isDisplayWideColorGamutChanged - || isDisplayServerWideColorGamutChanged || isRefreshRateChanged; + || isDisplayServerWideColorGamutChanged || isRefreshRateChanged + || displayModesChanged || currentModeChanged; if (!changed) return; if (sizeChanged) mSize = size; @@ -257,6 +296,8 @@ mIsDisplayServerWideColorGamut = isDisplayServerWideColorGamut; } if (isRefreshRateChanged) mRefreshRate = refreshRate; + if (displayModesChanged) mDisplayModes = supportedModes; + if (currentModeChanged) mCurrentDisplayMode = currentMode; getManager().updateDisplayOnNativeSide(this); if (rotationChanged) { @@ -277,5 +318,17 @@ o.onRefreshRateChanged(mRefreshRate); } } + if (displayModesChanged) { + DisplayAndroidObserver[] observers = getObservers(); + for (DisplayAndroidObserver o : observers) { + o.onDisplayModesChanged(mDisplayModes); + } + } + if (currentModeChanged) { + DisplayAndroidObserver[] observers = getObservers(); + for (DisplayAndroidObserver o : observers) { + o.onCurrentModeChanged(mCurrentDisplayMode); + } + } } }
diff --git a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java index 481f1e9..516e3a86 100644 --- a/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java +++ b/ui/android/java/src/org/chromium/ui/display/PhysicalDisplayAndroid.java
@@ -15,6 +15,9 @@ import org.chromium.base.Log; import org.chromium.base.compat.ApiHelperForO; +import java.util.Arrays; +import java.util.List; + /** * A DisplayAndroid implementation tied to a physical Display. */ @@ -144,8 +147,19 @@ int pixelFormatId = (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) ? display.getPixelFormat() : PixelFormat.RGBA_8888; + + Display.Mode currentMode = null; + List<Display.Mode> supportedModes = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + currentMode = display.getMode(); + supportedModes = Arrays.asList(display.getSupportedModes()); + assert currentMode != null; + assert supportedModes != null; + assert supportedModes.size() > 0; + } + super.update(size, displayMetrics.density, bitsPerPixel(pixelFormatId), bitsPerComponent(pixelFormatId), display.getRotation(), isWideColorGamut, null, - display.getRefreshRate()); + display.getRefreshRate(), currentMode, supportedModes); } }
diff --git a/ui/android/java/src/org/chromium/ui/display/VirtualDisplayAndroid.java b/ui/android/java/src/org/chromium/ui/display/VirtualDisplayAndroid.java index 4d33dfa..5719ba4 100644 --- a/ui/android/java/src/org/chromium/ui/display/VirtualDisplayAndroid.java +++ b/ui/android/java/src/org/chromium/ui/display/VirtualDisplayAndroid.java
@@ -5,6 +5,9 @@ package org.chromium.ui.display; import android.graphics.Point; +import android.view.Display; + +import java.util.List; /** * An instance of DisplayAndroid not associated with any physical display. @@ -27,16 +30,17 @@ update(new Point(other.getDisplayWidth(), other.getDisplayHeight()), other.getDipScale(), other.getBitsPerPixel(), other.getBitsPerComponent(), other.getRotation(), other.mIsDisplayWideColorGamut, other.mIsDisplayServerWideColorGamut, - other.getRefreshRate()); + other.getRefreshRate(), other.getCurrentMode(), other.getSupportedModes()); mAndroidUiScalingFactor = other.getAndroidUIScaling(); } public void update(Point size, Float dipScale, Float androidUiScalingFactor, Integer bitsPerPixel, Integer bitsPerComponent, Integer rotation, Boolean isDisplayWideColorGamut, Boolean isDisplayServerWideColorGamut, - Float refreshRate) { + Float refreshRate, Display.Mode currentMode, List<Display.Mode> supportedModes) { super.update(size, dipScale, bitsPerPixel, bitsPerComponent, rotation, - isDisplayWideColorGamut, isDisplayServerWideColorGamut, refreshRate); + isDisplayWideColorGamut, isDisplayServerWideColorGamut, refreshRate, currentMode, + supportedModes); if (androidUiScalingFactor != null) { mAndroidUiScalingFactor = androidUiScalingFactor; }
diff --git a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java index a695523..7838b0c6 100644 --- a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java +++ b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java
@@ -10,6 +10,7 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModel.ReadableBooleanPropertyKey; import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; @@ -96,6 +97,13 @@ public static final WritableBooleanPropertyKey CANCEL_ON_TOUCH_OUTSIDE = new WritableBooleanPropertyKey(); + /** + * Whether button touch events should be filtered when buttons are obscured by another visible + * window. + */ + public static final ReadableBooleanPropertyKey FILTER_TOUCH_FOR_SECURITY = + new ReadableBooleanPropertyKey(); + /** Whether the title is scrollable with the message. */ public static final WritableBooleanPropertyKey TITLE_SCROLLABLE = new WritableBooleanPropertyKey(); @@ -103,5 +111,5 @@ public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {CONTROLLER, CONTENT_DESCRIPTION, TITLE, TITLE_ICON, MESSAGE, CUSTOM_VIEW, POSITIVE_BUTTON_TEXT, POSITIVE_BUTTON_DISABLED, NEGATIVE_BUTTON_TEXT, NEGATIVE_BUTTON_DISABLED, CANCEL_ON_TOUCH_OUTSIDE, - TITLE_SCROLLABLE}; + FILTER_TOUCH_FOR_SECURITY, TITLE_SCROLLABLE}; }
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc index c5bd4f5..777965a9 100644 --- a/ui/android/window_android.cc +++ b/ui/android/window_android.cc
@@ -20,6 +20,7 @@ #include "ui/android/display_android_manager.h" #include "ui/android/window_android_compositor.h" #include "ui/android/window_android_observer.h" +#include "ui/base/ui_base_features.h" namespace ui { @@ -191,20 +192,29 @@ AttachCurrentThread(), jwindow_android)); } -WindowAndroid::WindowAndroid(JNIEnv* env, - jobject obj, - int display_id, - float scroll_factor, - bool window_is_wide_color_gamut) +WindowAndroid::WindowAndroid( + JNIEnv* env, + jobject obj, + int display_id, + float scroll_factor, + bool window_is_wide_color_gamut, + float current_refresh_rate, + const base::android::JavaParamRef<jfloatArray>& supported_refresh_rates) : display_id_(display_id), window_is_wide_color_gamut_(window_is_wide_color_gamut), compositor_(NULL), begin_frame_source_(new WindowBeginFrameSource(this)), - needs_begin_frames_(false) { + needs_begin_frames_(false), + current_refresh_rate_(current_refresh_rate) { java_window_.Reset(env, obj); mouse_wheel_scroll_factor_ = scroll_factor > 0 ? scroll_factor : kDefaultMouseWheelTickMultiplier * GetDipScale(); + + if (supported_refresh_rates) { + base::android::JavaFloatArrayToFloatVector(env, supported_refresh_rates, + &supported_refresh_rates_); + } } void WindowAndroid::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { @@ -275,8 +285,7 @@ } float WindowAndroid::GetRefreshRate() { - JNIEnv* env = AttachCurrentThread(); - return Java_WindowAndroid_getRefreshRate(env, GetJavaObject()); + return current_refresh_rate_; } void WindowAndroid::SetNeedsBeginFrames(bool needs_begin_frames) { @@ -361,8 +370,56 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, float refresh_rate) { + current_refresh_rate_ = refresh_rate; if (compositor_) compositor_->OnUpdateRefreshRate(refresh_rate); + Force60HzRefreshRateIfNeeded(); +} + +void WindowAndroid::OnSupportedRefreshRatesUpdated( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const JavaParamRef<jfloatArray>& supported_refresh_rates) { + base::android::JavaFloatArrayToFloatVector(env, supported_refresh_rates, + &supported_refresh_rates_); + Force60HzRefreshRateIfNeeded(); +} + +void WindowAndroid::SetForce60HzRefreshRate() { + if (force_60hz_refresh_rate_) + return; + + force_60hz_refresh_rate_ = true; + Force60HzRefreshRateIfNeeded(); +} + +void WindowAndroid::Force60HzRefreshRateIfNeeded() { + if (!force_60hz_refresh_rate_) + return; + + // Arbitrary error margin to account for cases where the display's refresh + // rate might not be exactly 60. + constexpr float kEpsilon = 2.f; + constexpr float k60HzRefreshRate = 60.f; + + float target_refresh_rate_delta = std::numeric_limits<float>::max(); + float target_refresh_rate = 0.f; + for (auto refresh_rate : supported_refresh_rates_) { + float refresh_rate_delta = fabs(refresh_rate - k60HzRefreshRate); + if (refresh_rate_delta < target_refresh_rate_delta) { + target_refresh_rate = refresh_rate; + target_refresh_rate_delta = refresh_rate_delta; + } + } + + if (current_refresh_rate_ == target_refresh_rate || + target_refresh_rate_delta > kEpsilon) { + return; + } + + JNIEnv* env = AttachCurrentThread(); + Java_WindowAndroid_setPreferredRefreshRate(env, GetJavaObject(), + target_refresh_rate); } bool WindowAndroid::HasPermission(const std::string& permission) { @@ -403,13 +460,17 @@ // Native JNI methods // ---------------------------------------------------------------------------- -jlong JNI_WindowAndroid_Init(JNIEnv* env, - const JavaParamRef<jobject>& obj, - jint sdk_display_id, - jfloat scroll_factor, - jboolean window_is_wide_color_gamut) { +jlong JNI_WindowAndroid_Init( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + jint sdk_display_id, + jfloat scroll_factor, + jboolean window_is_wide_color_gamut, + jfloat refresh_rate, + const base::android::JavaParamRef<jfloatArray>& supported_refresh_rates) { WindowAndroid* window = new WindowAndroid( - env, obj, sdk_display_id, scroll_factor, window_is_wide_color_gamut); + env, obj, sdk_display_id, scroll_factor, window_is_wide_color_gamut, + refresh_rate, supported_refresh_rates); return reinterpret_cast<intptr_t>(window); }
diff --git a/ui/android/window_android.h b/ui/android/window_android.h index 449604ab..5bc0a48c 100644 --- a/ui/android/window_android.h +++ b/ui/android/window_android.h
@@ -42,11 +42,14 @@ static WindowAndroid* FromJavaWindowAndroid( const base::android::JavaParamRef<jobject>& jwindow_android); - WindowAndroid(JNIEnv* env, - jobject obj, - int display_id, - float scroll_factor, - bool window_is_wide_color_gamut); + WindowAndroid( + JNIEnv* env, + jobject obj, + int display_id, + float scroll_factor, + bool window_is_wide_color_gamut, + float current_refresh_rate, + const base::android::JavaParamRef<jfloatArray>& supported_refresh_rates); ~WindowAndroid() override; @@ -95,6 +98,10 @@ void OnUpdateRefreshRate(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, float refresh_rate); + void OnSupportedRefreshRatesUpdated( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jfloatArray>& supported_refresh_rates); // Return whether the specified Android permission is granted. bool HasPermission(const std::string& permission); @@ -114,6 +121,8 @@ // See comment on WindowAndroid.getWindowIsWideColorGamut for details. display::Display GetDisplayWithWindowColorSpace(); + void SetForce60HzRefreshRate(); + private: class WindowBeginFrameSource; class ScopedOnBeginFrame; @@ -122,6 +131,7 @@ void SetNeedsBeginFrames(bool needs_begin_frames); void RequestVSyncUpdate(); + void Force60HzRefreshRateIfNeeded(); // ViewAndroid overrides. WindowAndroid* GetWindowAndroid() const override; @@ -141,6 +151,10 @@ float mouse_wheel_scroll_factor_; bool vsync_paused_ = false; + bool force_60hz_refresh_rate_ = false; + float current_refresh_rate_ = 0.f; + std::vector<float> supported_refresh_rates_; + DISALLOW_COPY_AND_ASSIGN(WindowAndroid); };
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index 19bf5ce..5b684ddd 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc
@@ -60,9 +60,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMaximumSize, nullptr) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr) -DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::vector<Window*>, - kMirrorWindowList, - nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr)
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index 93dbe871..65ba653 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h
@@ -107,11 +107,6 @@ // A property key to store the minimum size of the window. AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize; -// A property key to store a list of windows showing a mirror of the window this -// property is set on. -AURA_EXPORT extern const WindowProperty<std::vector<Window*>*>* const - kMirrorWindowList; - // The modal parent of a child modal window. AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey;
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index e4a397b..22d664d6 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -248,6 +248,8 @@ // observers of the change. virtual void SetNativeWindowOcclusionState(Window::OcclusionState state); + bool holding_pointer_moves() const { return holding_pointer_moves_; } + protected: friend class ScopedKeyboardHook; friend class TestScreen; // TODO(beng): see if we can remove/consolidate.
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn index 2dcd725d..30825ee 100644 --- a/ui/base/ime/BUILD.gn +++ b/ui/base/ime/BUILD.gn
@@ -27,10 +27,9 @@ "ime_text_span.h", "infolist_entry.cc", "infolist_entry.h", - "ui_base_ime_types_export.h", ] - defines = [ "UI_BASE_IME_TYPES_IMPLEMENTATION" ] + defines = [ "IS_UI_BASE_IME_TYPES_IMPL" ] deps = [ "//base", @@ -91,7 +90,6 @@ "text_edit_commands.h", "text_input_client.cc", "text_input_client.h", - "ui_base_ime_export.h", "win/imm32_manager.cc", "win/imm32_manager.h", "win/on_screen_keyboard_display_manager_input_pane.cc", @@ -144,7 +142,7 @@ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - defines = [ "UI_BASE_IME_IMPLEMENTATION" ] + defines = [ "IS_UI_BASE_IME_IMPL" ] deps = [ "//base",
diff --git a/ui/base/ime/candidate_window.h b/ui/base/ime/candidate_window.h index 60b8f68..82c3fac 100644 --- a/ui/base/ime/candidate_window.h +++ b/ui/base/ime/candidate_window.h
@@ -11,21 +11,21 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/infolist_entry.h" -#include "ui/base/ime/ui_base_ime_types_export.h" namespace ui { // CandidateWindow represents the structure of candidates generated from IME. -class UI_BASE_IME_TYPES_EXPORT CandidateWindow { +class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindow { public: enum Orientation { HORIZONTAL = 0, VERTICAL = 1, }; - struct UI_BASE_IME_TYPES_EXPORT CandidateWindowProperty { + struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindowProperty { CandidateWindowProperty(); virtual ~CandidateWindowProperty(); int page_size; @@ -41,7 +41,7 @@ }; // Represents a candidate entry. - struct UI_BASE_IME_TYPES_EXPORT Entry { + struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) Entry { Entry(); Entry(const Entry& other); virtual ~Entry();
diff --git a/ui/base/ime/character_composer.h b/ui/base/ime/character_composer.h index 9f7967e..57642c4 100644 --- a/ui/base/ime/character_composer.h +++ b/ui/base/ime/character_composer.h
@@ -10,9 +10,9 @@ #include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "base/strings/string_util.h" -#include "ui/base/ime/ui_base_ime_types_export.h" #include "ui/events/keycodes/dom/dom_key.h" namespace ui { @@ -20,7 +20,7 @@ // A class to recognize compose and dead key sequence. // Outputs composed character. -class UI_BASE_IME_TYPES_EXPORT CharacterComposer { +class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CharacterComposer { public: using ComposeBuffer = std::vector<DomKey>;
diff --git a/ui/base/ime/chromeos/component_extension_ime_manager.h b/ui/base/ime/chromeos/component_extension_ime_manager.h index 62240dd..6b8ea37 100644 --- a/ui/base/ime/chromeos/component_extension_ime_manager.h +++ b/ui/base/ime/chromeos/component_extension_ime_manager.h
@@ -9,18 +9,18 @@ #include <memory> #include <set> +#include "base/component_export.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/observer_list.h" #include "ui/base/ime/chromeos/input_method_descriptor.h" -#include "ui/base/ime/ui_base_ime_export.h" class Profile; namespace chromeos { // Represents an engine in component extension IME. -struct UI_BASE_IME_EXPORT ComponentExtensionEngine { +struct COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionEngine { ComponentExtensionEngine(); ComponentExtensionEngine(const ComponentExtensionEngine& other); ~ComponentExtensionEngine(); @@ -35,7 +35,7 @@ }; // Represents a component extension IME. -struct UI_BASE_IME_EXPORT ComponentExtensionIME { +struct COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIME { ComponentExtensionIME(); ComponentExtensionIME(const ComponentExtensionIME& other); ~ComponentExtensionIME(); @@ -48,7 +48,7 @@ }; // Provides an interface to list/load/unload for component extension IME. -class UI_BASE_IME_EXPORT ComponentExtensionIMEManagerDelegate { +class COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIMEManagerDelegate { public: ComponentExtensionIMEManagerDelegate(); virtual ~ComponentExtensionIMEManagerDelegate(); @@ -70,7 +70,7 @@ }; // This class manages component extension input method. -class UI_BASE_IME_EXPORT ComponentExtensionIMEManager { +class COMPONENT_EXPORT(UI_BASE_IME) ComponentExtensionIMEManager { public: ComponentExtensionIMEManager(); virtual ~ComponentExtensionIMEManager();
diff --git a/ui/base/ime/chromeos/extension_ime_util.h b/ui/base/ime/chromeos/extension_ime_util.h index 6946ecb..9266f5f1 100644 --- a/ui/base/ime/chromeos/extension_ime_util.h +++ b/ui/base/ime/chromeos/extension_ime_util.h
@@ -8,7 +8,7 @@ #include <string> #include "base/auto_reset.h" -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace chromeos { @@ -37,84 +37,89 @@ // Extension id, path (relative to |chrome::DIR_RESOURCES|) and IME engine // id for the builtin-in Braille IME extension. -UI_BASE_IME_EXPORT extern const char kBrailleImeExtensionId[]; -UI_BASE_IME_EXPORT extern const char kBrailleImeExtensionPath[]; -UI_BASE_IME_EXPORT extern const char kBrailleImeEngineId[]; +COMPONENT_EXPORT(UI_BASE_IME) extern const char kBrailleImeExtensionId[]; +COMPONENT_EXPORT(UI_BASE_IME) +extern const char kBrailleImeExtensionPath[]; +COMPONENT_EXPORT(UI_BASE_IME) extern const char kBrailleImeEngineId[]; // The fake language name used for ARC IMEs. -UI_BASE_IME_EXPORT extern const char kArcImeLanguage[]; +COMPONENT_EXPORT(UI_BASE_IME) extern const char kArcImeLanguage[]; // Returns InputMethodID for |engine_id| in |extension_id| of extension IME. // This function does not check |extension_id| is installed extension IME nor // |engine_id| is really a member of |extension_id|. -std::string UI_BASE_IME_EXPORT -GetInputMethodID(const std::string& extension_id, const std::string& engine_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetInputMethodID(const std::string& extension_id, + const std::string& engine_id); // Returns InputMethodID for |engine_id| in |extension_id| of component // extension IME, This function does not check |extension_id| is component one // nor |engine_id| is really a member of |extension_id|. -std::string UI_BASE_IME_EXPORT -GetComponentInputMethodID(const std::string& extension_id, - const std::string& engine_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetComponentInputMethodID(const std::string& extension_id, + const std::string& engine_id); // Returns InputMethodID for |engine_id| in |extension_id| of ARC IME. // This function does not check |extension_id| is one for ARC IME nor // |engine_id| is really an installed ARC IME. -std::string UI_BASE_IME_EXPORT -GetArcInputMethodID(const std::string& extension_id, - const std::string& engine_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetArcInputMethodID(const std::string& extension_id, + const std::string& engine_id); // Returns extension ID if |input_method_id| is extension IME ID or component // extension IME ID. Otherwise returns an empty string (""). -std::string UI_BASE_IME_EXPORT -GetExtensionIDFromInputMethodID(const std::string& input_method_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetExtensionIDFromInputMethodID(const std::string& input_method_id); // Returns InputMethodID from engine id (e.g. xkb:fr:fra), or returns itself if // the |engine_id| is not a known engine id. // The caller must make sure the |engine_id| is from system input methods // instead of 3rd party input methods. -std::string UI_BASE_IME_EXPORT -GetInputMethodIDByEngineID(const std::string& engine_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetInputMethodIDByEngineID(const std::string& engine_id); // Returns true if |input_method_id| is extension IME ID. This function does not // check |input_method_id| is installed extension IME. -bool UI_BASE_IME_EXPORT IsExtensionIME(const std::string& input_method_id); +bool COMPONENT_EXPORT(UI_BASE_IME) + IsExtensionIME(const std::string& input_method_id); // Returns true if |input_method_id| is component extension IME ID. This // function does not check |input_method_id| is really whitelisted one or not. // If you want to check |input_method_id| is whitelisted component extension // IME, please use ComponentExtensionIMEManager::IsWhitelisted instead. -bool UI_BASE_IME_EXPORT -IsComponentExtensionIME(const std::string& input_method_id); +bool COMPONENT_EXPORT(UI_BASE_IME) + IsComponentExtensionIME(const std::string& input_method_id); // Returns true if |input_method_id| is a Arc IME ID. This function does not // check |input_method_id| is really a installed Arc IME. -bool UI_BASE_IME_EXPORT IsArcIME(const std::string& input_method_id); +bool COMPONENT_EXPORT(UI_BASE_IME) IsArcIME(const std::string& input_method_id); // Returns true if the |input_method| is a member of |extension_id| of extension // IME, otherwise returns false. -bool UI_BASE_IME_EXPORT IsMemberOfExtension(const std::string& input_method_id, - const std::string& extension_id); +bool COMPONENT_EXPORT(UI_BASE_IME) + IsMemberOfExtension(const std::string& input_method_id, + const std::string& extension_id); // Returns true if the |input_method_id| is the extension based xkb keyboard, // otherwise returns false. -bool UI_BASE_IME_EXPORT -IsKeyboardLayoutExtension(const std::string& input_method_id); +bool COMPONENT_EXPORT(UI_BASE_IME) + IsKeyboardLayoutExtension(const std::string& input_method_id); // Returns true if |language| is the fake one for ARC IMEs. -bool UI_BASE_IME_EXPORT IsLanguageForArcIME(const std::string& language); +bool COMPONENT_EXPORT(UI_BASE_IME) + IsLanguageForArcIME(const std::string& language); // Returns input method component id from the extension-based InputMethodID // for component IME extensions. This function does not check that // |input_method_id| is installed. -std::string UI_BASE_IME_EXPORT -GetComponentIDByInputMethodID(const std::string& input_method_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + GetComponentIDByInputMethodID(const std::string& input_method_id); // Gets legacy xkb id (e.g. xkb:us::eng) from the new extension based xkb id // (e.g. _comp_ime_...xkb:us::eng). If the given id is not prefixed with // 'xkb:', just return the same as the given id. -std::string UI_BASE_IME_EXPORT -MaybeGetLegacyXkbId(const std::string& input_method_id); +std::string COMPONENT_EXPORT(UI_BASE_IME) + MaybeGetLegacyXkbId(const std::string& input_method_id); } // namespace extension_ime_util
diff --git a/ui/base/ime/chromeos/fake_ime_keyboard.h b/ui/base/ime/chromeos/fake_ime_keyboard.h index b11163d..37892d72 100644 --- a/ui/base/ime/chromeos/fake_ime_keyboard.h +++ b/ui/base/ime/chromeos/fake_ime_keyboard.h
@@ -10,12 +10,13 @@ #include <string> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" namespace chromeos { namespace input_method { -class UI_BASE_IME_EXPORT FakeImeKeyboard : public ImeKeyboard { +class COMPONENT_EXPORT(UI_BASE_IME) FakeImeKeyboard : public ImeKeyboard { public: FakeImeKeyboard(); ~FakeImeKeyboard() override;
diff --git a/ui/base/ime/chromeos/fake_input_method_delegate.h b/ui/base/ime/chromeos/fake_input_method_delegate.h index 9dceb0e..de045d3 100644 --- a/ui/base/ime/chromeos/fake_input_method_delegate.h +++ b/ui/base/ime/chromeos/fake_input_method_delegate.h
@@ -9,14 +9,15 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/chromeos/input_method_delegate.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace chromeos { namespace input_method { -class UI_BASE_IME_EXPORT FakeInputMethodDelegate : public InputMethodDelegate { +class COMPONENT_EXPORT(UI_BASE_IME) FakeInputMethodDelegate + : public InputMethodDelegate { public: typedef base::RepeatingCallback<base::string16( const std::string& language_code)>
diff --git a/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h b/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h index c28bf16..0c1989f 100644 --- a/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h +++ b/ui/base/ime/chromeos/ime_candidate_window_handler_interface.h
@@ -7,8 +7,8 @@ #include <stdint.h> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace gfx { class Rect; @@ -21,7 +21,7 @@ namespace chromeos { // A interface to handle the candidate window related method call. -class UI_BASE_IME_EXPORT IMECandidateWindowHandlerInterface { +class COMPONENT_EXPORT(UI_BASE_IME) IMECandidateWindowHandlerInterface { public: virtual ~IMECandidateWindowHandlerInterface() {}
diff --git a/ui/base/ime/chromeos/ime_keyboard.h b/ui/base/ime/chromeos/ime_keyboard.h index af8125a7..421412d8 100644 --- a/ui/base/ime/chromeos/ime_keyboard.h +++ b/ui/base/ime/chromeos/ime_keyboard.h
@@ -8,8 +8,8 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/observer_list.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace chromeos { namespace input_method { @@ -20,7 +20,7 @@ unsigned int repeat_interval_in_ms; }; -class UI_BASE_IME_EXPORT ImeKeyboard { +class COMPONENT_EXPORT(UI_BASE_IME) ImeKeyboard { public: class Observer { public: @@ -93,11 +93,11 @@ // On success, set current auto repeat rate on |out_rate| and returns true. // Returns false otherwise. This function is protected: for testability. - static UI_BASE_IME_EXPORT bool GetAutoRepeatRateForTesting( + static COMPONENT_EXPORT(UI_BASE_IME) bool GetAutoRepeatRateForTesting( AutoRepeatRate* out_rate); // Returns false if |layout_name| contains a bad character. - static UI_BASE_IME_EXPORT bool CheckLayoutNameForTesting( + static COMPONENT_EXPORT(UI_BASE_IME) bool CheckLayoutNameForTesting( const std::string& layout_name); bool caps_lock_is_enabled_;
diff --git a/ui/base/ime/chromeos/ime_keyboard_mus.h b/ui/base/ime/chromeos/ime_keyboard_mus.h index d6f5edc..8f96c9b 100644 --- a/ui/base/ime/chromeos/ime_keyboard_mus.h +++ b/ui/base/ime/chromeos/ime_keyboard_mus.h
@@ -5,9 +5,9 @@ #ifndef UI_BASE_IME_CHROMEOS_IME_KEYBOARD_MUS_H_ #define UI_BASE_IME_CHROMEOS_IME_KEYBOARD_MUS_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/chromeos/ime_keyboard.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ws { class InputDeviceControllerClient; @@ -16,7 +16,7 @@ namespace chromeos { namespace input_method { -class UI_BASE_IME_EXPORT ImeKeyboardMus : public ImeKeyboard { +class COMPONENT_EXPORT(UI_BASE_IME) ImeKeyboardMus : public ImeKeyboard { public: explicit ImeKeyboardMus( ws::InputDeviceControllerClient* input_device_controller_client);
diff --git a/ui/base/ime/chromeos/ime_keymap.h b/ui/base/ime/chromeos/ime_keymap.h index 2f8d012d..4b09d00 100644 --- a/ui/base/ime/chromeos/ime_keymap.h +++ b/ui/base/ime/chromeos/ime_keymap.h
@@ -6,17 +6,18 @@ #define UI_BASE_IME_CHROMEOS_IME_KEYMAP_H_ #include <string> -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" #include "ui/events/keycodes/keyboard_codes.h" namespace ui { // Translates the DOM4 key code string to ui::KeyboardCode. -UI_BASE_IME_EXPORT KeyboardCode -DomKeycodeToKeyboardCode(const std::string& code); +COMPONENT_EXPORT(UI_BASE_IME) +KeyboardCode DomKeycodeToKeyboardCode(const std::string& code); // Translates the ui::KeyboardCode to DOM4 key code string. -UI_BASE_IME_EXPORT std::string KeyboardCodeToDomKeycode(KeyboardCode code); +COMPONENT_EXPORT(UI_BASE_IME) +std::string KeyboardCodeToDomKeycode(KeyboardCode code); } // namespace ui
diff --git a/ui/base/ime/chromeos/input_method_descriptor.h b/ui/base/ime/chromeos/input_method_descriptor.h index 3a7590c..09c76136 100644 --- a/ui/base/ime/chromeos/input_method_descriptor.h +++ b/ui/base/ime/chromeos/input_method_descriptor.h
@@ -8,14 +8,14 @@ #include <string> #include <vector> -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" #include "url/gurl.h" namespace chromeos { namespace input_method { // A structure which represents an input method. -class UI_BASE_IME_EXPORT InputMethodDescriptor { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodDescriptor { public: InputMethodDescriptor(); InputMethodDescriptor(const std::string& id,
diff --git a/ui/base/ime/chromeos/input_method_manager.h b/ui/base/ime/chromeos/input_method_manager.h index 2cb04e5..0f83c5b8 100644 --- a/ui/base/ime/chromeos/input_method_manager.h +++ b/ui/base/ime/chromeos/input_method_manager.h
@@ -12,10 +12,10 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/memory/ref_counted.h" #include "ui/base/ime/chromeos/input_method_descriptor.h" #include "ui/base/ime/chromeos/public/interfaces/ime_keyset.mojom.h" -#include "ui/base/ime/ui_base_ime_export.h" class Profile; @@ -33,7 +33,7 @@ // This class manages input methodshandles. Classes can add themselves as // observers. Clients can get an instance of this library class by: // InputMethodManager::Get(). -class UI_BASE_IME_EXPORT InputMethodManager { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodManager { public: enum UISessionState { STATE_LOGIN_SCREEN = 0, @@ -259,16 +259,17 @@ // Gets the global instance of InputMethodManager. Initialize() must be called // first. - static UI_BASE_IME_EXPORT InputMethodManager* Get(); + static COMPONENT_EXPORT(UI_BASE_IME) InputMethodManager* Get(); // Sets the global instance. |instance| will be owned by the internal pointer // and deleted by Shutdown(). // TODO(nona): Instanciate InputMethodManagerImpl inside of this function once // crbug.com/164375 is fixed. - static UI_BASE_IME_EXPORT void Initialize(InputMethodManager* instance); + static COMPONENT_EXPORT(UI_BASE_IME) void Initialize( + InputMethodManager* instance); // Destroy the global instance. - static UI_BASE_IME_EXPORT void Shutdown(); + static COMPONENT_EXPORT(UI_BASE_IME) void Shutdown(); // Get the current UI session state (e.g. login screen, lock screen, etc.). virtual UISessionState GetUISessionState() = 0;
diff --git a/ui/base/ime/chromeos/input_method_util.h b/ui/base/ime/chromeos/input_method_util.h index 36565a7..f47f64b 100644 --- a/ui/base/ime/chromeos/input_method_util.h +++ b/ui/base/ime/chromeos/input_method_util.h
@@ -11,12 +11,12 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/strings/string16.h" #include "base/threading/thread_checker.h" #include "ui/base/ime/chromeos/input_method_descriptor.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace chromeos { namespace input_method { @@ -29,7 +29,7 @@ }; // A class which provides miscellaneous input method utility functions. -class UI_BASE_IME_EXPORT InputMethodUtil { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodUtil { public: explicit InputMethodUtil(InputMethodDelegate* delegate); ~InputMethodUtil();
diff --git a/ui/base/ime/chromeos/input_method_whitelist.h b/ui/base/ime/chromeos/input_method_whitelist.h index c42fd5a..217dc937 100644 --- a/ui/base/ime/chromeos/input_method_whitelist.h +++ b/ui/base/ime/chromeos/input_method_whitelist.h
@@ -10,8 +10,8 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace chromeos { namespace input_method { @@ -21,7 +21,7 @@ // A class which has white listed input method list. The list is generated by // gen_input_methods.py from input_methods.txt. -class UI_BASE_IME_EXPORT InputMethodWhitelist { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWhitelist { public: InputMethodWhitelist(); ~InputMethodWhitelist();
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager.h b/ui/base/ime/chromeos/mock_component_extension_ime_manager.h index 829f562..bb1483c 100644 --- a/ui/base/ime/chromeos/mock_component_extension_ime_manager.h +++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager.h
@@ -5,11 +5,12 @@ #ifndef UI_BASE_IME_MOCK_CHROMEOS_COMPONENT_EXTENSION_IME_MANAGER_H_ #define UI_BASE_IME_MOCK_CHROMEOS_COMPONENT_EXTENSION_IME_MANAGER_H_ +#include "base/component_export.h" #include "ui/base/ime/chromeos/component_extension_ime_manager.h" namespace chromeos { -class UI_BASE_IME_EXPORT MockComponentExtensionIMEManager +class COMPONENT_EXPORT(UI_BASE_IME) MockComponentExtensionIMEManager : public ComponentExtensionIMEManager { public: input_method::InputMethodDescriptors GetXkbIMEAsInputMethodDescriptor()
diff --git a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h index a237d8b..e7c8650 100644 --- a/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h +++ b/ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h
@@ -5,14 +5,14 @@ #ifndef UI_BASE_IME_CHROMEOS_MOCK_COMPONENT_EXTENSION_IME_MANAGER_DELEGATE_H_ #define UI_BASE_IME_CHROMEOS_MOCK_COMPONENT_EXTENSION_IME_MANAGER_DELEGATE_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/chromeos/component_extension_ime_manager.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace chromeos { namespace input_method { -class UI_BASE_IME_EXPORT MockComponentExtIMEManagerDelegate +class COMPONENT_EXPORT(UI_BASE_IME) MockComponentExtIMEManagerDelegate : public ComponentExtensionIMEManagerDelegate { public: MockComponentExtIMEManagerDelegate();
diff --git a/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h b/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h index d9ab2aa..029e393 100644 --- a/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h +++ b/ui/base/ime/chromeos/mock_ime_candidate_window_handler.h
@@ -7,14 +7,14 @@ #include <stdint.h> +#include "base/component_export.h" #include "ui/base/ime/candidate_window.h" #include "ui/base/ime/chromeos/ime_candidate_window_handler_interface.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/geometry/rect.h" namespace chromeos { -class UI_BASE_IME_EXPORT MockIMECandidateWindowHandler +class COMPONENT_EXPORT(UI_BASE_IME) MockIMECandidateWindowHandler : public IMECandidateWindowHandlerInterface { public: struct UpdateLookupTableArg {
diff --git a/ui/base/ime/chromeos/mock_ime_engine_handler.h b/ui/base/ime/chromeos/mock_ime_engine_handler.h index 1394e63e..5668f5b 100644 --- a/ui/base/ime/chromeos/mock_ime_engine_handler.h +++ b/ui/base/ime/chromeos/mock_ime_engine_handler.h
@@ -9,13 +9,13 @@ #include <stdint.h> #include <vector> +#include "base/component_export.h" #include "ui/base/ime/ime_engine_handler_interface.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/event.h" namespace chromeos { -class UI_BASE_IME_EXPORT MockIMEEngineHandler +class COMPONENT_EXPORT(UI_BASE_IME) MockIMEEngineHandler : public ui::IMEEngineHandlerInterface { public: MockIMEEngineHandler();
diff --git a/ui/base/ime/chromeos/mock_input_method_manager.h b/ui/base/ime/chromeos/mock_input_method_manager.h index fb6c4131..2461ea1a 100644 --- a/ui/base/ime/chromeos/mock_input_method_manager.h +++ b/ui/base/ime/chromeos/mock_input_method_manager.h
@@ -5,6 +5,7 @@ #ifndef UI_BASE_IME_CHROMEOS_MOCK_INPUT_METHOD_MANAGER_H_ #define UI_BASE_IME_CHROMEOS_MOCK_INPUT_METHOD_MANAGER_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/input_method_keyboard_controller.h" @@ -15,7 +16,7 @@ class ImeKeyboard; // The mock InputMethodManager for testing. -class UI_BASE_IME_EXPORT MockInputMethodManager +class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethodManager : public InputMethodManager, public ui::InputMethodKeyboardController { public:
diff --git a/ui/base/ime/composition_text.h b/ui/base/ime/composition_text.h index 6d05f15..cddf445e 100644 --- a/ui/base/ime/composition_text.h +++ b/ui/base/ime/composition_text.h
@@ -7,15 +7,15 @@ #include <stddef.h> +#include "base/component_export.h" #include "base/strings/string16.h" #include "ui/base/ime/ime_text_span.h" -#include "ui/base/ime/ui_base_ime_types_export.h" #include "ui/gfx/range/range.h" namespace ui { // A struct represents the status of an ongoing composition text. -struct UI_BASE_IME_TYPES_EXPORT CompositionText { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CompositionText { CompositionText(); CompositionText(const CompositionText& other); ~CompositionText();
diff --git a/ui/base/ime/composition_text_util_pango.h b/ui/base/ime/composition_text_util_pango.h index ae53ebb..062f31e 100644 --- a/ui/base/ime/composition_text_util_pango.h +++ b/ui/base/ime/composition_text_util_pango.h
@@ -5,8 +5,8 @@ #ifndef UI_BASE_IME_COMPOSITION_TEXT_UTIL_PANGO_H_ #define UI_BASE_IME_COMPOSITION_TEXT_UTIL_PANGO_H_ +#include "base/component_export.h" #include "ui/base/glib/glib_integers.h" -#include "ui/base/ime/ui_base_ime_export.h" typedef struct _PangoAttrList PangoAttrList; @@ -16,11 +16,11 @@ // Extracts composition text information (text, underlines, selection range) // from given Gtk preedit data (utf-8 text, pango attributes, cursor position). -UI_BASE_IME_EXPORT void ExtractCompositionTextFromGtkPreedit( - const gchar* utf8_text, - PangoAttrList* attrs, - int cursor_position, - CompositionText* composition); +COMPONENT_EXPORT(UI_BASE_IME) +void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text, + PangoAttrList* attrs, + int cursor_position, + CompositionText* composition); } // namespace ui
diff --git a/ui/base/ime/constants.h b/ui/base/ime/constants.h index f5e812a..3224e34e 100644 --- a/ui/base/ime/constants.h +++ b/ui/base/ime/constants.h
@@ -5,7 +5,7 @@ #ifndef UI_BASE_IME_CONSTANTS_H_ #define UI_BASE_IME_CONSTANTS_H_ -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { @@ -14,7 +14,7 @@ // This is used where the key event is simulated by the virtual keyboard // (e.g. IME extension API) as well as the input field implementation (e.g. // Textfield). -UI_BASE_IME_EXPORT extern const char kPropertyFromVK[]; +COMPONENT_EXPORT(UI_BASE_IME) extern const char kPropertyFromVK[]; } // namespace ui
diff --git a/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h b/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h index e3d074d..32cf15e 100644 --- a/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h +++ b/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h
@@ -7,14 +7,14 @@ #include <fuchsia/ui/input/cpp/fidl.h> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { // Manages visibility of the onscreen keyboard. -class UI_BASE_IME_EXPORT InputMethodKeyboardControllerFuchsia +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodKeyboardControllerFuchsia : public InputMethodKeyboardController { public: // |ime_service| must outlive |this|.
diff --git a/ui/base/ime/ime_bridge.h b/ui/base/ime/ime_bridge.h index 0a807f6870..7c77a43f 100644 --- a/ui/base/ime/ime_bridge.h +++ b/ui/base/ime/ime_bridge.h
@@ -5,12 +5,12 @@ #ifndef UI_BASE_IME_IME_BRIDGE_H_ #define UI_BASE_IME_IME_BRIDGE_H_ +#include "base/component_export.h" #include "base/macros.h" #include "build/build_config.h" #include "ui/base/ime/ime_bridge_observer.h" #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/ime_input_context_handler_interface.h" -#include "ui/base/ime/ui_base_ime_export.h" #if defined(OS_CHROMEOS) #include "ui/base/ime/chromeos/ime_candidate_window_handler_interface.h" @@ -24,7 +24,7 @@ // IMEBridge provides access of each IME related handler. This class // is used for IME implementation. -class UI_BASE_IME_EXPORT IMEBridge { +class COMPONENT_EXPORT(UI_BASE_IME) IMEBridge { public: virtual ~IMEBridge();
diff --git a/ui/base/ime/ime_bridge_observer.h b/ui/base/ime/ime_bridge_observer.h index 74dd8e9..3e8813c 100644 --- a/ui/base/ime/ime_bridge_observer.h +++ b/ui/base/ime/ime_bridge_observer.h
@@ -5,13 +5,14 @@ #ifndef UI_BASE_IME_IME_BRIDGE_OBSERVER_H_ #define UI_BASE_IME_IME_BRIDGE_OBSERVER_H_ +#include "base/component_export.h" #include "base/observer_list_types.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { // A interface to observe changes in the IMEBridge. -class UI_BASE_IME_EXPORT IMEBridgeObserver : public base::CheckedObserver { +class COMPONENT_EXPORT(UI_BASE_IME) IMEBridgeObserver + : public base::CheckedObserver { public: // Called when requesting to switch the engine handler from ui::InputMethod. virtual void OnRequestSwitchEngine() = 0;
diff --git a/ui/base/ime/ime_engine_handler_interface.h b/ui/base/ime/ime_engine_handler_interface.h index 481bc66..37d015c 100644 --- a/ui/base/ime/ime_engine_handler_interface.h +++ b/ui/base/ime/ime_engine_handler_interface.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/callback.h" +#include "base/component_export.h" #include "build/build_config.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/text_input_mode.h" @@ -26,7 +27,7 @@ class KeyEvent; // A interface to handle the engine handler method call. -class UI_BASE_IME_EXPORT IMEEngineHandlerInterface { +class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { public: typedef base::OnceCallback<void(bool consumed)> KeyEventDoneCallback;
diff --git a/ui/base/ime/ime_input_context_handler_interface.h b/ui/base/ime/ime_input_context_handler_interface.h index 14029ff..21c0f45c5 100644 --- a/ui/base/ime/ime_input_context_handler_interface.h +++ b/ui/base/ime/ime_input_context_handler_interface.h
@@ -8,9 +8,9 @@ #include <stdint.h> #include <string> +#include "base/component_export.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/input_method.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/event.h" namespace ui { @@ -20,7 +20,7 @@ gfx::Range selection_range; }; -class UI_BASE_IME_EXPORT IMEInputContextHandlerInterface { +class COMPONENT_EXPORT(UI_BASE_IME) IMEInputContextHandlerInterface { public: // Called when the engine commit a text. virtual void CommitText(const std::string& text) = 0;
diff --git a/ui/base/ime/ime_text_span.h b/ui/base/ime/ime_text_span.h index ba45d09..4e449567 100644 --- a/ui/base/ime/ime_text_span.h +++ b/ui/base/ime/ime_text_span.h
@@ -10,15 +10,15 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ime/ui_base_ime_types_export.h" namespace ui { // Intentionally keep sync with blink::WebImeTextSpan defined in: // third_party/WebKit/public/web/WebImeTextSpan.h -struct UI_BASE_IME_TYPES_EXPORT ImeTextSpan { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { enum class Type { // Creates a composition marker. kComposition,
diff --git a/ui/base/ime/infolist_entry.h b/ui/base/ime/infolist_entry.h index 1e16e5e9..54d6320 100644 --- a/ui/base/ime/infolist_entry.h +++ b/ui/base/ime/infolist_entry.h
@@ -5,13 +5,13 @@ #ifndef UI_BASE_IME_INFOLIST_ENTRY_H_ #define UI_BASE_IME_INFOLIST_ENTRY_H_ +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ime/ui_base_ime_types_export.h" namespace ui { // The data model of infolist window. -struct UI_BASE_IME_TYPES_EXPORT InfolistEntry { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) InfolistEntry { base::string16 title; base::string16 body; bool highlighted;
diff --git a/ui/base/ime/input_method_auralinux.h b/ui/base/ime/input_method_auralinux.h index 8963ab9..199d561a 100644 --- a/ui/base/ime/input_method_auralinux.h +++ b/ui/base/ime/input_method_auralinux.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/input_method_base.h" @@ -17,7 +18,7 @@ // A ui::InputMethod implementation for Aura on Linux platforms. The // implementation details are separated to ui::LinuxInputMethodContext // interface. -class UI_BASE_IME_EXPORT InputMethodAuraLinux +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodAuraLinux : public InputMethodBase, public LinuxInputMethodContextDelegate { public:
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index 2643c7f4..368fa8f 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h
@@ -9,13 +9,13 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "build/build_config.h" #include "ui/base/ime/ime_input_context_handler_interface.h" #include "ui/base/ime/input_method.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/event_dispatcher.h" namespace gfx { @@ -31,7 +31,7 @@ // A helper class providing functionalities shared among ui::InputMethod // implementations. -class UI_BASE_IME_EXPORT InputMethodBase +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase : public InputMethod, public base::SupportsWeakPtr<InputMethodBase>, public IMEInputContextHandlerInterface {
diff --git a/ui/base/ime/input_method_chromeos.h b/ui/base/ime/input_method_chromeos.h index 300dd23..eef6635f 100644 --- a/ui/base/ime/input_method_chromeos.h +++ b/ui/base/ime/input_method_chromeos.h
@@ -13,6 +13,7 @@ #include "base/callback_forward.h" #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "ui/base/ime/character_composer.h" @@ -24,7 +25,8 @@ namespace ui { // A ui::InputMethod implementation based on IBus. -class UI_BASE_IME_EXPORT InputMethodChromeOS : public InputMethodBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodChromeOS + : public InputMethodBase { public: explicit InputMethodChromeOS(internal::InputMethodDelegate* delegate); ~InputMethodChromeOS() override;
diff --git a/ui/base/ime/input_method_delegate.h b/ui/base/ime/input_method_delegate.h index 70a1460..a0bcccd2 100644 --- a/ui/base/ime/input_method_delegate.h +++ b/ui/base/ime/input_method_delegate.h
@@ -6,7 +6,7 @@ #define UI_BASE_IME_INPUT_METHOD_DELEGATE_H_ #include "base/callback_forward.h" -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { @@ -18,7 +18,7 @@ // An interface implemented by the object that handles events sent back from an // ui::InputMethod implementation. -class UI_BASE_IME_EXPORT InputMethodDelegate { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodDelegate { public: virtual ~InputMethodDelegate() {}
diff --git a/ui/base/ime/input_method_factory.h b/ui/base/ime/input_method_factory.h index 22a19c2..0f94731 100644 --- a/ui/base/ime/input_method_factory.h +++ b/ui/base/ime/input_method_factory.h
@@ -8,8 +8,8 @@ #include <memory> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "ui/base/ime/input_method_initializer.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/native_widget_types.h" namespace ui { @@ -20,13 +20,15 @@ class InputMethod; // Creates a new instance of InputMethod and returns it. -UI_BASE_IME_EXPORT std::unique_ptr<InputMethod> CreateInputMethod( +COMPONENT_EXPORT(UI_BASE_IME) +std::unique_ptr<InputMethod> CreateInputMethod( internal::InputMethodDelegate* delegate, gfx::AcceleratedWidget widget); // Makes CreateInputMethod return a MockInputMethod. -UI_BASE_IME_EXPORT void SetUpInputMethodFactoryForTesting(); -UI_BASE_IME_EXPORT void SetUpInputMethodForTesting(InputMethod* input_method); +COMPONENT_EXPORT(UI_BASE_IME) void SetUpInputMethodFactoryForTesting(); +COMPONENT_EXPORT(UI_BASE_IME) +void SetUpInputMethodForTesting(InputMethod* input_method); } // namespace ui;
diff --git a/ui/base/ime/input_method_fuchsia.h b/ui/base/ime/input_method_fuchsia.h index 3137db5..8e5c099 100644 --- a/ui/base/ime/input_method_fuchsia.h +++ b/ui/base/ime/input_method_fuchsia.h
@@ -9,11 +9,11 @@ #include <lib/fidl/cpp/binding.h> #include <memory> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h" #include "ui/base/ime/input_method_base.h" #include "ui/base/ime/input_method_delegate.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/fuchsia/input_event_dispatcher.h" #include "ui/events/fuchsia/input_event_dispatcher_delegate.h" #include "ui/gfx/native_widget_types.h" @@ -21,7 +21,7 @@ namespace ui { // Handles input from physical keyboards and the IME service. -class UI_BASE_IME_EXPORT InputMethodFuchsia +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodFuchsia : public InputMethodBase, public InputEventDispatcherDelegate, public fuchsia::ui::input::InputMethodEditorClient {
diff --git a/ui/base/ime/input_method_initializer.h b/ui/base/ime/input_method_initializer.h index 588d7f1..2105a88 100644 --- a/ui/base/ime/input_method_initializer.h +++ b/ui/base/ime/input_method_initializer.h
@@ -5,25 +5,25 @@ #ifndef UI_BASE_IME_INPUT_METHOD_INITIALIZER_H_ #define UI_BASE_IME_INPUT_METHOD_INITIALIZER_H_ -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { // Initializes thread-local resources for input method. This function should be // called in the UI thread before input method is used. -UI_BASE_IME_EXPORT void InitializeInputMethod(); +COMPONENT_EXPORT(UI_BASE_IME) void InitializeInputMethod(); // Shutdown thread-local resources for input method. This function should be // called in the UI thread after input method is used. -UI_BASE_IME_EXPORT void ShutdownInputMethod(); +COMPONENT_EXPORT(UI_BASE_IME) void ShutdownInputMethod(); // Initializes thread-local resources for input method. This function is // intended to be called from Setup function of unit tests. -UI_BASE_IME_EXPORT void InitializeInputMethodForTesting(); +COMPONENT_EXPORT(UI_BASE_IME) void InitializeInputMethodForTesting(); // Initializes thread-local resources for input method. This function is // intended to be called from TearDown function of unit tests. -UI_BASE_IME_EXPORT void ShutdownInputMethodForTesting(); +COMPONENT_EXPORT(UI_BASE_IME) void ShutdownInputMethodForTesting(); } // namespace ui
diff --git a/ui/base/ime/input_method_keyboard_controller.h b/ui/base/ime/input_method_keyboard_controller.h index a023aae..e335212 100644 --- a/ui/base/ime/input_method_keyboard_controller.h +++ b/ui/base/ime/input_method_keyboard_controller.h
@@ -5,7 +5,7 @@ #ifndef UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_H_ #define UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_H_ -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { @@ -13,7 +13,7 @@ // This class provides functionality to display the on screen keyboard and // add observers to observe changes in it. -class UI_BASE_IME_EXPORT InputMethodKeyboardController { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodKeyboardController { public: virtual ~InputMethodKeyboardController() = default;
diff --git a/ui/base/ime/input_method_keyboard_controller_observer.h b/ui/base/ime/input_method_keyboard_controller_observer.h index fc18a4e..6ec42e3 100644 --- a/ui/base/ime/input_method_keyboard_controller_observer.h +++ b/ui/base/ime/input_method_keyboard_controller_observer.h
@@ -5,7 +5,7 @@ #ifndef UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_OBSERVER_H_ #define UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_OBSERVER_H_ -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace gfx { class Rect; @@ -15,7 +15,7 @@ // This observer class provides a method to observe on screen // keyboard changes. -class UI_BASE_IME_EXPORT InputMethodKeyboardControllerObserver { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodKeyboardControllerObserver { public: // The |keyboard_rect| parameter contains the bounds of the keyboard in dips. virtual void OnKeyboardVisible(const gfx::Rect& keyboard_rect) = 0;
diff --git a/ui/base/ime/input_method_keyboard_controller_stub.h b/ui/base/ime/input_method_keyboard_controller_stub.h index 305ccdf..2dfcd7c 100644 --- a/ui/base/ime/input_method_keyboard_controller_stub.h +++ b/ui/base/ime/input_method_keyboard_controller_stub.h
@@ -5,14 +5,14 @@ #ifndef UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_STUB_H_ #define UI_BASE_IME_INPUT_METHOD_KEYBOARD_CONTROLLER_STUB_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { // This class provides a stub InputMethodKeyboardController. -class UI_BASE_IME_EXPORT InputMethodKeyboardControllerStub final +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodKeyboardControllerStub final : public InputMethodKeyboardController { public: InputMethodKeyboardControllerStub();
diff --git a/ui/base/ime/input_method_mac.h b/ui/base/ime/input_method_mac.h index 7ca676d..d547379d 100644 --- a/ui/base/ime/input_method_mac.h +++ b/ui/base/ime/input_method_mac.h
@@ -5,6 +5,7 @@ #ifndef UI_BASE_IME_INPUT_METHOD_MAC_H_ #define UI_BASE_IME_INPUT_METHOD_MAC_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_base.h" @@ -14,7 +15,7 @@ // On the Mac, key events don't pass through InputMethod. // Instead, NSTextInputClient calls are bridged to the currently focused // ui::TextInputClient object. -class UI_BASE_IME_EXPORT InputMethodMac : public InputMethodBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodMac : public InputMethodBase { public: explicit InputMethodMac(internal::InputMethodDelegate* delegate); ~InputMethodMac() override;
diff --git a/ui/base/ime/input_method_minimal.h b/ui/base/ime/input_method_minimal.h index 259c999..9bc8e60 100644 --- a/ui/base/ime/input_method_minimal.h +++ b/ui/base/ime/input_method_minimal.h
@@ -5,6 +5,7 @@ #ifndef UI_BASE_IME_INPUT_METHOD_MINIMAL_H_ #define UI_BASE_IME_INPUT_METHOD_MINIMAL_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_base.h" @@ -12,7 +13,8 @@ // A minimal implementation of ui::InputMethod, which supports only the direct // input without any compositions or conversions. -class UI_BASE_IME_EXPORT InputMethodMinimal : public InputMethodBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodMinimal + : public InputMethodBase { public: explicit InputMethodMinimal(internal::InputMethodDelegate* delegate); ~InputMethodMinimal() override;
diff --git a/ui/base/ime/input_method_observer.h b/ui/base/ime/input_method_observer.h index 1a042ae..1581c4a 100644 --- a/ui/base/ime/input_method_observer.h +++ b/ui/base/ime/input_method_observer.h
@@ -5,14 +5,14 @@ #ifndef UI_BASE_IME_INPUT_METHOD_OBSERVER_H_ #define UI_BASE_IME_INPUT_METHOD_OBSERVER_H_ -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { class InputMethod; class TextInputClient; -class UI_BASE_IME_EXPORT InputMethodObserver { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodObserver { public: virtual ~InputMethodObserver() {}
diff --git a/ui/base/ime/input_method_win_base.h b/ui/base/ime/input_method_win_base.h index f1f4950..3d9a513 100644 --- a/ui/base/ime/input_method_win_base.h +++ b/ui/base/ime/input_method_win_base.h
@@ -10,6 +10,7 @@ #include <string> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_base.h" #include "ui/base/ime/win/imm32_manager.h" @@ -17,7 +18,8 @@ namespace ui { // A common InputMethod base implementation for Windows. -class UI_BASE_IME_EXPORT InputMethodWinBase : public InputMethodBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinBase + : public InputMethodBase { public: InputMethodWinBase(internal::InputMethodDelegate* delegate, HWND toplevel_window_handle);
diff --git a/ui/base/ime/input_method_win_imm32.h b/ui/base/ime/input_method_win_imm32.h index a144e4823..62f4a40 100644 --- a/ui/base/ime/input_method_win_imm32.h +++ b/ui/base/ime/input_method_win_imm32.h
@@ -10,6 +10,7 @@ #include <string> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/input_method_win_base.h" #include "ui/base/ime/win/imm32_manager.h" @@ -17,7 +18,8 @@ namespace ui { // A common InputMethod implementation based on IMM32. -class UI_BASE_IME_EXPORT InputMethodWinImm32 : public InputMethodWinBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinImm32 + : public InputMethodWinBase { public: InputMethodWinImm32(internal::InputMethodDelegate* delegate, HWND toplevel_window_handle);
diff --git a/ui/base/ime/input_method_win_tsf.h b/ui/base/ime/input_method_win_tsf.h index aa53ec06..e3c0eedf 100644 --- a/ui/base/ime/input_method_win_tsf.h +++ b/ui/base/ime/input_method_win_tsf.h
@@ -9,6 +9,7 @@ #include <string> +#include "base/component_export.h" #include "ui/base/ime/input_method_win_base.h" namespace ui { @@ -16,7 +17,8 @@ class TSFEventRouter; // An InputMethod implementation based on Windows TSF API. -class UI_BASE_IME_EXPORT InputMethodWinTSF : public InputMethodWinBase { +class COMPONENT_EXPORT(UI_BASE_IME) InputMethodWinTSF + : public InputMethodWinBase { public: InputMethodWinTSF(internal::InputMethodDelegate* delegate, HWND toplevel_window_handle);
diff --git a/ui/base/ime/linux/BUILD.gn b/ui/base/ime/linux/BUILD.gn index bdbc26b..6469e32 100644 --- a/ui/base/ime/linux/BUILD.gn +++ b/ui/base/ime/linux/BUILD.gn
@@ -14,10 +14,9 @@ "linux_input_method_context.h", "linux_input_method_context_factory.cc", "linux_input_method_context_factory.h", - "ui_base_ime_linux_export.h", ] - defines = [ "UI_BASE_IME_LINUX_IMPLEMENTATION" ] + defines = [ "IS_UI_BASE_IME_LINUX_IMPL" ] deps = [ "//base",
diff --git a/ui/base/ime/linux/fake_input_method_context_factory.h b/ui/base/ime/linux/fake_input_method_context_factory.h index 1d5f8b8..267da58 100644 --- a/ui/base/ime/linux/fake_input_method_context_factory.h +++ b/ui/base/ime/linux/fake_input_method_context_factory.h
@@ -5,15 +5,15 @@ #ifndef UI_BASE_IME_LINUX_FAKE_INPUT_METHOD_CONTEXT_FACTORY_H_ #define UI_BASE_IME_LINUX_FAKE_INPUT_METHOD_CONTEXT_FACTORY_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/ime/linux/linux_input_method_context_factory.h" -#include "ui/base/ime/linux/ui_base_ime_linux_export.h" namespace ui { // An implementation of LinuxInputMethodContextFactory, which creates and // returns FakeInputMethodContext's. -class UI_BASE_IME_LINUX_EXPORT FakeInputMethodContextFactory +class COMPONENT_EXPORT(UI_BASE_IME_LINUX) FakeInputMethodContextFactory : public LinuxInputMethodContextFactory { public: FakeInputMethodContextFactory();
diff --git a/ui/base/ime/linux/linux_input_method_context.h b/ui/base/ime/linux/linux_input_method_context.h index ca80623..5e4f410 100644 --- a/ui/base/ime/linux/linux_input_method_context.h +++ b/ui/base/ime/linux/linux_input_method_context.h
@@ -5,8 +5,8 @@ #ifndef UI_BASE_IME_LINUX_LINUX_INPUT_METHOD_CONTEXT_H_ #define UI_BASE_IME_LINUX_LINUX_INPUT_METHOD_CONTEXT_H_ +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ime/linux/ui_base_ime_linux_export.h" #include "ui/base/ime/text_input_type.h" namespace gfx { @@ -21,7 +21,7 @@ // An interface of input method context for input method frameworks on // GNU/Linux and likes. -class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContext { +class COMPONENT_EXPORT(UI_BASE_IME_LINUX) LinuxInputMethodContext { public: virtual ~LinuxInputMethodContext() {} @@ -50,7 +50,7 @@ }; // An interface of callback functions called from LinuxInputMethodContext. -class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContextDelegate { +class COMPONENT_EXPORT(UI_BASE_IME_LINUX) LinuxInputMethodContextDelegate { public: virtual ~LinuxInputMethodContextDelegate() {}
diff --git a/ui/base/ime/linux/linux_input_method_context_factory.h b/ui/base/ime/linux/linux_input_method_context_factory.h index 2429067..4d30a968 100644 --- a/ui/base/ime/linux/linux_input_method_context_factory.h +++ b/ui/base/ime/linux/linux_input_method_context_factory.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ui/base/ime/linux/ui_base_ime_linux_export.h" +#include "base/component_export.h" namespace ui { @@ -17,7 +17,7 @@ // An interface that lets different Linux platforms override the // CreateInputMethodContext function declared here to return native input method // contexts. -class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContextFactory { +class COMPONENT_EXPORT(UI_BASE_IME_LINUX) LinuxInputMethodContextFactory { public: // Returns the current active factory or NULL. static const LinuxInputMethodContextFactory* instance();
diff --git a/ui/base/ime/linux/text_edit_command_auralinux.h b/ui/base/ime/linux/text_edit_command_auralinux.h index 92ff115..4eda237 100644 --- a/ui/base/ime/linux/text_edit_command_auralinux.h +++ b/ui/base/ime/linux/text_edit_command_auralinux.h
@@ -7,7 +7,7 @@ #include <string> -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { @@ -15,7 +15,7 @@ // Represents a command that performs a specific operation on text. // Copy and assignment are explicitly allowed; these objects live in vectors. -class UI_BASE_IME_EXPORT TextEditCommandAuraLinux { +class COMPONENT_EXPORT(UI_BASE_IME) TextEditCommandAuraLinux { public: TextEditCommandAuraLinux(TextEditCommand command, const std::string& argument) : command_(command), argument_(argument) {}
diff --git a/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h b/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h index 5ff03e3f..fb1e479c 100644 --- a/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h +++ b/ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h
@@ -7,7 +7,7 @@ #include <vector> -#include "ui/base/ime/ui_base_ime_export.h" +#include "base/component_export.h" namespace ui { class Event; @@ -18,7 +18,7 @@ // // On desktop Linux, we've traditionally supported the user's custom // keybindings. We need to support this in both content/ and in views/. -class UI_BASE_IME_EXPORT TextEditKeyBindingsDelegateAuraLinux { +class COMPONENT_EXPORT(UI_BASE_IME) TextEditKeyBindingsDelegateAuraLinux { public: // Matches a key event against the users' platform specific key bindings, // false will be returned if the key event doesn't correspond to a predefined @@ -33,10 +33,11 @@ // Sets/Gets the global TextEditKeyBindingsDelegateAuraLinux. No ownership // changes. Can be NULL. -UI_BASE_IME_EXPORT void SetTextEditKeyBindingsDelegate( +COMPONENT_EXPORT(UI_BASE_IME) +void SetTextEditKeyBindingsDelegate( TextEditKeyBindingsDelegateAuraLinux* delegate); -UI_BASE_IME_EXPORT TextEditKeyBindingsDelegateAuraLinux* -GetTextEditKeyBindingsDelegate(); +COMPONENT_EXPORT(UI_BASE_IME) +TextEditKeyBindingsDelegateAuraLinux* GetTextEditKeyBindingsDelegate(); } // namespace ui
diff --git a/ui/base/ime/linux/ui_base_ime_linux_export.h b/ui/base/ime/linux/ui_base_ime_linux_export.h deleted file mode 100644 index e59f303..0000000 --- a/ui/base/ime/linux/ui_base_ime_linux_export.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_ -#define UI_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(UI_BASE_IME_LINUX_IMPLEMENTATION) -#define UI_BASE_IME_LINUX_EXPORT __declspec(dllexport) -#else -#define UI_BASE_IME_LINUX_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(UI_BASE_IME_LINUX_IMPLEMENTATION) -#define UI_BASE_IME_LINUX_EXPORT __attribute__((visibility("default"))) -#else -#define UI_BASE_IME_LINUX_EXPORT -#endif - -#endif - -#else // !defined(COMPONENT_BUILD) - -#define UI_BASE_IME_LINUX_EXPORT - -#endif - -#endif // UI_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_
diff --git a/ui/base/ime/mock_ime_input_context_handler.h b/ui/base/ime/mock_ime_input_context_handler.h index 986efff..2d0df39 100644 --- a/ui/base/ime/mock_ime_input_context_handler.h +++ b/ui/base/ime/mock_ime_input_context_handler.h
@@ -7,15 +7,15 @@ #include <stdint.h> +#include "base/component_export.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/ime_input_context_handler_interface.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/event.h" namespace ui { class InputMethod; -class UI_BASE_IME_EXPORT MockIMEInputContextHandler +class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler : public IMEInputContextHandlerInterface { public: struct UpdateCompositionTextArg {
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h index eaf66b1..58104ab 100644 --- a/ui/base/ime/mock_input_method.h +++ b/ui/base/ime/mock_input_method.h
@@ -8,13 +8,13 @@ #include <string> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "build/build_config.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_keyboard_controller_stub.h" #include "ui/base/ime/input_method_observer.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { @@ -25,7 +25,7 @@ // of this class as the global input method with calling // SetUpInputMethodFactoryForTesting() which is declared in // ui/base/ime/input_method_factory.h -class UI_BASE_IME_EXPORT MockInputMethod : public InputMethod { +class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod { public: explicit MockInputMethod(internal::InputMethodDelegate* delegate); ~MockInputMethod() override;
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h index 1bbffb7..69f252f 100644 --- a/ui/base/ime/text_input_client.h +++ b/ui/base/ime/text_input_client.h
@@ -12,6 +12,7 @@ #include <vector> #endif +#include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/strings/string16.h" #include "build/build_config.h" @@ -19,7 +20,6 @@ #include "ui/base/ime/composition_text.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/range/range.h" @@ -33,7 +33,7 @@ enum class TextEditCommand; // An interface implemented by a View that needs text input support. -class UI_BASE_IME_EXPORT TextInputClient { +class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { public: // The reason the control was focused, used by the virtual keyboard to detect // pen input.
diff --git a/ui/base/ime/ui_base_ime_export.h b/ui/base/ime/ui_base_ime_export.h deleted file mode 100644 index 955502f..0000000 --- a/ui/base/ime/ui_base_ime_export.h +++ /dev/null
@@ -1,34 +0,0 @@ -// 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 UI_BASE_IME_UI_BASE_IME_EXPORT_H_ -#define UI_BASE_IME_UI_BASE_IME_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(UI_BASE_IME_IMPLEMENTATION) -#define UI_BASE_IME_EXPORT __declspec(dllexport) -#else -#define UI_BASE_IME_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(UI_BASE_IME_IMPLEMENTATION) -#define UI_BASE_IME_EXPORT __attribute__((visibility("default"))) -#else -#define UI_BASE_IME_EXPORT -#endif - -#endif - -#else // !defined(COMPONENT_BUILD) - -#define UI_BASE_IME_EXPORT - -#endif - -#endif // UI_BASE_IME_UI_BASE_IME_EXPORT_H_
diff --git a/ui/base/ime/ui_base_ime_types_export.h b/ui/base/ime/ui_base_ime_types_export.h deleted file mode 100644 index 354a8ad..0000000 --- a/ui/base/ime/ui_base_ime_types_export.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_ -#define UI_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_ - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(UI_BASE_IME_TYPES_IMPLEMENTATION) -#define UI_BASE_IME_TYPES_EXPORT __declspec(dllexport) -#else -#define UI_BASE_IME_TYPES_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(UI_BASE_IME_TYPES_IMPLEMENTATION) -#define UI_BASE_IME_TYPES_EXPORT __attribute__((visibility("default"))) -#else -#define UI_BASE_IME_TYPES_EXPORT -#endif - -#endif - -#else // !defined(COMPONENT_BUILD) - -#define UI_BASE_IME_TYPES_EXPORT - -#endif - -#endif // UI_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_
diff --git a/ui/base/ime/win/imm32_manager.h b/ui/base/ime/win/imm32_manager.h index e2df5f5..fcd29d3e 100644 --- a/ui/base/ime/win/imm32_manager.h +++ b/ui/base/ime/win/imm32_manager.h
@@ -10,11 +10,11 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/macros.h" #include "base/strings/string16.h" #include "ui/base/ime/text_input_mode.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/geometry/rect.h" namespace ui { @@ -74,7 +74,7 @@ // hand, we can NEVER disable either TSF or CUAS in Windows Vista, i.e. // THIS CLASS IS NOT ONLY USED ON THE INPUT CONTEXTS OF EAST-ASIAN // LANGUAGES BUT ALSO USED ON THE INPUT CONTEXTS OF ALL LANGUAGES. -class UI_BASE_IME_EXPORT IMM32Manager { +class COMPONENT_EXPORT(UI_BASE_IME) IMM32Manager { public: IMM32Manager(); virtual ~IMM32Manager();
diff --git a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h index f97533f..aa7319c 100644 --- a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h +++ b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h
@@ -12,12 +12,12 @@ #include <memory> +#include "base/component_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/win/windows_types.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/geometry/rect.h" namespace ui { @@ -26,7 +26,8 @@ // This class provides an implementation of the OnScreenKeyboardDisplayManager // that uses InputPane which is available on Windows >= 10.0.10240.0. -class UI_BASE_IME_EXPORT OnScreenKeyboardDisplayManagerInputPane final +class COMPONENT_EXPORT(UI_BASE_IME) + OnScreenKeyboardDisplayManagerInputPane final : public InputMethodKeyboardController { public: explicit OnScreenKeyboardDisplayManagerInputPane(HWND hwnd);
diff --git a/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h b/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h index 0cc130f..8fa8d1f 100644 --- a/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h +++ b/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h
@@ -5,12 +5,12 @@ #ifndef UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAP_TIP_H_ #define UI_BASE_IME_WIN_ON_SCREEN_KEYBOARD_DISPLAY_MANAGER_TAP_TIP_H_ +#include "base/component_export.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/strings/string16.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/base/ui_base_export.h" #include "ui/gfx/geometry/rect.h" @@ -21,7 +21,7 @@ // This class provides an implementation of the InputMethodKeyboardController // that uses heuristics and the TabTip.exe to display the on screen keyboard. // Used on Windows > 7 and Windows < 10.0.10240.0 -class UI_BASE_IME_EXPORT OnScreenKeyboardDisplayManagerTabTip final +class COMPONENT_EXPORT(UI_BASE_IME) OnScreenKeyboardDisplayManagerTabTip final : public InputMethodKeyboardController { public: OnScreenKeyboardDisplayManagerTabTip(HWND hwnd);
diff --git a/ui/base/ime/win/tsf_bridge.h b/ui/base/ime/win/tsf_bridge.h index 541264d0..f7ada4b73 100644 --- a/ui/base/ime/win/tsf_bridge.h +++ b/ui/base/ime/win/tsf_bridge.h
@@ -9,8 +9,8 @@ #include <windows.h> #include <wrl/client.h> +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { class TextInputClient; @@ -26,7 +26,7 @@ // of text inputting and current focused TextInputClient. // // All methods in this class must be used in UI thread. -class UI_BASE_IME_EXPORT TSFBridge { +class COMPONENT_EXPORT(UI_BASE_IME) TSFBridge { public: virtual ~TSFBridge();
diff --git a/ui/base/ime/win/tsf_event_router.h b/ui/base/ime/win/tsf_event_router.h index 6af6f582..9f09d7e 100644 --- a/ui/base/ime/win/tsf_event_router.h +++ b/ui/base/ime/win/tsf_event_router.h
@@ -11,9 +11,9 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/win/atl.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/gfx/range/range.h" namespace ui { @@ -44,7 +44,7 @@ // This class monitors TSF related events and forwards them to given // |observer|. -class UI_BASE_IME_EXPORT TSFEventRouter { +class COMPONENT_EXPORT(UI_BASE_IME) TSFEventRouter { public: // Do not pass NULL to |observer|. explicit TSFEventRouter(TSFEventRouterObserver* observer);
diff --git a/ui/base/ime/win/tsf_input_scope.h b/ui/base/ime/win/tsf_input_scope.h index e11e5de3..a9ea345 100644 --- a/ui/base/ime/win/tsf_input_scope.h +++ b/ui/base/ime/win/tsf_input_scope.h
@@ -9,23 +9,23 @@ #include <Windows.h> #include <vector> +#include "base/component_export.h" #include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" -#include "ui/base/ime/ui_base_ime_export.h" namespace ui { namespace tsf_inputscope { // Initializes the TSF for input scopes. It loads the tsf dll and get the // function pointer for setting the input scopes in TSF. -UI_BASE_IME_EXPORT void InitializeTsfForInputScopes(); +COMPONENT_EXPORT(UI_BASE_IME) void InitializeTsfForInputScopes(); // Returns InputScope list corresoponding to ui::TextInputType and // ui::TextInputMode. // This function is only used from following functions but declared for test. -UI_BASE_IME_EXPORT std::vector<InputScope> GetInputScopes( - TextInputType text_input_type, - TextInputMode text_input_mode); +COMPONENT_EXPORT(UI_BASE_IME) +std::vector<InputScope> GetInputScopes(TextInputType text_input_type, + TextInputMode text_input_mode); // Returns an instance of ITfInputScope, which is the Windows-specific // category representation corresponding to ui::TextInputType and @@ -33,18 +33,18 @@ // in the target field. // The returned instance has 0 reference count. The caller must maintain its // reference count. -UI_BASE_IME_EXPORT ITfInputScope* CreateInputScope( - TextInputType text_input_type, - TextInputMode text_input_mode); +COMPONENT_EXPORT(UI_BASE_IME) +ITfInputScope* CreateInputScope(TextInputType text_input_type, + TextInputMode text_input_mode); // A wrapper of the SetInputScopes API exported by msctf.dll. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms629026.aspx // Does nothing on Windows XP in case TSF is disabled. // NOTE: For TSF-aware window, you should use ITfInputScope instead. -UI_BASE_IME_EXPORT void SetInputScopeForTsfUnawareWindow( - HWND window_handle, - TextInputType text_input_type, - TextInputMode text_input_mode); +COMPONENT_EXPORT(UI_BASE_IME) +void SetInputScopeForTsfUnawareWindow(HWND window_handle, + TextInputType text_input_type, + TextInputMode text_input_mode); } // namespace tsf_inputscope } // namespace ui
diff --git a/ui/base/ime/win/tsf_text_store.h b/ui/base/ime/win/tsf_text_store.h index eb86030..f3f0189 100644 --- a/ui/base/ime/win/tsf_text_store.h +++ b/ui/base/ime/win/tsf_text_store.h
@@ -10,11 +10,11 @@ #include <deque> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/strings/string16.h" #include "ui/base/ime/ime_text_span.h" #include "ui/base/ime/input_method_delegate.h" -#include "ui/base/ime/ui_base_ime_export.h" #include "ui/events/event_utils.h" #include "ui/gfx/range/range.h" @@ -99,10 +99,11 @@ // // More information about TSF can be found here: // http://msdn.microsoft.com/en-us/library/ms629032 -class UI_BASE_IME_EXPORT TSFTextStore : public ITextStoreACP, - public ITfContextOwnerCompositionSink, - public ITfKeyTraceEventSink, - public ITfTextEditSink { +class COMPONENT_EXPORT(UI_BASE_IME) TSFTextStore + : public ITextStoreACP, + public ITfContextOwnerCompositionSink, + public ITfKeyTraceEventSink, + public ITfTextEditSink { public: TSFTextStore(); virtual ~TSFTextStore();
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 13cb40377..b94206b 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -719,14 +719,9 @@ DCHECK(expect_scroll_update_end_); expect_scroll_update_end_ = false; #endif - if (ShouldAnimate(gesture_event.data.scroll_end.delta_units != - blink::WebGestureEvent::ScrollUnits::kPixels)) { - // Do nothing if the scroll is being animated; the scroll animation will - // generate the ScrollEnd when it is done. - } else { - cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event); - input_handler_->ScrollEnd(&scroll_state, true); - } + + cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event); + input_handler_->ScrollEnd(&scroll_state, true); if (scroll_sequence_ignored_) return DROP_EVENT;
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index 703de75..9a88ab1f 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -51,6 +51,7 @@ ":media_import_handler", ":media_scanner", ":metadata_proxy", + ":mount_metrics", ":progress_center", ":runtime_loaded_test_util", ":task_queue", @@ -124,6 +125,7 @@ ":launcher", ":launcher_search", ":media_import_handler", + ":mount_metrics", ":progress_center", "../../common/js:files_app_entry_types", "../../common/js:metrics", @@ -490,6 +492,21 @@ externs_list = [ "../../../externs/volume_info_list.js" ] } +js_library("mount_metrics") { + deps = [ + "../../common/js:metrics", + ] +} + +js_unittest("mount_metrics_unittest") { + deps = [ + ":mount_metrics", + "//ui/file_manager/base/js:mock_chrome", + "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/base/js:volume_manager_types", + ] +} + js_library("volume_manager_impl") { deps = [ ":entry_location_impl", @@ -535,6 +552,7 @@ ":import_history_unittest", ":media_import_handler_unittest", ":media_scanner_unittest", + ":mount_metrics_unittest", ":task_queue_unittest", ":volume_manager_unittest", ]
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index a28c34c..dfbefcd 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -82,6 +82,9 @@ /** @type {!Crostini} */ this.crostini = new CrostiniImpl(); + /** @type {!MountMetrics} */ + this.mountMetrics = new MountMetrics(); + /** * String assets. * @type {Object<string>}
diff --git a/ui/file_manager/file_manager/background/js/background_scripts.js b/ui/file_manager/file_manager/background/js/background_scripts.js index e7288c6..4bd7906 100644 --- a/ui/file_manager/file_manager/background/js/background_scripts.js +++ b/ui/file_manager/file_manager/background/js/background_scripts.js
@@ -24,6 +24,7 @@ // <include src="task_queue.js"> // <include src="media_import_handler.js"> // <include src="media_scanner.js"> +// <include src="mount_metrics.js"> // <include src="progress_center.js"> // <include src="test_util.js"> // <include src="background.js">
diff --git a/ui/file_manager/file_manager/background/js/device_handler.js b/ui/file_manager/file_manager/background/js/device_handler.js index 5bb25af8..df7ae8b 100644 --- a/ui/file_manager/file_manager/background/js/device_handler.js +++ b/ui/file_manager/file_manager/background/js/device_handler.js
@@ -2,33 +2,338 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * Handler of device event. - * @constructor - * @extends {cr.EventTarget} - */ -function DeviceHandler() { - cr.EventTarget.call(this); +/** Handler of device event. */ +class DeviceHandler extends cr.EventTarget { + constructor() { + super(); + + /** + * Map of device path and mount status of devices. + * @private {Object<DeviceHandler.MountStatus>} + */ + this.mountStatus_ = {}; + + chrome.fileManagerPrivate.onDeviceChanged.addListener( + this.onDeviceChanged_.bind(this)); + chrome.fileManagerPrivate.onMountCompleted.addListener( + this.onMountCompleted_.bind(this)); + chrome.notifications.onClicked.addListener( + this.onNotificationClicked_.bind(this)); + chrome.notifications.onButtonClicked.addListener( + this.onNotificationClicked_.bind(this)); + } /** - * Map of device path and mount status of devices. - * @private {Object<DeviceHandler.MountStatus>} + * Handles notifications from C++ sides. + * @param {chrome.fileManagerPrivate.DeviceEvent} event Device event. + * @private */ - this.mountStatus_ = {}; + onDeviceChanged_(event) { + util.doIfPrimaryContext(() => { + this.onDeviceChangedInternal_(event); + }); + } - chrome.fileManagerPrivate.onDeviceChanged.addListener( - this.onDeviceChanged_.bind(this)); - chrome.fileManagerPrivate.onMountCompleted.addListener( - this.onMountCompleted_.bind(this)); - chrome.notifications.onClicked.addListener( - this.onNotificationClicked_.bind(this)); - chrome.notifications.onButtonClicked.addListener( - this.onNotificationClicked_.bind(this)); + /** + * @param {chrome.fileManagerPrivate.DeviceEvent} event Device event. + * @private + */ + onDeviceChangedInternal_(event) { + switch (event.type) { + case 'disabled': + DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.show( + event.devicePath); + break; + case 'removed': + DeviceHandler.Notification.DEVICE_FAIL.hide(event.devicePath); + DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.hide( + event.devicePath); + delete this.mountStatus_[event.devicePath]; + break; + case 'hard_unplugged': + DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED.show(event.devicePath); + break; + case 'format_start': + DeviceHandler.Notification.FORMAT_START.show(event.devicePath); + break; + case 'format_success': + DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); + DeviceHandler.Notification.FORMAT_SUCCESS.show(event.devicePath); + break; + case 'format_fail': + DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); + DeviceHandler.Notification.FORMAT_FAIL.show(event.devicePath); + break; + case 'rename_fail': + DeviceHandler.Notification.RENAME_FAIL.show(event.devicePath); + break; + default: + console.error('Unknown event type: ' + event.type); + break; + } + } + + /** + * Handles mount completed events to show notifications for removable devices. + * @param {chrome.fileManagerPrivate.MountCompletedEvent} event Mount + * completed event. + * @private + */ + onMountCompleted_(event) { + util.doIfPrimaryContext(() => { + this.onMountCompletedInternal_(event); + }); + } + + onMountCompletedInternal_(event) { + const volume = event.volumeMetadata; + + if (event.status === 'success' && event.shouldNotify) { + if (event.eventType === 'mount') { + this.onMount_(event); + } else if (event.eventType === 'unmount') { + this.onUnmount_(event); + } + } + + if (!volume.deviceType || !volume.devicePath || !event.shouldNotify) { + return; + } + + const getFirstStatus = event => { + if (event.status === 'success') { + return DeviceHandler.MountStatus.SUCCESS; + } else if (event.volumeMetadata.isParentDevice) { + return DeviceHandler.MountStatus.ONLY_PARENT_ERROR; + } else { + return DeviceHandler.MountStatus.CHILD_ERROR; + } + }; + + // Update the current status. + if (!this.mountStatus_[volume.devicePath]) { + this.mountStatus_[volume.devicePath] = + DeviceHandler.MountStatus.NO_RESULT; + } + switch (this.mountStatus_[volume.devicePath]) { + // If the multipart error message has already shown, do nothing because + // the message does not changed by the following mount results. + case DeviceHandler.MountStatus.MULTIPART_ERROR: + return; + // If this is the first result, hide the scanning notification. + case DeviceHandler.MountStatus.NO_RESULT: + this.mountStatus_[volume.devicePath] = getFirstStatus(event); + break; + // If there are only parent errors, and the new result is child's one, + // hide the parent error. (parent device contains partition table, which + // is unmountable) + case DeviceHandler.MountStatus.ONLY_PARENT_ERROR: + if (!volume.isParentDevice) { + DeviceHandler.Notification.DEVICE_FAIL.hide( + /** @type {string} */ (volume.devicePath)); + } + this.mountStatus_[volume.devicePath] = getFirstStatus(event); + break; + // We have a multi-partition device for which at least one mount + // failed. + case DeviceHandler.MountStatus.SUCCESS: + case DeviceHandler.MountStatus.CHILD_ERROR: + if (this.mountStatus_[volume.devicePath] === + DeviceHandler.MountStatus.SUCCESS && + event.status === 'success') { + this.mountStatus_[volume.devicePath] = + DeviceHandler.MountStatus.SUCCESS; + } else { + this.mountStatus_[volume.devicePath] = + DeviceHandler.MountStatus.MULTIPART_ERROR; + } + break; + } + + if (event.eventType === 'unmount') { + return; + } + + // Show the notification for the current errors. + // If there is no error, do not show/update the notification. + let message; + switch (this.mountStatus_[volume.devicePath]) { + case DeviceHandler.MountStatus.MULTIPART_ERROR: + message = volume.deviceLabel ? + strf('MULTIPART_DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) : + str('MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE'); + DeviceHandler.Notification.DEVICE_FAIL.show( + /** @type {string} */ (volume.devicePath), message); + break; + case DeviceHandler.MountStatus.CHILD_ERROR: + case DeviceHandler.MountStatus.ONLY_PARENT_ERROR: + if (event.status === 'error_unsupported_filesystem') { + message = volume.deviceLabel ? + strf('DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) : + str('DEVICE_UNSUPPORTED_DEFAULT_MESSAGE'); + DeviceHandler.Notification.DEVICE_FAIL.show( + /** @type {string} */ (volume.devicePath), message); + } else { + message = volume.deviceLabel ? + strf('DEVICE_UNKNOWN_MESSAGE', volume.deviceLabel) : + str('DEVICE_UNKNOWN_DEFAULT_MESSAGE'); + if (event.volumeMetadata.isReadOnly) { + DeviceHandler.Notification.DEVICE_FAIL_UNKNOWN_READONLY.show( + /** @type {string} */ (volume.devicePath), message); + } else { + DeviceHandler.Notification.DEVICE_FAIL_UNKNOWN.show( + /** @type {string} */ (volume.devicePath), message); + } + } + } + } + + /** + * Handles mount events. + * @param {chrome.fileManagerPrivate.MountCompletedEvent} event + * @private + */ + onMount_(event) { + // If this is remounting, which happens when resuming Chrome OS, the device + // has already inserted to the computer. So we suppress the notification. + const metadata = event.volumeMetadata; + volumeManagerFactory.getInstance() + .then( + /** + * @param {!VolumeManager} volumeManager + * @return {!Promise<!VolumeInfo>} + */ + (volumeManager) => { + if (!metadata.volumeId) { + return Promise.reject('No volume id associated with event.'); + } + return volumeManager.whenVolumeInfoReady(metadata.volumeId); + }) + .then( + /** + * @param {!VolumeInfo} volumeInfo + * @return {!Promise<!DirectoryEntry>} The root directory + * of the volume. + */ + volumeInfo => { + return importer.importEnabled().then( + /** @param {boolean} enabled */ + enabled => { + if (enabled && importer.isEligibleVolume(volumeInfo)) { + return volumeInfo.resolveDisplayRoot(); + } + return Promise.reject('Cloud import disabled.'); + }); + }) + .then( + /** + * @param {!DirectoryEntry} root + * @return {!Promise<!DirectoryEntry>} + */ + root => { + return importer.getMediaDirectory(root); + }) + .then(/** + * @param {!DirectoryEntry} directory + */ + directory => { + return importer.isPhotosAppImportEnabled().then( + /** + * @param {boolean} appEnabled + */ + appEnabled => { + // We don't want to auto-open two windows when a user + // inserts a removable device. Only open Files app if + // auto-import is disabled in Photos app. + if (!appEnabled) { + this.openMediaDirectory_( + metadata.volumeId, null, directory.fullPath); + } + }); + }) + .catch(error => { + if (metadata.deviceType && metadata.devicePath) { + if (metadata.isReadOnly && !metadata.isReadOnlyRemovableDevice) { + DeviceHandler.Notification.DEVICE_NAVIGATION_READONLY_POLICY.show( + /** @type {string} */ (metadata.devicePath)); + } else { + DeviceHandler.Notification.DEVICE_NAVIGATION.show( + /** @type {string} */ (metadata.devicePath)); + } + } + }); + } + + onUnmount_(event) { + DeviceHandler.Notification.DEVICE_NAVIGATION.hide( + /** @type {string} */ (event.devicePath)); + } + + /** + * Handles notification body or button click. + * @param {string} id ID of the notification. + * @private + */ + onNotificationClicked_(id) { + util.doIfPrimaryContext(() => { + this.onNotificationClickedInternal_(id); + }); + } + + /** + * @param {string} id ID of the notification. + * @private + */ + onNotificationClickedInternal_(id) { + const pos = id.indexOf(':'); + const type = id.substr(0, pos); + const devicePath = id.substr(pos + 1); + if (type === 'deviceNavigation' || type === 'deviceFail') { + chrome.notifications.clear(id, () => {}); + this.openMediaDirectory_(null, devicePath, null); + } else if (type === 'deviceImport') { + chrome.notifications.clear(id, () => {}); + this.openMediaDirectory_(null, devicePath, 'DCIM'); + } + } + + /** + * Opens a directory on removable media. + * @param {?string} volumeId + * @param {?string} devicePath + * @param {?string} filePath + * @private + */ + openMediaDirectory_(volumeId, devicePath, filePath) { + const event = new Event(DeviceHandler.VOLUME_NAVIGATION_REQUESTED); + event.volumeId = volumeId; + event.devicePath = devicePath; + event.filePath = filePath; + this.dispatchEvent(event); + } } -DeviceHandler.prototype = { - __proto__: cr.EventTarget.prototype + +/** + * Mount status for the device. + * Each multi-partition devices can obtain multiple mount completed events. + * This status shows what results are already obtained for the device. + * @enum {string} + * @const + */ +DeviceHandler.MountStatus = { + // There is no mount results on the device. + NO_RESULT: 'noResult', + // There is no error on the device. + SUCCESS: 'success', + // There is only parent errors, that can be overridden by child results. + ONLY_PARENT_ERROR: 'onlyParentError', + // There is one child error. + CHILD_ERROR: 'childError', + // There is multiple child results and at least one is failure. + MULTIPART_ERROR: 'multipartError' }; +Object.freeze(DeviceHandler.MountStatus); /** * An event name trigerred when a user requests to navigate to a volume. @@ -40,52 +345,129 @@ /** * Notification type. - * @param {string} prefix Prefix of notification ID. - * @param {string} title String ID of title. - * @param {string} message String ID of message. - * @param {string=} opt_buttonLabel String ID of the button label. - * @param {boolean=} opt_isClickable True if the notification body is clickable. - * @constructor - * @struct */ -DeviceHandler.Notification = function( - prefix, title, message, opt_buttonLabel, opt_isClickable) { +DeviceHandler.Notification = class { /** - * Prefix of notification ID. - * @type {string} + * @param {string} prefix Prefix of notification ID. + * @param {string} title String ID of title. + * @param {string} message String ID of message. + * @param {string=} opt_buttonLabel String ID of the button label. + * @param {boolean=} opt_isClickable True if the notification body is + * clickable. */ - this.prefix = prefix; + constructor(prefix, title, message, opt_buttonLabel, opt_isClickable) { + /** + * Prefix of notification ID. + * @type {string} + */ + this.prefix = prefix; + + /** + * String ID of title. + * @type {string} + */ + this.title = title; + + /** + * String ID of message. + * @type {string} + */ + this.message = message; + + /** + * String ID of button label. + * @type {?string} + */ + this.buttonLabel = opt_buttonLabel || null; + + /** + * True if the notification body is clickable. + * @type {boolean} + */ + this.isClickable = opt_isClickable || false; + + /** + * Queue of API call. + * @type {AsyncUtil.Queue} + * @private + */ + this.queue_ = new AsyncUtil.Queue(); + } /** - * String ID of title. - * @type {string} + * Shows the notification for the device path. + * @param {string} devicePath Device path. + * @param {string=} opt_message Message overrides the default message. + * @return {string} Notification ID. */ - this.title = title; + show(devicePath, opt_message) { + const notificationId = this.makeId_(devicePath); + this.queue_.run(callback => { + this.showInternal_(notificationId, opt_message || null, callback); + }); + return notificationId; + } /** - * String ID of message. - * @type {string} + * Shows the notification for the device path. + * If the existing notification has been already shown, it does not anything. + * @param {string} devicePath Device path. */ - this.message = message; + showOnce(devicePath) { + const notificationId = this.makeId_(devicePath); + this.queue_.run(function(callback) { + chrome.notifications.getAll(idList => { + if (idList.indexOf(notificationId) !== -1) { + callback(); + return; + } + this.showInternal_(notificationId, null, callback); + }); + }); + } /** - * String ID of button label. - * @type {?string} - */ - this.buttonLabel = opt_buttonLabel || null; - - /** - * True if the notification body is clickable. - * @type {boolean} - */ - this.isClickable = opt_isClickable || false; - - /** - * Queue of API call. - * @type {AsyncUtil.Queue} + * Shows the notificaiton without using AsyncQueue. + * @param {string} notificationId Notification ID. + * @param {?string} message Message overriding the normal message. + * @param {function()} callback Callback to be invoked when the notification + * is created. * @private */ - this.queue_ = new AsyncUtil.Queue(); + showInternal_(notificationId, message, callback) { + const buttons = + this.buttonLabel ? [{title: str(this.buttonLabel)}] : undefined; + chrome.notifications.create( + notificationId, { + type: 'basic', + title: str(this.title), + message: message || str(this.message), + iconUrl: chrome.runtime.getURL('/common/images/icon96.png'), + buttons: buttons, + isClickable: this.isClickable + }, + callback); + } + + /** + * Hides the notification for the device path. + * @param {string} devicePath Device path. + */ + hide(devicePath) { + this.queue_.run(callback => { + chrome.notifications.clear(this.makeId_(devicePath), callback); + }); + } + + /** + * Makes a notification ID for the device path. + * @param {string} devicePath Device path. + * @return {string} Notification ID. + * @private + */ + makeId_(devicePath) { + return this.prefix + ':' + devicePath; + } }; /** @@ -190,389 +572,3 @@ DeviceHandler.Notification.RENAME_FAIL = new DeviceHandler.Notification( 'renameFail', 'RENAMING_OF_DEVICE_FAILED_TITLE', 'RENAMING_OF_DEVICE_FINISHED_FAILURE_MESSAGE'); - -/** - * Shows the notification for the device path. - * @param {string} devicePath Device path. - * @param {string=} opt_message Message overrides the default message. - * @return {string} Notification ID. - */ -DeviceHandler.Notification.prototype.show = function(devicePath, opt_message) { - const notificationId = this.makeId_(devicePath); - this.queue_.run(callback => { - this.showInternal_(notificationId, opt_message || null, callback); - }); - return notificationId; -}; - -/** - * Shows the notification for the device path. - * If the existing notification has been already shown, it does not anything. - * @param {string} devicePath Device path. - */ -DeviceHandler.Notification.prototype.showOnce = function(devicePath) { - const notificationId = this.makeId_(devicePath); - this.queue_.run(function(callback) { - chrome.notifications.getAll(idList => { - if (idList.indexOf(notificationId) !== -1) { - callback(); - return; - } - this.showInternal_(notificationId, null, callback); - }); - }); -}; - -/** - * Shows the notificaiton without using AsyncQueue. - * @param {string} notificationId Notification ID. - * @param {?string} message Message overriding the normal message. - * @param {function()} callback Callback to be invoked when the notification is - * created. - * @private - */ -DeviceHandler.Notification.prototype.showInternal_ = function( - notificationId, message, callback) { - const buttons = - this.buttonLabel ? [{title: str(this.buttonLabel)}] : undefined; - chrome.notifications.create( - notificationId, { - type: 'basic', - title: str(this.title), - message: message || str(this.message), - iconUrl: chrome.runtime.getURL('/common/images/icon96.png'), - buttons: buttons, - isClickable: this.isClickable - }, - callback); -}; - -/** - * Hides the notification for the device path. - * @param {string} devicePath Device path. - */ -DeviceHandler.Notification.prototype.hide = function(devicePath) { - this.queue_.run(callback => { - chrome.notifications.clear(this.makeId_(devicePath), callback); - }); -}; - -/** - * Makes a notification ID for the device path. - * @param {string} devicePath Device path. - * @return {string} Notification ID. - * @private - */ -DeviceHandler.Notification.prototype.makeId_ = function(devicePath) { - return this.prefix + ':' + devicePath; -}; - -/** - * Handles notifications from C++ sides. - * @param {chrome.fileManagerPrivate.DeviceEvent} event Device event. - * @private - */ -DeviceHandler.prototype.onDeviceChanged_ = function(event) { - util.doIfPrimaryContext(() => { - this.onDeviceChangedInternal_(event); - }); -}; - -/** - * @param {chrome.fileManagerPrivate.DeviceEvent} event Device event. - * @private - */ -DeviceHandler.prototype.onDeviceChangedInternal_ = function(event) { - switch (event.type) { - case 'disabled': - DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.show( - event.devicePath); - break; - case 'removed': - DeviceHandler.Notification.DEVICE_FAIL.hide(event.devicePath); - DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.hide( - event.devicePath); - delete this.mountStatus_[event.devicePath]; - break; - case 'hard_unplugged': - DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED.show(event.devicePath); - break; - case 'format_start': - DeviceHandler.Notification.FORMAT_START.show(event.devicePath); - break; - case 'format_success': - DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); - DeviceHandler.Notification.FORMAT_SUCCESS.show(event.devicePath); - break; - case 'format_fail': - DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); - DeviceHandler.Notification.FORMAT_FAIL.show(event.devicePath); - break; - case 'rename_fail': - DeviceHandler.Notification.RENAME_FAIL.show(event.devicePath); - break; - default: - console.error('Unknown event type: ' + event.type); - break; - } -}; - -/** - * Mount status for the device. - * Each multi-partition devices can obtain multiple mount completed events. - * This status shows what results are already obtained for the device. - * @enum {string} - * @const - */ -DeviceHandler.MountStatus = { - // There is no mount results on the device. - NO_RESULT: 'noResult', - // There is no error on the device. - SUCCESS: 'success', - // There is only parent errors, that can be overridden by child results. - ONLY_PARENT_ERROR: 'onlyParentError', - // There is one child error. - CHILD_ERROR: 'childError', - // There is multiple child results and at least one is failure. - MULTIPART_ERROR: 'multipartError' -}; -Object.freeze(DeviceHandler.MountStatus); - -/** - * Handles mount completed events to show notifications for removable devices. - * @param {chrome.fileManagerPrivate.MountCompletedEvent} event Mount completed - * event. - * @private - */ -DeviceHandler.prototype.onMountCompleted_ = function(event) { - util.doIfPrimaryContext(() => { - this.onMountCompletedInternal_(event); - }); -}; - -DeviceHandler.prototype.onMountCompletedInternal_ = function(event) { - const volume = event.volumeMetadata; - - if (event.status === 'success' && event.shouldNotify) { - if (event.eventType === 'mount') { - this.onMount_(event); - } else if (event.eventType === 'unmount') { - this.onUnmount_(event); - } - } - - if (!volume.deviceType || !volume.devicePath || !event.shouldNotify) { - return; - } - - const getFirstStatus = event => { - if (event.status === 'success') { - return DeviceHandler.MountStatus.SUCCESS; - } else if (event.volumeMetadata.isParentDevice) { - return DeviceHandler.MountStatus.ONLY_PARENT_ERROR; - } else { - return DeviceHandler.MountStatus.CHILD_ERROR; - } - }; - - // Update the current status. - if (!this.mountStatus_[volume.devicePath]) { - this.mountStatus_[volume.devicePath] = DeviceHandler.MountStatus.NO_RESULT; - } - switch (this.mountStatus_[volume.devicePath]) { - // If the multipart error message has already shown, do nothing because the - // message does not changed by the following mount results. - case DeviceHandler.MountStatus.MULTIPART_ERROR: - return; - // If this is the first result, hide the scanning notification. - case DeviceHandler.MountStatus.NO_RESULT: - this.mountStatus_[volume.devicePath] = getFirstStatus(event); - break; - // If there are only parent errors, and the new result is child's one, hide - // the parent error. (parent device contains partition table, which is - // unmountable) - case DeviceHandler.MountStatus.ONLY_PARENT_ERROR: - if (!volume.isParentDevice) { - DeviceHandler.Notification.DEVICE_FAIL.hide( - /** @type {string} */ (volume.devicePath)); - } - this.mountStatus_[volume.devicePath] = getFirstStatus(event); - break; - // We have a multi-partition device for which at least one mount - // failed. - case DeviceHandler.MountStatus.SUCCESS: - case DeviceHandler.MountStatus.CHILD_ERROR: - if (this.mountStatus_[volume.devicePath] === - DeviceHandler.MountStatus.SUCCESS && - event.status === 'success') { - this.mountStatus_[volume.devicePath] = - DeviceHandler.MountStatus.SUCCESS; - } else { - this.mountStatus_[volume.devicePath] = - DeviceHandler.MountStatus.MULTIPART_ERROR; - } - break; - } - - if (event.eventType === 'unmount') { - return; - } - - // Show the notification for the current errors. - // If there is no error, do not show/update the notification. - let message; - switch (this.mountStatus_[volume.devicePath]) { - case DeviceHandler.MountStatus.MULTIPART_ERROR: - message = volume.deviceLabel ? - strf('MULTIPART_DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) : - str('MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE'); - DeviceHandler.Notification.DEVICE_FAIL.show( - /** @type {string} */ (volume.devicePath), message); - break; - case DeviceHandler.MountStatus.CHILD_ERROR: - case DeviceHandler.MountStatus.ONLY_PARENT_ERROR: - if (event.status === 'error_unsupported_filesystem') { - message = volume.deviceLabel ? - strf('DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) : - str('DEVICE_UNSUPPORTED_DEFAULT_MESSAGE'); - DeviceHandler.Notification.DEVICE_FAIL.show( - /** @type {string} */ (volume.devicePath), message); - } else { - message = volume.deviceLabel ? - strf('DEVICE_UNKNOWN_MESSAGE', volume.deviceLabel) : - str('DEVICE_UNKNOWN_DEFAULT_MESSAGE'); - if (event.volumeMetadata.isReadOnly) { - DeviceHandler.Notification.DEVICE_FAIL_UNKNOWN_READONLY.show( - /** @type {string} */ (volume.devicePath), message); - } else { - DeviceHandler.Notification.DEVICE_FAIL_UNKNOWN.show( - /** @type {string} */ (volume.devicePath), message); - } - } - } -}; - -/** - * Handles mount events. - * @param {chrome.fileManagerPrivate.MountCompletedEvent} event - * @private - */ -DeviceHandler.prototype.onMount_ = function(event) { - // If this is remounting, which happens when resuming Chrome OS, the device - // has already inserted to the computer. So we suppress the notification. - const metadata = event.volumeMetadata; - volumeManagerFactory.getInstance() - .then( - /** - * @param {!VolumeManager} volumeManager - * @return {!Promise<!VolumeInfo>} - */ - (volumeManager) => { - if (!metadata.volumeId) { - return Promise.reject('No volume id associated with event.'); - } - return volumeManager.whenVolumeInfoReady(metadata.volumeId); - }) - .then( - /** - * @param {!VolumeInfo} volumeInfo - * @return {!Promise<!DirectoryEntry>} The root directory - * of the volume. - */ - volumeInfo => { - return importer.importEnabled().then( - /** @param {boolean} enabled */ - enabled => { - if (enabled && importer.isEligibleVolume(volumeInfo)) { - return volumeInfo.resolveDisplayRoot(); - } - return Promise.reject('Cloud import disabled.'); - }); - }) - .then( - /** - * @param {!DirectoryEntry} root - * @return {!Promise<!DirectoryEntry>} - */ - root => { - return importer.getMediaDirectory(root); - }) - .then(/** - * @param {!DirectoryEntry} directory - */ - directory => { - return importer.isPhotosAppImportEnabled().then( - /** - * @param {boolean} appEnabled - */ - appEnabled => { - // We don't want to auto-open two windows when a user - // inserts a removable device. Only open Files app if - // auto-import is disabled in Photos app. - if (!appEnabled) { - this.openMediaDirectory_( - metadata.volumeId, null, directory.fullPath); - } - }); - }) - .catch(error => { - if (metadata.deviceType && metadata.devicePath) { - if (metadata.isReadOnly && !metadata.isReadOnlyRemovableDevice) { - DeviceHandler.Notification.DEVICE_NAVIGATION_READONLY_POLICY.show( - /** @type {string} */ (metadata.devicePath)); - } else { - DeviceHandler.Notification.DEVICE_NAVIGATION.show( - /** @type {string} */ (metadata.devicePath)); - } - } - }); -}; - -DeviceHandler.prototype.onUnmount_ = event => { - DeviceHandler.Notification.DEVICE_NAVIGATION.hide( - /** @type {string} */ (event.devicePath)); -}; - -/** - * Handles notification body or button click. - * @param {string} id ID of the notification. - * @private - */ -DeviceHandler.prototype.onNotificationClicked_ = function(id) { - util.doIfPrimaryContext(() => { - this.onNotificationClickedInternal_(id); - }); -}; - -/** - * @param {string} id ID of the notification. - * @private - */ -DeviceHandler.prototype.onNotificationClickedInternal_ = function(id) { - const pos = id.indexOf(':'); - const type = id.substr(0, pos); - const devicePath = id.substr(pos + 1); - if (type === 'deviceNavigation' || type === 'deviceFail') { - chrome.notifications.clear(id, () => {}); - this.openMediaDirectory_(null, devicePath, null); - } else if (type === 'deviceImport') { - chrome.notifications.clear(id, () => {}); - this.openMediaDirectory_(null, devicePath, 'DCIM'); - } -}; - -/** - * Opens a directory on removable media. - * @param {?string} volumeId - * @param {?string} devicePath - * @param {?string} filePath - * @private - */ -DeviceHandler.prototype.openMediaDirectory_ = function( - volumeId, devicePath, filePath) { - const event = new Event(DeviceHandler.VOLUME_NAVIGATION_REQUESTED); - event.volumeId = volumeId; - event.devicePath = devicePath; - event.filePath = filePath; - this.dispatchEvent(event); -};
diff --git a/ui/file_manager/file_manager/background/js/mount_metrics.js b/ui/file_manager/file_manager/background/js/mount_metrics.js new file mode 100644 index 0000000..abe4e29 --- /dev/null +++ b/ui/file_manager/file_manager/background/js/mount_metrics.js
@@ -0,0 +1,124 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Records metrics for mount events. + * @constructor + * @struct + */ +function MountMetrics() { + chrome.fileManagerPrivate.onMountCompleted.addListener( + this.onMountCompleted_.bind(this)); +} + +/** + * Event handler called when some volume was mounted or unmounted. + * @param {chrome.fileManagerPrivate.MountCompletedEvent} event Received event. + * @private + */ +MountMetrics.prototype.onMountCompleted_ = function(event) { + if (event.eventType === 'mount') { + if (event.status === 'success' && event.volumeMetadata) { + if (event.volumeMetadata.volumeType === 'provided') { + const providerUmaValue = + this.getFileSystemProviderForUma(event.volumeMetadata.providerId); + metrics.recordEnum( + 'FileSystemProviderMounted', providerUmaValue, + Object.keys(MountMetrics.FileSystemProvidersForUMA).length + 1); + } + } + } +}; + + +/** + * This enum provides a lookup for each file system provider type to the UMA + * enun FileSystemProviderMountType that can be found in + * tools/metrics/histograms/enums.xml. + * These values should never be changed, new entries should be added to the end + * of the enumeration. + * + * @enum {number} + * @const + */ +MountMetrics.FileSystemProvidersForUMA = { + UNKNOWN: 0, + ZIP_UNPACKER: 1, + FILE_SYSTEM_FOR_DROPBOX: 2, + FILE_SYSTEM_FOR_ONEDRIVE: 3, + SFTP_FILE_SYSTEM: 4, + BOX_FOR_CHROMEOS: 5, + TED_TALKS: 6, + WEBDAV_FILE_SYSTEM: 7, + CLOUD_STORAGE: 8, + SCAN: 9, + FILE_SYSTEM_FOR_SMB_CIFS: 10, + ADD_MY_DOCUMENTS: 11, + WICKED_GOOD_UNARCHIVER: 12, + NETWORK_FILE_SHARE_FOR_CHROMEOS: 13, + LAN_FOLDER: 14, + ZIP_ARCHIVER: 15, + SECURE_SHELL_APP: 16, + NATIVE_NETWORK_SMB: 17, +}; +Object.freeze(MountMetrics.FileSystemProvidersForUMA); + +/** + * Enumeration of known FSPs used to map to a UMA enumeration index. + * All FSPs NOT present in this list will be reported as 'Unknown'. + * + * These look like extension ids, but are actually provider ids which may + * but don't have to be extension ids. + * + * @enum {MountMetrics.FileSystemProvidersForUMA<number>} + */ +MountMetrics.FileSystemProviders = { + oedeeodfidgoollimchfdnbmhcpnklnd: + MountMetrics.FileSystemProvidersForUMA.ZIP_UNPACKER, + hlffpaajmfllggclnjppbblobdhokjhe: + MountMetrics.FileSystemProvidersForUMA.FILE_SYSTEM_FOR_DROPBOX, + jbfdfcehgafdbfpniaimfbfomafoadgo: + MountMetrics.FileSystemProvidersForUMA.FILE_SYSTEM_FOR_ONEDRIVE, + gbheifiifcfekkamhepkeogobihicgmn: + MountMetrics.FileSystemProvidersForUMA.SFTP_FILE_SYSTEM, + dikonaebkejmpbpcnnmfaeopkaenicgf: + MountMetrics.FileSystemProvidersForUMA.BOX_FOR_CHROMEOS, + iibcngmpkgghccnakicfmgajlkhnohep: + MountMetrics.FileSystemProvidersForUMA.TED_TALKS, + hmckflbfniicjijmdoffagjkpnjgbieh: + MountMetrics.FileSystemProvidersForUMA.WEBDAV_FILE_SYSTEM, + ibfbhbegfkamboeglpnianlggahglbfi: + MountMetrics.FileSystemProvidersForUMA.CLOUD_STORAGE, + pmnllmkmjilbojkpgplbdmckghmaocjh: MountMetrics.FileSystemProvidersForUMA.SCAN, + mfhnnfciefdpolbelmfkpmhhmlkehbdf: + MountMetrics.FileSystemProvidersForUMA.FILE_SYSTEM_FOR_SMB_CIFS, + plmanjiaoflhcilcfdnjeffklbgejmje: + MountMetrics.FileSystemProvidersForUMA.ADD_MY_DOCUMENTS, + mljpablpddhocfbnokacjggdbmafjnon: + MountMetrics.FileSystemProvidersForUMA.WICKED_GOOD_UNARCHIVER, + ndjpildffkeodjdaeebdhnncfhopkajk: + MountMetrics.FileSystemProvidersForUMA.NETWORK_FILE_SHARE_FOR_CHROMEOS, + gmhmnhjihabohahcllfgjooaoecglhpi: + MountMetrics.FileSystemProvidersForUMA.LAN_FOLDER, + dmboannefpncccogfdikhmhpmdnddgoe: + MountMetrics.FileSystemProvidersForUMA.ZIP_ARCHIVER, + pnhechapfaindjhompbnflcldabbghjo: + MountMetrics.FileSystemProvidersForUMA.SECURE_SHELL_APP, + /** + * Native Providers. + */ + '@smb': MountMetrics.FileSystemProvidersForUMA.NATIVE_NETWORK_SMB, +}; +Object.freeze(MountMetrics.FileSystemProviders); + +/** + * Returns the UMA index for a provided file system type. Returns + * MountMetrics.FileSystemProvidersForUMA.UNKNOWN for unknown providers. + * @param {string|undefined} providerId The FSP provider ID. + * @return {MountMetrics.FileSystemProvidersForUMA} + */ +MountMetrics.prototype.getFileSystemProviderForUma = function(providerId) { + return MountMetrics.FileSystemProviders[providerId] || + MountMetrics.FileSystemProvidersForUMA.UNKNOWN; +};
diff --git a/ui/file_manager/file_manager/background/js/mount_metrics_unittest.js b/ui/file_manager/file_manager/background/js/mount_metrics_unittest.js new file mode 100644 index 0000000..ee2c200 --- /dev/null +++ b/ui/file_manager/file_manager/background/js/mount_metrics_unittest.js
@@ -0,0 +1,87 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +/** @type {!MountMetrics} */ +let mountMetrics; + +/** + * Mock chrome APIs. + * @type {!Object} + */ +let mockChrome; + +/** + * Mock metrics. + * @type {!Object} + */ +window.metrics = { + calledName: '', + calledValue: '', + recordEnum: function(name, value, opt_validValues) { + window.metrics.calledName = name; + window.metrics.calledValue = value; + }, +}; + +// Set up the test components. +function setUp() { + mockChrome = { + fileManagerPrivate: { + onMountCompletedListeners_: [], + onMountCompleted: { + addListener: function(listener) { + mockChrome.fileManagerPrivate.onMountCompletedListeners_.push( + listener); + }, + dispatchEvent: function(event) { + mockChrome.fileManagerPrivate.onMountCompletedListeners_.forEach( + listener => { + listener(event); + }); + } + } + } + }; + installMockChrome(mockChrome); + new MockCommandLinePrivate(); + + mountMetrics = new MountMetrics(); +} + +/** + * Tests mounting a file system provider where the providerId is not known to + * mount metrics. + */ +function testMountUnknownProvider() { + mockChrome.fileManagerPrivate.onMountCompleted.dispatchEvent({ + eventType: 'mount', + status: 'success', + volumeMetadata: { + volumeType: VolumeManagerCommon.VolumeType.PROVIDED, + providerId: 'fubar', + } + }); + + assertEquals(window.metrics.calledName, 'FileSystemProviderMounted'); + assertEquals(window.metrics.calledValue, 0); +} + +/** + * Tests mounting Zip Archiver file system provider. + */ +function testMountZipArchiver() { + mockChrome.fileManagerPrivate.onMountCompleted.dispatchEvent({ + eventType: 'mount', + status: 'success', + volumeMetadata: { + volumeType: VolumeManagerCommon.VolumeType.PROVIDED, + providerId: 'dmboannefpncccogfdikhmhpmdnddgoe', + } + }); + + assertEquals(window.metrics.calledName, 'FileSystemProviderMounted'); + assertEquals(window.metrics.calledValue, 15); +}
diff --git a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js index ec0fa7f3..55a6985 100644 --- a/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js +++ b/ui/file_manager/file_manager/background/js/runtime_loaded_test_util.js
@@ -826,6 +826,28 @@ }; /** + * Calls the metadata model to get the selected file entries in the file + * list and try to get their metadata properties. + * + * @param {Array<String>} properties Content metadata properties to get. + * @param {function(*)} callback Callback with metadata results returned. + * @suppress {missingProperties} getContentMetadata isn't visible in the + * background window. + */ +test.util.async.getContentMetadata = (contentWindow, properties, callback) => { + const entries = + contentWindow.fileManager.directoryModel.getSelectedEntries_(); + + assert(entries.length > 0); + const metaPromise = + contentWindow.fileManager.metadataModel.get(entries, properties); + // Wait for the promise to resolve + metaPromise.then(resultsList => { + callback(resultsList); + }); +}; + +/** * Returns true when FileManager has finished loading, by checking the attribute * "loaded" on its root element. */
diff --git a/ui/file_manager/file_manager/common/js/async_util.js b/ui/file_manager/file_manager/common/js/async_util.js index f701d61..b48a34eb 100644 --- a/ui/file_manager/file_manager/common/js/async_util.js +++ b/ui/file_manager/file_manager/common/js/async_util.js
@@ -31,8 +31,8 @@ const queue = new AsyncUtil.Queue(); for (let i = 0; i < array.length; i++) { queue.run(((element, index, iterationCompletionCallback) => { - callback(iterationCompletionCallback, element, index, array); - }).bind(null, array[i], i)); + callback(iterationCompletionCallback, element, index, array); + }).bind(null, array[i], i)); } queue.run(iterationCompletionCallback => { completionCallback(); // Don't pass iteration completion callback. @@ -344,8 +344,8 @@ // If recently called, then schedule the consecutive call with a delay. if (Date.now() - this.lastRunTime_ < this.delay_) { this.cancelScheduledRuns_(); - this.scheduledRunsTimer_ = setTimeout(this.runImmediately_.bind(this), - this.delay_ + 1); + this.scheduledRunsTimer_ = + setTimeout(this.runImmediately_.bind(this), this.delay_ + 1); this.lastRunTime_ = Date.now(); return; }
diff --git a/ui/file_manager/file_manager/common/js/async_util_unittest.js b/ui/file_manager/file_manager/common/js/async_util_unittest.js index 7951a97..f5dd07a 100644 --- a/ui/file_manager/file_manager/common/js/async_util_unittest.js +++ b/ui/file_manager/file_manager/common/js/async_util_unittest.js
@@ -13,11 +13,13 @@ let slot; function setUp() { - slot = new PromiseSlot(value => { - result = 'fulfilled:' + value; - }, value => { - result = 'rejected:' + value; - }); + slot = new PromiseSlot( + value => { + result = 'fulfilled:' + value; + }, + value => { + result = 'rejected:' + value; + }); result = null; } @@ -25,16 +27,22 @@ const fulfilledPromise = Promise.resolve('fulfilled'); const rejectedPromise = Promise.reject('rejected'); slot.setPromise(fulfilledPromise); - reportPromise(fulfilledPromise.then(() => { - assertEquals('fulfilled:fulfilled', result); - slot.setPromise(rejectedPromise); - return rejectedPromise; - }).then(() => { - // Should not reach here. - assertTrue(false); - }, () => { - assertEquals('rejected:rejected', result); - }), callback); + reportPromise( + fulfilledPromise + .then(() => { + assertEquals('fulfilled:fulfilled', result); + slot.setPromise(rejectedPromise); + return rejectedPromise; + }) + .then( + () => { + // Should not reach here. + assertTrue(false); + }, + () => { + assertEquals('rejected:rejected', result); + }), + callback); } function testPromiseSlotReassignBeforeCompletion(callback) { @@ -47,15 +55,19 @@ slot.setPromise(computingPromise); // Reassign promise. slot.setPromise(fulfilledPromise); - reportPromise(fulfilledPromise.then(() => { - assertEquals('fulfilled:fulfilled', result); - fulfillComputation('fulfilled after detached'); - return computingPromise; - }).then(value => { - assertEquals('fulfilled after detached', value); - // The detached promise does not affect the slot. - assertEquals('fulfilled:fulfilled', result); - }), callback); + reportPromise( + fulfilledPromise + .then(() => { + assertEquals('fulfilled:fulfilled', result); + fulfillComputation('fulfilled after detached'); + return computingPromise; + }) + .then(value => { + assertEquals('fulfilled after detached', value); + // The detached promise does not affect the slot. + assertEquals('fulfilled:fulfilled', result); + }), + callback); } function testPromiseSlotReassignBeforeCompletionWithCancel(callback) { @@ -70,17 +82,23 @@ slot.setPromise(computingPromise); slot.setPromise(fulfilledPromise); - reportPromise(fulfilledPromise.then(() => { - assertEquals('fulfilled:fulfilled', result); - return computingPromise; - }).then(() => { - // Should not reach here. - assertTrue(false); - }, value => { - assertEquals('cancelled', value); - // The detached promise does not affect the slot. - assertEquals('fulfilled:fulfilled', result); - }), callback); + reportPromise( + fulfilledPromise + .then(() => { + assertEquals('fulfilled:fulfilled', result); + return computingPromise; + }) + .then( + () => { + // Should not reach here. + assertTrue(false); + }, + value => { + assertEquals('cancelled', value); + // The detached promise does not affect the slot. + assertEquals('fulfilled:fulfilled', result); + }), + callback); } function testPromiseSlotReassignNullBeforeCompletion(callback) { @@ -94,8 +112,10 @@ assertEquals(null, result); fulfillComputation('fulfilled'); - reportPromise(computingPromise.then(value => { - assertEquals('fulfilled', value); - assertEquals(null, result); - }), callback); + reportPromise( + computingPromise.then(value => { + assertEquals('fulfilled', value); + assertEquals(null, result); + }), + callback); }
diff --git a/ui/file_manager/file_manager/common/js/file_type.js b/ui/file_manager/file_manager/common/js/file_type.js index cf7dd666..ba2337b 100644 --- a/ui/file_manager/file_manager/common/js/file_type.js +++ b/ui/file_manager/file_manager/common/js/file_type.js
@@ -470,8 +470,10 @@ // subtype is the extension excluding the first dot. return { - name: 'GENERIC_FILE_TYPE', type: 'UNKNOWN', - subtype: extension.substr(1).toUpperCase(), icon: '' + name: 'GENERIC_FILE_TYPE', + type: 'UNKNOWN', + subtype: extension.substr(1).toUpperCase(), + icon: '' }; }; @@ -511,8 +513,10 @@ // subtype is the extension excluding the first dot. return { - name: 'GENERIC_FILE_TYPE', type: 'UNKNOWN', - subtype: extension.substr(1).toUpperCase(), icon: '' + name: 'GENERIC_FILE_TYPE', + type: 'UNKNOWN', + subtype: extension.substr(1).toUpperCase(), + icon: '' }; };
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types.js b/ui/file_manager/file_manager/common/js/files_app_entry_types.js index 3396058..141c17cc 100644 --- a/ui/file_manager/file_manager/common/js/files_app_entry_types.js +++ b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
@@ -206,7 +206,6 @@ this.currentReader_ = this.readers_.pop(); this.readEntries(success, error); } - }, error); } } @@ -263,7 +262,8 @@ constructor(label, rootType, devicePath = '') { /** * @private {string} label: Label to be used when displaying to user, it - * should be already translated. */ + * should be already translated. + */ this.label_ = label; /** @private {VolumeManagerCommon.RootType} rootType root type. */ @@ -720,7 +720,8 @@ constructor(label, rootType, opt_sourceRestriction) { /** * @public {string} label: Label to be used when displaying to user, it - * should be already translated. */ + * should be already translated. + */ this.label = label; /** @public {string} Name for this volume. */
diff --git a/ui/file_manager/file_manager/common/js/importer_common.js b/ui/file_manager/file_manager/common/js/importer_common.js index f9241fd..9ab80cab 100644 --- a/ui/file_manager/file_manager/common/js/importer_common.js +++ b/ui/file_manager/file_manager/common/js/importer_common.js
@@ -54,7 +54,7 @@ */ importer.ELIGIBLE_VOLUME_TYPES_ = [ VolumeManagerCommon.VolumeType.MTP, - VolumeManagerCommon.VolumeType.REMOVABLE + VolumeManagerCommon.VolumeType.REMOVABLE, ]; /** @@ -63,7 +63,7 @@ */ importer.ValidImportRoots_ = { DCIM: 'DCIM', - MP_ROOT: 'MP_ROOT' // MP_ROOT is a Sony thing. + MP_ROOT: 'MP_ROOT' // MP_ROOT is a Sony thing. }; /** @@ -83,8 +83,7 @@ */ importer.isEligibleType = entry => { // TODO(mtomasz): Add support to mime types. - return !!entry && - entry.isFile && + return !!entry && entry.isFile && FileType.isType(['image', 'raw', 'video'], entry); }; @@ -95,7 +94,7 @@ * @return {!Array<string>} */ importer.splitPath_ = entry => { - const splitPath = entry.fullPath.toUpperCase().split('/'); + const splitPath = entry.fullPath.toUpperCase().split('/'); // Remove the empty string caused by the leading '/'. splitPath.splice(0, 1); // If there is a trailing empty string, remove it. @@ -189,7 +188,7 @@ if (!entry || !entry.isDirectory || !entry.fullPath) { return false; } - const splitPath = importer.splitPath_(/** @type {Entry} */(entry)); + const splitPath = importer.splitPath_(/** @type {Entry} */ (entry)); if (importer.isEligiblePath_(splitPath)) { return true; } @@ -223,14 +222,13 @@ } // If standard (upper case) forms are not present, // check for a lower-case "DCIM". - return importer.getDirectory_(directory, 'dcim') - .then(directory => { - if (!!directory && directory.isDirectory) { - return Promise.resolve(directory); - } else { - return Promise.reject('Unable to local media directory.'); - } - }); + return importer.getDirectory_(directory, 'dcim').then(directory => { + if (!!directory && directory.isDirectory) { + return Promise.resolve(directory); + } else { + return Promise.reject('Unable to local media directory.'); + } + }); }); }; @@ -269,15 +267,14 @@ * is enabled. */ importer.importEnabled = () => { - return new Promise( - (resolve, reject) => { - chrome.commandLinePrivate.hasSwitch( - 'disable-cloud-import', - /** @param {boolean} disabled */ - disabled => { - resolve(!disabled); - }); - }); + return new Promise((resolve, reject) => { + chrome.commandLinePrivate.hasSwitch( + 'disable-cloud-import', + /** @param {boolean} disabled */ + disabled => { + resolve(!disabled); + }); + }); }; /** @@ -337,19 +334,15 @@ */ importer.getMachineId = () => { const storage = importer.ChromeLocalStorage.getInstance(); - return storage.get(importer.Setting.MACHINE_ID) - .then( - id => { - if (id) { - return id; - } - id = importer.generateId(); - return storage.set(importer.Setting.MACHINE_ID, id) - .then( - () => { - return id; - }); - }); + return storage.get(importer.Setting.MACHINE_ID).then(id => { + if (id) { + return id; + } + id = importer.generateId(); + return storage.set(importer.Setting.MACHINE_ID, id).then(() => { + return id; + }); + }); }; /** @@ -357,10 +350,9 @@ * machines history file. */ importer.getHistoryFilename = () => { - return importer.getMachineId().then( - machineId => { - return machineId + '-import-history.log'; - }); + return importer.getMachineId().then(machineId => { + return machineId + '-import-history.log'; + }); }; /** @@ -369,10 +361,9 @@ * machines debug log file. */ importer.getDebugLogFilename = logId => { - return importer.getMachineId().then( - machineId => { - return machineId + '-import-debug-' + logId + '.log'; - }); + return importer.getMachineId().then(machineId => { + return machineId + '-import-debug-' + logId + '.log'; + }); }; /** @@ -391,11 +382,11 @@ */ importer.getUnownedHistoryFiles_ = machineId => { const historyFiles = []; - return importer.ChromeSyncFilesystem.getRoot() - .then( - /** @param {!DirectoryEntry} root */ - root => { - return importer.listEntries_( + return importer.ChromeSyncFilesystem.getRoot().then( + /** @param {!DirectoryEntry} root */ + root => { + return importer + .listEntries_( root, /** @param {Entry} entry */ entry => { @@ -405,11 +396,10 @@ historyFiles.push(/** @type {!FileEntry} */ (entry)); } }) - .then( - () => { - return historyFiles; - }); - }); + .then(() => { + return historyFiles; + }); + }); }; /** @@ -428,16 +418,18 @@ * the current (*this*) machine. List will always have at least one entry. */ importer.getHistoryFiles = () => { - return Promise.all([ - importer.getOrCreateHistoryFile(), - importer.getMachineId().then(importer.getUnownedHistoryFiles_) - ]).then( - /** @param {!Array<!FileEntry|!Array<!FileEntry>>} entries */ - entries => { - const historyFiles = entries[1]; - historyFiles.unshift(entries[0]); - return historyFiles; - }); + return Promise + .all([ + importer.getOrCreateHistoryFile(), + importer.getMachineId().then(importer.getUnownedHistoryFiles_) + ]) + .then( + /** @param {!Array<!FileEntry|!Array<!FileEntry>>} entries */ + entries => { + const historyFiles = entries[1]; + historyFiles.unshift(entries[0]); + return historyFiles; + }); }; /** @@ -449,26 +441,25 @@ * @private */ importer.listEntries_ = (directory, callback) => { - return new Promise( - (resolve, reject) => { - const reader = directory.createReader(); + return new Promise((resolve, reject) => { + const reader = directory.createReader(); - const readEntries = () => { - reader.readEntries ( - /** @param {!Array<!Entry>} entries */ - entries => { - if (entries.length === 0) { - resolve(undefined); - return; - } - entries.forEach(callback); - readEntries(); - }, - reject); - }; + const readEntries = () => { + reader.readEntries( + /** @param {!Array<!Entry>} entries */ + entries => { + if (entries.length === 0) { + resolve(undefined); + return; + } + entries.forEach(callback); + readEntries(); + }, + reject); + }; - readEntries(); - }); + readEntries(); + }); }; /** @@ -489,11 +480,10 @@ this.reject_; /** @private {!Promise<T>} */ - this.promise_ = new Promise( - (resolve, reject) => { - this.resolve_ = resolve; - this.reject_ = reject; - }); + this.promise_ = new Promise((resolve, reject) => { + this.resolve_ = resolve; + this.reject_ = reject; + }); const settler = () => { this.settled_ = true; @@ -539,17 +529,10 @@ * @return {!Promise<!DirectoryEntry>} */ importer.demandChildDirectory = (parent, name) => { - return new Promise( - (resolve, reject) => { - parent.getDirectory( - name, - { - create: true, - exclusive: false - }, - resolve, - reject); - }); + return new Promise((resolve, reject) => { + parent.getDirectory( + name, {create: true, exclusive: false}, resolve, reject); + }); }; /** @@ -663,18 +646,17 @@ * @private */ importer.ChromeSyncFilesystem.getFileSystem_ = () => { - return new Promise( - (resolve, reject) => { - chrome.syncFileSystem.requestFileSystem( - /** @param {FileSystem} filesystem */ - filesystem => { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError.message); - } else { - resolve(/** @type {!FileSystem} */ (filesystem)); - } - }); - }); + return new Promise((resolve, reject) => { + chrome.syncFileSystem.requestFileSystem( + /** @param {FileSystem} filesystem */ + filesystem => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError.message); + } else { + resolve(/** @type {!FileSystem} */ (filesystem)); + } + }); + }); }; /** @@ -683,19 +665,17 @@ * @return {!Promise<!DirectoryEntry>} */ importer.ChromeSyncFilesystem.getRoot = () => { - return new Promise( - (resolve, reject) => { - importer.ChromeSyncFilesystem.getFileSystem_() - .then( - /** @param {FileSystem} filesystem */ - filesystem => { - if (!filesystem.root) { - reject('Unable to access ChromeSyncFilesystem root'); - } - resolve( - /** @type {!DirectoryEntry} */ (filesystem.root)); - }); - }); + return new Promise((resolve, reject) => { + importer.ChromeSyncFilesystem.getFileSystem_().then( + /** @param {FileSystem} filesystem */ + filesystem => { + if (!filesystem.root) { + reject('Unable to access ChromeSyncFilesystem root'); + } + resolve( + /** @type {!DirectoryEntry} */ (filesystem.root)); + }); + }); }; /** @@ -705,29 +685,22 @@ * @return {!Promise<!FileEntry>} */ importer.ChromeSyncFilesystem.getOrCreateFileEntry = fileNamePromise => { - const promise = importer.ChromeSyncFilesystem.getRoot() - .then( - /** - * @param {!DirectoryEntry} directory - * @return {!Promise<!FileEntry>} - */ - directory => { - return fileNamePromise.then( - /** @param {string} fileName */ - fileName => { - return new Promise( - (resolve, reject) => { - directory.getFile( - fileName, - { - create: true, - exclusive: false - }, - resolve, - reject); - }); - }); - }); + const promise = importer.ChromeSyncFilesystem.getRoot().then( + /** + * @param {!DirectoryEntry} directory + * @return {!Promise<!FileEntry>} + */ + directory => { + return fileNamePromise.then( + /** @param {string} fileName */ + fileName => { + return new Promise((resolve, reject) => { + directory.getFile( + fileName, {create: true, exclusive: false}, resolve, + reject); + }); + }); + }); return /** @type {!Promise<!FileEntry>} */ (promise); }; @@ -797,7 +770,6 @@ const prefix = '(' + context + ') '; return error => { - let message = prefix + 'Caught error in promise chain.'; // Append error info, if provided, then output the error. if (error) { @@ -807,7 +779,7 @@ // Output a stack, if provided. if (error && error.stack) { - this.write_('STACK', prefix + error.stack); + this.write_('STACK', prefix + error.stack); } }; }; @@ -841,14 +813,13 @@ const blob = new Blob( ['[' + type + ' @ ' + new Date().toString() + '] ' + line + '\n'], {type: 'text/plain; charset=UTF-8'}); - return new Promise( - (resolve, reject) => { - writer.onwriteend = resolve; - writer.onerror = reject; + return new Promise((resolve, reject) => { + writer.onwriteend = resolve; + writer.onerror = reject; - writer.seek(writer.length); - writer.write(blob); - }); + writer.seek(writer.length); + writer.write(blob); + }); }; /** @private {importer.Logger} */ @@ -861,14 +832,12 @@ */ importer.getLogger = () => { if (!importer.logger_) { - const nextLogId = importer.getNextDebugLogId_(); /** @return {!Promise} */ const rotator = () => { return importer.rotateLogs( - nextLogId, - importer.ChromeSyncFilesystem.getOrCreateFileEntry); + nextLogId, importer.ChromeSyncFilesystem.getOrCreateFileEntry); }; // This is a sligtly odd arrangement in service of two goals. @@ -917,17 +886,14 @@ /** @return {!Promise} */ const rememberLogId = () => { - return storage.set( - importer.Setting.LAST_KNOWN_LOG_ID, - nextLogId); + return storage.set(importer.Setting.LAST_KNOWN_LOG_ID, nextLogId); }; return storage.get(importer.Setting.LAST_KNOWN_LOG_ID) .then( /** @param {number} lastKnownLogId */ lastKnownLogId => { - if (nextLogId === lastKnownLogId || - lastKnownLogId === undefined) { + if (nextLogId === lastKnownLogId || lastKnownLogId === undefined) { return Promise.resolve(); } @@ -942,8 +908,8 @@ return new Promise(entry.remove.bind(entry)); }); }) - .then(rememberLogId) - .catch(rememberLogId); + .then(rememberLogId) + .catch(rememberLogId); }; /** @@ -961,20 +927,17 @@ * @return {!Promise} Resolves when operation is complete */ importer.ChromeLocalStorage.prototype.set = (key, value) => { - return new Promise( - (resolve, reject) => { - const values = {}; - values[key] = value; - chrome.storage.local.set( - values, - () => { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError); - } else { - resolve(undefined); - } - }); - }); + return new Promise((resolve, reject) => { + const values = {}; + values[key] = value; + chrome.storage.local.set(values, () => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else { + resolve(undefined); + } + }); + }); }; /** @@ -985,21 +948,20 @@ * @template T */ importer.ChromeLocalStorage.prototype.get = (key, opt_default) => { - return new Promise( - (resolve, reject) => { - chrome.storage.local.get( - key, - /** @param {Object<?>} values */ - values => { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError); - } else if (key in values) { - resolve(values[key]); - } else { - resolve(opt_default); - } - }); - }); + return new Promise((resolve, reject) => { + chrome.storage.local.get( + key, + /** @param {Object<?>} values */ + values => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else if (key in values) { + resolve(values[key]); + } else { + resolve(opt_default); + } + }); + }); }; /** @private @const {!importer.ChromeLocalStorage} */
diff --git a/ui/file_manager/file_manager/common/js/importer_common_unittest.js b/ui/file_manager/file_manager/common/js/importer_common_unittest.js index e99c5274..1181318 100644 --- a/ui/file_manager/file_manager/common/js/importer_common_unittest.js +++ b/ui/file_manager/file_manager/common/js/importer_common_unittest.js
@@ -34,13 +34,9 @@ importer.setupTestLogger(); cameraVolume = MockVolumeManager.createMockVolumeInfo( - VolumeManagerCommon.VolumeType.MTP, - 'camera-fs', - 'Some Camera'); + VolumeManagerCommon.VolumeType.MTP, 'camera-fs', 'Some Camera'); sdVolume = MockVolumeManager.createMockVolumeInfo( - VolumeManagerCommon.VolumeType.REMOVABLE, - 'sd-fs', - 'Some SD Card'); + VolumeManagerCommon.VolumeType.REMOVABLE, 'sd-fs', 'Some SD Card'); volumeManager = new MockVolumeManager(); volumeManager.volumeInfoList.add(cameraVolume); volumeManager.volumeInfoList.add(sdVolume); @@ -74,8 +70,7 @@ } function testIsMediaDirectory() { - ['/DCIM', '/DCIM/', '/dcim', '/dcim/', '/MP_ROOT/' ].forEach( - assertIsMediaDir); + ['/DCIM', '/DCIM/', '/dcim', '/dcim/', '/MP_ROOT/'].forEach(assertIsMediaDir); ['/blabbity/DCIM', '/blabbity/dcim', '/blabbity-blab'].forEach( assertIsNotMediaDir); } @@ -84,11 +79,10 @@ const resolver = new importer.Resolver(); assertFalse(resolver.settled); resolver.resolve(1); - resolver.promise.then( - value => { - assertTrue(resolver.settled); - assertEquals(1, value); - }); + resolver.promise.then(value => { + assertTrue(resolver.settled); + assertEquals(1, value); + }); reportPromise(resolver.promise, callback); } @@ -97,25 +91,20 @@ const resolver = new importer.Resolver(); assertFalse(resolver.settled); resolver.reject('ouch'); - resolver.promise - .then(callback.bind(null, true)) - .catch( - error => { - assertTrue(resolver.settled); - assertEquals('ouch', error); - callback(false); - }); + resolver.promise.then(callback.bind(null, true)).catch(error => { + assertTrue(resolver.settled); + assertEquals('ouch', error); + callback(false); + }); } function testGetMachineId_Persisted(callback) { - const promise = importer.getMachineId().then( - firstMachineId => { - assertTrue(100000 <= firstMachineId <= 9999999); - importer.getMachineId().then( - secondMachineId => { - assertEquals(firstMachineId, secondMachineId); - }); - }); + const promise = importer.getMachineId().then(firstMachineId => { + assertTrue(100000 <= firstMachineId <= 9999999); + importer.getMachineId().then(secondMachineId => { + assertEquals(firstMachineId, secondMachineId); + }); + }); reportPromise(promise, callback); } @@ -126,50 +115,48 @@ } function testPhotosApp_ImportEnabled(callback) { - const promise = importer.handlePhotosAppMessage(true).then( - () => { - return importer.isPhotosAppImportEnabled().then(assertTrue); - }); + const promise = importer.handlePhotosAppMessage(true).then(() => { + return importer.isPhotosAppImportEnabled().then(assertTrue); + }); reportPromise(promise, callback); } function testPhotosApp_ImportDisabled(callback) { - const promise = importer.handlePhotosAppMessage(false).then( - () => { - return importer.isPhotosAppImportEnabled().then(assertFalse); - }); + const promise = importer.handlePhotosAppMessage(false).then(() => { + return importer.isPhotosAppImportEnabled().then(assertFalse); + }); reportPromise(promise, callback); } function testHistoryFilename(callback) { - const promise = importer.getHistoryFilename().then( - firstName => { - assertTrue(!!firstName && firstName.length > 10); - importer.getHistoryFilename().then( - secondName => { - assertEquals(firstName, secondName); - }); - }); + const promise = importer.getHistoryFilename().then(firstName => { + assertTrue(!!firstName && firstName.length > 10); + importer.getHistoryFilename().then(secondName => { + assertEquals(firstName, secondName); + }); + }); reportPromise(promise, callback); } function testLocalStorageWrapper(callback) { const storage = new importer.ChromeLocalStorage(); - const promise = Promise.all([ - storage.set('lamb', 'chop'), - storage.set('isPoodle', true), - storage.set('age of grandma', 103) - ]).then( - () => { - return Promise.all([ - storage.get('lamb').then(assertEquals.bind(null, 'chop')), - storage.get('isPoodle').then(assertEquals.bind(null, true)), - storage.get('age of grandma').then(assertEquals.bind(null, 103)) - ]); - }); + const promise = + Promise + .all([ + storage.set('lamb', 'chop'), + storage.set('isPoodle', true), + storage.set('age of grandma', 103), + ]) + .then(() => { + return Promise.all([ + storage.get('lamb').then(assertEquals.bind(null, 'chop')), + storage.get('isPoodle').then(assertEquals.bind(null, true)), + storage.get('age of grandma').then(assertEquals.bind(null, 103)) + ]); + }); reportPromise(promise, callback); } @@ -177,33 +164,32 @@ function testRotateLogs(callback) { let fileName; const fileFactory = namePromise => { - return namePromise.then( - name => { - fileName = name; - return Promise.resolve(driveFileEntry); - }); + return namePromise.then(name => { + fileName = name; + return Promise.resolve(driveFileEntry); + }); }; const nextLogId = 0; const lastLogId = 1; - const promise = importer.ChromeLocalStorage.getInstance() - .set(importer.Setting.LAST_KNOWN_LOG_ID, lastLogId) - .then( - () => { + const promise = + importer.ChromeLocalStorage.getInstance() + .set(importer.Setting.LAST_KNOWN_LOG_ID, lastLogId) + .then(() => { // Should delete the log with the nextLogId. return importer.rotateLogs(nextLogId, fileFactory); }) - .then( - () => { + .then(() => { assertTrue(fileName !== undefined); // Verify the *active* log is deleted. - assertEquals(0, fileName.search(/[0-9]{6}-import-debug-0.log/), + assertEquals( + 0, fileName.search(/[0-9]{6}-import-debug-0.log/), 'Filename (' + fileName + ') does not match next pattern.'); driveFileEntry.asMock().assertRemoved(); return importer.ChromeLocalStorage.getInstance() - .get(importer.Setting.LAST_KNOWN_LOG_ID) - .then(assertEquals.bind(null, nextLogId)); + .get(importer.Setting.LAST_KNOWN_LOG_ID) + .then(assertEquals.bind(null, nextLogId)); }); reportPromise(promise, callback); @@ -218,13 +204,11 @@ return Promise.resolve(); }; - const promise = - importer.rotateLogs(nextLogId, fileFactory) - .then(() => { - return importer.ChromeLocalStorage.getInstance() - .get(importer.Setting.LAST_KNOWN_LOG_ID) - .then(assertEquals.bind(null, nextLogId)); - }); + const promise = importer.rotateLogs(nextLogId, fileFactory).then(() => { + return importer.ChromeLocalStorage.getInstance() + .get(importer.Setting.LAST_KNOWN_LOG_ID) + .then(assertEquals.bind(null, nextLogId)); + }); reportPromise(promise, callback); } @@ -235,22 +219,25 @@ const deflated = importer.deflateAppUrl(url); // Just verify that the string starts with our secret sauce marker... - assertEquals('$', deflated.substring(0, 1), + assertEquals( + '$', deflated.substring(0, 1), 'Deflated URLs must beging with the deflation marker.'); // And that it is shorter than the original... - assertTrue(deflated.length < url.length, + assertTrue( + deflated.length < url.length, 'Deflated URLs must be shorter than the original.'); // And finally that we can reconstitute the original. - assertEquals(url, importer.inflateAppUrl(deflated), + assertEquals( + url, importer.inflateAppUrl(deflated), 'Deflated then inflated URLs must match original URL.'); } function testHasMediaDirectory(callback) { const dir = createDirectoryEntry(sdVolume, '/DCIM'); const promise = importer.hasMediaDirectory(sdVolume.fileSystem.root) - .then(assertTrue.bind(null)); + .then(assertTrue.bind(null)); reportPromise(promise, callback); }
diff --git a/ui/file_manager/file_manager/common/js/mock_entry.js b/ui/file_manager/file_manager/common/js/mock_entry.js index eddd517..593b472 100644 --- a/ui/file_manager/file_manager/common/js/mock_entry.js +++ b/ui/file_manager/file_manager/common/js/mock_entry.js
@@ -92,8 +92,7 @@ if (path.indexOf(parentPath) === 0 && path !== parentPath) { const nextSeparator = path.indexOf('/', parentPath.length); // Add immediate children files and directories... - if (nextSeparator === -1 || - nextSeparator === path.length - 1) { + if (nextSeparator === -1 || nextSeparator === path.length - 1) { children.push(this.entries[path]); } }
diff --git a/ui/file_manager/file_manager/common/js/progress_center_common.js b/ui/file_manager/file_manager/common/js/progress_center_common.js index 712dd896..615f6a48 100644 --- a/ui/file_manager/file_manager/common/js/progress_center_common.js +++ b/ui/file_manager/file_manager/common/js/progress_center_common.js
@@ -163,9 +163,9 @@ * @return {boolean} True if the item can be canceled. */ get cancelable() { - return !!(this.state == ProgressItemState.PROGRESSING && - this.cancelCallback && - this.single); + return !!( + this.state == ProgressItemState.PROGRESSING && this.cancelCallback && + this.single); } };
diff --git a/ui/file_manager/file_manager/common/js/test_importer_common.js b/ui/file_manager/file_manager/common/js/test_importer_common.js index 2d39cf6..9a514ce 100644 --- a/ui/file_manager/file_manager/common/js/test_importer_common.js +++ b/ui/file_manager/file_manager/common/js/test_importer_common.js
@@ -60,7 +60,8 @@ /** @override */ importer.TestLogger.prototype.catcher = function(context) { return error => { - this.error('Caught promise error. Context: ' + context + + this.error( + 'Caught promise error. Context: ' + context + ' Error: ' + error.message); if (!this.quiet_) { console.error(error.stack);
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index 10b60c0..5cac3462 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -102,9 +102,12 @@ util.htmlEscape = str => { return str.replace(/[<>&]/g, entity => { switch (entity) { - case '<': return '<'; - case '>': return '>'; - case '&': return '&'; + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; } }); }; @@ -116,9 +119,12 @@ util.htmlUnescape = str => { return str.replace(/&(lt|gt|amp);/g, entity => { switch (entity) { - case '<': return '<'; - case '>': return '>'; - case '&': return '&'; + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; } }); }; @@ -142,22 +148,24 @@ // a new entry may be create on background. However, there is no way not to // overwrite the existing file, unfortunately. The risk should be low, // assuming the unsafe period is very short. - (entry.isFile ? parent.getFile : parent.getDirectory).call( - parent, newName, {create: false}, - entry => { - // The entry with the name already exists. - errorCallback(util.createDOMError(util.FileError.PATH_EXISTS_ERR)); - }, - error => { - if (error.name != util.FileError.NOT_FOUND_ERR) { - // Unexpected error is found. - errorCallback(error); - return; - } + (entry.isFile ? parent.getFile : parent.getDirectory) + .call( + parent, newName, {create: false}, + entry => { + // The entry with the name already exists. + errorCallback( + util.createDOMError(util.FileError.PATH_EXISTS_ERR)); + }, + error => { + if (error.name != util.FileError.NOT_FOUND_ERR) { + // Unexpected error is found. + errorCallback(error); + return; + } - // No existing entry is found. - entry.moveTo(parent, newName, successCallback, errorCallback); - }); + // No existing entry is found. + entry.moveTo(parent, newName, successCallback, errorCallback); + }); }, errorCallback); }; @@ -180,17 +188,16 @@ // a) If we get PATH_EXISTS_ERR, a directory exists. // b) If we get TYPE_MISMATCH_ERR, a file exists. return strf( - (entry.isFile && error.name == - util.FileError.PATH_EXISTS_ERR) || - (!entry.isFile && error.name == - util.FileError.TYPE_MISMATCH_ERR) ? + (entry.isFile && error.name == util.FileError.PATH_EXISTS_ERR) || + (!entry.isFile && + error.name == util.FileError.TYPE_MISMATCH_ERR) ? 'FILE_ALREADY_EXISTS' : 'DIRECTORY_ALREADY_EXISTS', newName); } - return strf('ERROR_RENAMING', entry.name, - util.getFileErrorString(error.name)); + return strf( + 'ERROR_RENAMING', entry.name, util.getFileErrorString(error.name)); }; /** @@ -216,20 +223,24 @@ */ util.bytesToString = bytes => { // Translation identifiers for size units. - const UNITS = ['SIZE_BYTES', - 'SIZE_KB', - 'SIZE_MB', - 'SIZE_GB', - 'SIZE_TB', - 'SIZE_PB']; + const UNITS = [ + 'SIZE_BYTES', + 'SIZE_KB', + 'SIZE_MB', + 'SIZE_GB', + 'SIZE_TB', + 'SIZE_PB', + ]; // Minimum values for the units above. - const STEPS = [0, - Math.pow(2, 10), - Math.pow(2, 20), - Math.pow(2, 30), - Math.pow(2, 40), - Math.pow(2, 50)]; + const STEPS = [ + 0, + Math.pow(2, 10), + Math.pow(2, 20), + Math.pow(2, 30), + Math.pow(2, 40), + Math.pow(2, 50), + ]; const str = (n, u) => { return strf(u, n.toLocaleString()); @@ -272,10 +283,8 @@ * @return {string} Modifiers. */ util.getKeyModifiers = event => { - return (event.ctrlKey ? 'Ctrl-' : '') + - (event.altKey ? 'Alt-' : '') + - (event.shiftKey ? 'Shift-' : '') + - (event.metaKey ? 'Meta-' : ''); + return (event.ctrlKey ? 'Ctrl-' : '') + (event.altKey ? 'Alt-' : '') + + (event.shiftKey ? 'Shift-' : '') + (event.metaKey ? 'Meta-' : ''); }; /** @@ -294,10 +303,10 @@ */ util.applyTransform = (element, transform) => { // The order of rotate and scale matters. - element.style.transform = - transform ? 'rotate(' + transform.rotate90 * 90 + 'deg)' + - 'scaleX(' + transform.scaleX + ') ' + - 'scaleY(' + transform.scaleY + ') ' : + element.style.transform = transform ? + 'rotate(' + transform.rotate90 * 90 + 'deg)' + + 'scaleX(' + transform.scaleX + ') ' + + 'scaleY(' + transform.scaleY + ') ' : ''; }; @@ -308,10 +317,12 @@ */ util.extractFilePath = url => { const match = - /^filesystem:[\w-]*:\/\/[\w]*\/(external|persistent|temporary)(\/.*)$/. - exec(url); + /^filesystem:[\w-]*:\/\/[\w]*\/(external|persistent|temporary)(\/.*)$/ + .exec(url); const path = match && match[2]; - if (!path) return null; + if (!path) { + return null; + } return decodeURIComponent(path); }; @@ -413,8 +424,9 @@ if (appWindow) { return appWindow.isFullscreen(); } else { - console.error('App window not passed. Unable to check status of ' + - 'the full screen mode.'); + console.error( + 'App window not passed. Unable to check status of the full screen ' + + 'mode.'); return false; } }; @@ -725,8 +737,8 @@ * Collator for sorting. * @type {Intl.Collator} */ -util.collator = new Intl.Collator( - [], {usage: 'sort', numeric: true, sensitivity: 'base'}); +util.collator = + new Intl.Collator([], {usage: 'sort', numeric: true, sensitivity: 'base'}); /** * Compare by name. The 2 entries must be in same directory. @@ -809,18 +821,15 @@ * parent of {@code entry}. */ util.isChildEntry = (entry, directory) => { - return new Promise( - (resolve, reject) => { - if (!entry || !directory) { - resolve(false); - } + return new Promise((resolve, reject) => { + if (!entry || !directory) { + resolve(false); + } - entry.getParent( - parent => { - resolve(util.isSameEntry(parent, directory)); - }, - reject); - }); + entry.getParent(parent => { + resolve(util.isSameEntry(parent, directory)); + }, reject); + }); }; /** @@ -948,14 +957,16 @@ */ util.URLsToEntries = (urls, opt_callback) => { const promises = urls.map(url => { - return new Promise(window.webkitResolveLocalFileSystemURL.bind(null, url)). - then(entry => { - return {entry: entry}; - }, failureUrl => { - // Not an error. Possibly, the file is not accessible anymore. - console.warn('Failed to resolve the file with url: ' + url + '.'); - return {failureUrl: url}; - }); + return new Promise(window.webkitResolveLocalFileSystemURL.bind(null, url)) + .then( + entry => { + return {entry: entry}; + }, + failureUrl => { + // Not an error. Possibly, the file is not accessible anymore. + console.warn('Failed to resolve the file with url: ' + url + '.'); + return {failureUrl: url}; + }); }); const resultPromise = Promise.all(promises).then(results => { const entries = []; @@ -970,20 +981,22 @@ } return { entries: entries, - failureUrls: failureUrls + failureUrls: failureUrls, }; }); // Invoke the callback. If opt_callback is specified, resultPromise is still // returned and fulfilled with a result. if (opt_callback) { - resultPromise.then(result => { - opt_callback(result.entries, result.failureUrls); - }).catch(error => { - console.error( - 'util.URLsToEntries is failed.', - error.stack ? error.stack : error); - }); + resultPromise + .then(result => { + opt_callback(result.entries, result.failureUrls); + }) + .catch(error => { + console.error( + 'util.URLsToEntries is failed.', + error.stack ? error.stack : error); + }); } return resultPromise; @@ -998,8 +1011,7 @@ * {!Entry} if possible, else rejects. */ util.urlToEntry = url => { - return new Promise( - window.webkitResolveLocalFileSystemURL.bind(null, url)); + return new Promise(window.webkitResolveLocalFileSystemURL.bind(null, url)); }; /** @@ -1313,8 +1325,7 @@ */ util.timeoutPromise = (promise, ms, opt_message) => { return Promise.race([ - promise, - util.delay(ms).then(() => { + promise, util.delay(ms).then(() => { throw new Error(opt_message || 'Operation timed out.'); }) ]); @@ -1335,60 +1346,56 @@ * If 0 is specified, only the rootEntry will be read. If -1 is specified * or opt_maxDepth is unspecified, the depth of recursion is unlimited. */ -util.readEntriesRecursively = ( - rootEntry, - entriesCallback, - successCallback, - errorCallback, - shouldStop, - opt_maxDepth -) => { - let numRunningTasks = 0; - let error = null; - const maxDepth = opt_maxDepth === undefined ? -1 : opt_maxDepth; - const maybeRunCallback = () => { - if (numRunningTasks === 0) { - if (shouldStop()) { - errorCallback(util.createDOMError(util.FileError.ABORT_ERR)); - } else if (error) { - errorCallback(error); - } else { - successCallback(); - } - } - }; - const processEntry = (entry, depth) => { - const onError = fileError => { - if (!error) { - error = fileError; - } - numRunningTasks--; - maybeRunCallback(); - }; - const onSuccess = entries => { - if (shouldStop() || error || entries.length === 0) { - numRunningTasks--; - maybeRunCallback(); - return; - } - entriesCallback(entries); - for (let i = 0; i < entries.length; i++) { - if (entries[i].isDirectory && (maxDepth === -1 || depth < maxDepth)) { - processEntry(entries[i], depth + 1); +util.readEntriesRecursively = + (rootEntry, entriesCallback, successCallback, errorCallback, shouldStop, + opt_maxDepth) => { + let numRunningTasks = 0; + let error = null; + const maxDepth = opt_maxDepth === undefined ? -1 : opt_maxDepth; + const maybeRunCallback = () => { + if (numRunningTasks === 0) { + if (shouldStop()) { + errorCallback(util.createDOMError(util.FileError.ABORT_ERR)); + } else if (error) { + errorCallback(error); + } else { + successCallback(); + } } - } - // Read remaining entries. - reader.readEntries(onSuccess, onError); + }; + const processEntry = (entry, depth) => { + const onError = fileError => { + if (!error) { + error = fileError; + } + numRunningTasks--; + maybeRunCallback(); + }; + const onSuccess = entries => { + if (shouldStop() || error || entries.length === 0) { + numRunningTasks--; + maybeRunCallback(); + return; + } + entriesCallback(entries); + for (let i = 0; i < entries.length; i++) { + if (entries[i].isDirectory && + (maxDepth === -1 || depth < maxDepth)) { + processEntry(entries[i], depth + 1); + } + } + // Read remaining entries. + reader.readEntries(onSuccess, onError); + }; + + numRunningTasks++; + const reader = entry.createReader(); + reader.readEntries(onSuccess, onError); + }; + + processEntry(rootEntry, 0); }; - numRunningTasks++; - const reader = entry.createReader(); - reader.readEntries(onSuccess, onError); - }; - - processEntry(rootEntry, 0); -}; - /** * Do not remove or modify. Used in vm.CrostiniFiles tast tests at: * https://chromium.googlesource.com/chromiumos/platform/tast-tests
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index eb8fffd..e870a095 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -423,9 +423,7 @@ } #sort-button > .icon { - background-image: -webkit-image-set( - url(../images/files/ui/sorting_white.png) 1x, - url(../images/files/ui/2x/sorting_white.png) 2x); + background-image: url(../images/files/ui/sorting_white.svg); } body.check-select #sort-button {
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js index e4b3faf..3193f24 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
@@ -182,7 +182,7 @@ * @private */ audioUrl_: function(contentUrl, type) { - return this.isAudio_(type) ? contentUrl : ""; + return this.isAudio_(type) ? contentUrl : ''; }, /**
diff --git a/ui/file_manager/file_manager/foreground/elements/files_safe_media_webview_content.js b/ui/file_manager/file_manager/foreground/elements/files_safe_media_webview_content.js index 7d393de..108ad78 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_safe_media_webview_content.js +++ b/ui/file_manager/file_manager/foreground/elements/files_safe_media_webview_content.js
@@ -3,7 +3,8 @@ // found in the LICENSE file. window.onload = () => { - const FILES_APP_ORIGIN = 'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj'; + const FILES_APP_ORIGIN = + 'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj'; let messageSource; const content = document.querySelector('#content'); @@ -19,12 +20,14 @@ case 'html': content.textContent = ''; contentChanged(null); - fetch(event.data.src).then((response) => { - return response.text(); - }).then((text) => { - content.textContent = text; - contentChanged(text); - }); + fetch(event.data.src) + .then((response) => { + return response.text(); + }) + .then((text) => { + content.textContent = text; + contentChanged(text); + }); break; case 'audio': case 'video': @@ -35,13 +38,15 @@ content.remove(); content.onload = (e) => contentChanged(e.target.src); content.src = event.data.src; - content.decode().then(() => { - content.removeAttribute('generic-thumbnail'); - document.body.appendChild(content); - }).catch(() => { - content.setAttribute('generic-thumbnail', 'image'); - document.body.appendChild(content); - }); + content.decode() + .then(() => { + content.removeAttribute('generic-thumbnail'); + document.body.appendChild(content); + }) + .catch(() => { + content.setAttribute('generic-thumbnail', 'image'); + document.body.appendChild(content); + }); break; default: content.onload = (e) => contentChanged(e.target.src);
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.png b/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.png deleted file mode 100644 index b636c16..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.svg b/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.svg new file mode 100644 index 0000000..ad251ae --- /dev/null +++ b/ui/file_manager/file_manager/foreground/images/files/ui/sorting_white.svg
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g> + <rect x="0" y="0" width="20" height="20"></rect> + <path d="M7.5078125,12.9492188 L3.91210938,12.9492188 L3.22851562,15 L1.04785156,15 L4.75292969,5.046875 L6.65332031,5.046875 L10.3789062,15 L8.19824219,15 L7.5078125,12.9492188 Z M4.46582031,11.2880859 L6.95410156,11.2880859 L5.703125,7.5625 L4.46582031,11.2880859 Z" fill="#FFFFFF" fill-rule="nonzero"></path> + <polygon fill="#FFFFFF" fill-rule="nonzero" points="13.5625 13.3525391 18.5800781 13.3525391 18.5800781 15 10.9990234 15 10.9990234 13.796875 15.9208984 6.70800781 11.0058594 6.70800781 11.0058594 5.046875 18.4707031 5.046875 18.4707031 6.22265625"></polygon> + <polygon fill="#FFFFFF" points="12 3 8 3 10 1"></polygon> + <polygon fill="#FFFFFF" points="8 17 12 17 10 19"></polygon> + </g> + </g> +</svg>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/byte_reader.js b/ui/file_manager/file_manager/foreground/js/metadata/byte_reader.js index a151fd9..5cae08a 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/byte_reader.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/byte_reader.js
@@ -113,7 +113,9 @@ for (let i = 0; i < size; ++i) { const code = dataView.getUint8(pos + i); - if (code == 0) break; + if (code == 0) { + break; + } codes.push(code); } @@ -133,27 +135,30 @@ * @param {number=} opt_end Maximum position to read from. * @return {string} Read string. */ -ByteReader.readNullTerminatedStringUTF16 = (dataView, pos, bom, size, opt_end) => { - ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); +ByteReader.readNullTerminatedStringUTF16 = + (dataView, pos, bom, size, opt_end) => { + ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); - let littleEndian = false; - let start = 0; + let littleEndian = false; + let start = 0; - if (bom) { - littleEndian = (dataView.getUint8(pos) == 0xFF); - start = 2; - } + if (bom) { + littleEndian = (dataView.getUint8(pos) == 0xFF); + start = 2; + } - const codes = []; + const codes = []; - for (let i = start; i < size; i += 2) { - const code = dataView.getUint16(pos + i, littleEndian); - if (code == 0) break; - codes.push(code); - } + for (let i = start; i < size; i += 2) { + const code = dataView.getUint16(pos + i, littleEndian); + if (code == 0) { + break; + } + codes.push(code); + } - return String.fromCharCode.apply(null, codes); -}; + return String.fromCharCode.apply(null, codes); + }; /** * @const @@ -161,8 +166,8 @@ * @private */ ByteReader.base64Alphabet_ = - ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'). - split(''); + ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') + .split(''); /** * Read as a sequence of bytes, returning them as a single base64 encoded @@ -235,10 +240,10 @@ // Two bytes is enough to identify the mime type. const prefixToMime = { - '\x89P' : 'png', - '\xFF\xD8' : 'jpeg', - 'BM' : 'bmp', - 'GI' : 'gif' + '\x89P': 'png', + '\xFF\xD8': 'jpeg', + 'BM': 'bmp', + 'GI': 'gif', }; const prefix = ByteReader.readString(dataView, pos, 2, opt_end); @@ -376,10 +381,8 @@ * @return {string} Null-terminated string value. */ ByteReader.prototype.readNullTerminatedString = function(size, opt_end) { - const rv = ByteReader.readNullTerminatedString(this.view_, - this.pos_, - size, - opt_end); + const rv = + ByteReader.readNullTerminatedString(this.view_, this.pos_, size, opt_end); this.pos_ += rv.length; if (rv.length < size) { @@ -403,8 +406,8 @@ * @param {number=} opt_end Maximum position to read from. * @return {string} Read string. */ -ByteReader.prototype.readNullTerminatedStringUTF16 = - function(bom, size, opt_end) { +ByteReader.prototype.readNullTerminatedStringUTF16 = function( + bom, size, opt_end) { const rv = ByteReader.readNullTerminatedStringUTF16( this.view_, this.pos_, bom, size, opt_end); @@ -436,8 +439,7 @@ * @param {function(new:Array<*>)=} opt_arrayConstructor Array constructor. * @return {Array<*>} Array of bytes. */ -ByteReader.prototype.readSlice = function(size, opt_end, - opt_arrayConstructor) { +ByteReader.prototype.readSlice = function(size, opt_end, opt_arrayConstructor) { this.validateRead(size, opt_end); const arrayConstructor = opt_arrayConstructor || Uint8Array;
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js index da10929..ad86d9b 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
@@ -10,9 +10,7 @@ * @struct */ function ContentMetadataProvider(opt_messagePort) { - MetadataProvider.call( - this, - ContentMetadataProvider.PROPERTY_NAMES); + MetadataProvider.call(this, ContentMetadataProvider.PROPERTY_NAMES); /** * Pass all URLs to the metadata reader until we have a correct filter. @@ -107,8 +105,9 @@ const promises = []; for (let i = 0; i < requests.length; i++) { promises.push(new Promise(((request, fulfill) => { - this.getImpl_(request.entry, request.names, fulfill); - }).bind(null, requests[i]))); + this.getImpl_( + request.entry, request.names, fulfill); + }).bind(null, requests[i]))); } return Promise.all(promises); }; @@ -123,9 +122,13 @@ */ ContentMetadataProvider.prototype.getImpl_ = function(entry, names, callback) { if (entry.isDirectory) { - setTimeout(callback.bind(null, this.createError_(entry.toURL(), - 'get', - 'we don\'t generate thumbnails for directory')), 0); + setTimeout( + callback.bind( + null, + this.createError_( + entry.toURL(), 'get', + 'we don\'t generate thumbnails for directory')), + 0); return; } // TODO(ryoh): mediaGalleries API does not handle @@ -155,37 +158,39 @@ * the entry. * @private */ -ContentMetadataProvider.prototype.getFromMediaGalleries_ = - function(entry, names) { +ContentMetadataProvider.prototype.getFromMediaGalleries_ = function( + entry, names) { const self = this; return new Promise((resolve, reject) => { - entry.file(blob => { - let metadataType = 'mimeTypeOnly'; - if (names.indexOf('mediaArtist') !== -1 || - names.indexOf('mediaTitle') !== -1 || - names.indexOf('mediaTrack') !== -1 || - names.indexOf('mediaYearRecorded') !== -1) { - metadataType = 'mimeTypeAndTags'; - } - if (names.indexOf('contentThumbnailUrl') !== -1) { - metadataType = 'all'; - } - chrome.mediaGalleries.getMetadata(blob, {metadataType: metadataType}, - metadata => { - if (chrome.runtime.lastError) { - resolve(self.createError_(entry.toURL(), - 'resolving metadata', - chrome.runtime.lastError.toString())); - } else { - self.convertMediaMetadataToMetadataItem_(entry, metadata) - .then(resolve, reject); - } - }); - }, err => { - resolve(self.createError_(entry.toURL(), - 'loading file entry', - 'failed to open file entry')); - }); + entry.file( + blob => { + let metadataType = 'mimeTypeOnly'; + if (names.indexOf('mediaArtist') !== -1 || + names.indexOf('mediaTitle') !== -1 || + names.indexOf('mediaTrack') !== -1 || + names.indexOf('mediaYearRecorded') !== -1) { + metadataType = 'mimeTypeAndTags'; + } + if (names.indexOf('contentThumbnailUrl') !== -1) { + metadataType = 'all'; + } + chrome.mediaGalleries.getMetadata( + blob, {metadataType: metadataType}, metadata => { + if (chrome.runtime.lastError) { + resolve(self.createError_( + entry.toURL(), 'resolving metadata', + chrome.runtime.lastError.toString())); + } else { + self.convertMediaMetadataToMetadataItem_(entry, metadata) + .then(resolve, reject); + } + }); + }, + err => { + resolve(self.createError_( + entry.toURL(), 'loading file entry', + 'failed to open file entry')); + }); }); }; @@ -203,18 +208,14 @@ case 'result': this.onResult_( data.arguments[0], - data.arguments[1] ? - ContentMetadataProvider.convertContentMetadata(data.arguments[1]) : - new MetadataItem()); + data.arguments[1] ? ContentMetadataProvider.convertContentMetadata( + data.arguments[1]) : + new MetadataItem()); break; case 'error': const error = this.createError_( - data.arguments[0], - data.arguments[1], - data.arguments[2]); - this.onResult_( - data.arguments[0], - error); + data.arguments[0], data.arguments[1], data.arguments[2]); + this.onResult_(data.arguments[0], error); break; case 'log': this.onLog_(data.arguments[0]); @@ -278,8 +279,9 @@ function(entry, metadata) { return new Promise((resolve, reject) => { if (!metadata) { - resolve(this.createError_(entry.toURL(), 'Reading a thumbnail image', - "Failed to parse metadata")); + resolve(this.createError_( + entry.toURL(), 'Reading a thumbnail image', + 'Failed to parse metadata')); return; } const item = new MetadataItem(); @@ -341,7 +343,8 @@ resolve(item); }; reader.onerror = e => { - resolve(this.createError_(entry.toURL(), 'Reading a thumbnail image', + resolve(this.createError_( + entry.toURL(), 'Reading a thumbnail image', reader.error.toString())); }; reader.readAsDataURL(metadata.attachedImages[0]); @@ -359,15 +362,17 @@ * @return {!MetadataItem} Error metadata * @private */ -ContentMetadataProvider.prototype.createError_ = (url, step, errorDescription) => { - // For error case, fill all fields with error object. - const error = new ContentMetadataProvider.Error(url, step, errorDescription); - const item = new MetadataItem(); - item.contentImageTransformError = error; - item.contentThumbnailTransformError = error; - item.contentThumbnailUrlError = error; - return item; -}; +ContentMetadataProvider.prototype.createError_ = + (url, step, errorDescription) => { + // For error case, fill all fields with error object. + const error = + new ContentMetadataProvider.Error(url, step, errorDescription); + const item = new MetadataItem(); + item.contentImageTransformError = error; + item.contentThumbnailTransformError = error; + item.contentThumbnailUrlError = error; + return item; + }; /** * Content metadata provider error.
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js index 4ff0999..26b71a68 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
@@ -23,7 +23,7 @@ } }; } - +// clang-format off const entryA = makeFileEntryFromDataURL( 'image.jpg', 'data:image/jpeg;base64,/9j/4QDcRXhpZgAATU0AKgAAAAgABwESAAMAAAABAA' + @@ -55,10 +55,9 @@ 'd+5n14+zU1Ld23GijHnlPvg6u7gNEKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAP/Z'); +// clang-format on -const entryB = makeFileEntryFromDataURL( - 'empty.jpg', - 'data:image/jpeg;base64,'); +const entryB = makeFileEntryFromDataURL('empty.jpg', 'data:image/jpeg;base64,'); function testExternalMetadataProviderBasic(callback) { // Mocking SharedWorker's port. @@ -83,20 +82,24 @@ // TODO(ryoh): chrome.mediaGalleries API is not available in unit tests. const provider = new ContentMetadataProvider(port); - reportPromise(provider.get([ - new MetadataRequest( - entryA, ['contentThumbnailUrl', 'contentThumbnailTransform']), - new MetadataRequest( - entryB, ['contentThumbnailUrl', 'contentThumbnailTransform']), - ]).then(results => { - assertEquals(2, results.length); - assertEquals(entryA.url + ',url', results[0].contentThumbnailUrl); - assertEquals( - entryA.url + ',transform', - results[0].contentThumbnailTransform); - assertEquals(entryB.url + ',url', results[1].contentThumbnailUrl); - assertEquals( - entryB.url + ',transform', - results[1].contentThumbnailTransform); - }), callback); + reportPromise( + provider + .get([ + new MetadataRequest( + entryA, ['contentThumbnailUrl', 'contentThumbnailTransform']), + new MetadataRequest( + entryB, ['contentThumbnailUrl', 'contentThumbnailTransform']), + ]) + .then(results => { + assertEquals(2, results.length); + assertEquals(entryA.url + ',url', results[0].contentThumbnailUrl); + assertEquals( + entryA.url + ',transform', + results[0].contentThumbnailTransform); + assertEquals(entryB.url + ',url', results[1].contentThumbnailUrl); + assertEquals( + entryB.url + ',transform', + results[1].contentThumbnailTransform); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js index 13b5fb7..16dca93f 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser.js
@@ -29,7 +29,9 @@ ImageParser.call(this, parent, 'jpeg', /\.jpe?g$/i); } -ExifParser.prototype = {__proto__: ImageParser.prototype}; +ExifParser.prototype = { + __proto__: ImageParser.prototype +}; /** * @param {File} file File object to parse. @@ -98,7 +100,8 @@ * @param {number=} opt_bytes */ const reread = (opt_offset, opt_bytes) => { - self.requestSlice(file, callback, errorCallback, metadata, + self.requestSlice( + file, callback, errorCallback, metadata, filePos + br.tell() + (opt_offset || 0), opt_bytes); }; @@ -131,7 +134,7 @@ this.parseExifSection(metadata, buf, br); } else if (ExifParser.isSOF_(mark)) { // The most reliable size information is encoded in the SOF section. - br.seek(1, ByteReader.SEEK_CUR); // Skip the precision byte. + br.seek(1, ByteReader.SEEK_CUR); // Skip the precision byte. const height = br.readScalar(2); const width = br.readScalar(2); ExifParser.setImageSize(metadata, width, height); @@ -154,7 +157,9 @@ ExifParser.isSOF_ = mark => { // There are 13 variants of SOF fragment format distinguished by the last // hex digit of the mark, but the part we want is always the same. - if ((mark & ~0xF) !== Exif.Mark.SOF) return false; + if ((mark & ~0xF) !== Exif.Mark.SOF) { + return false; + } // If the last digit is 4, 8 or 12 it is not really a SOF. const type = mark & 0xF; @@ -197,7 +202,7 @@ metadata.littleEndian = (order === Exif.Align.LITTLE); metadata.ifd = { image: {}, - thumbnail: {} + thumbnail: {}, }; let directoryOffset = br.readScalar(4); @@ -242,8 +247,8 @@ Exif.Tag.JPG_THUMB_LENGTH in metadata.ifd.thumbnail) { this.vlog('Read thumbnail image.'); br.seek(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_OFFSET].value); - metadata.thumbnailURL = br.readImage( - metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_LENGTH].value); + metadata.thumbnailURL = + br.readImage(metadata.ifd.thumbnail[Exif.Tag.JPG_THUMB_LENGTH].value); } else { this.vlog('Image has EXIF data, but no JPG thumbnail.'); } @@ -315,9 +320,10 @@ try { unsafeRead(size, opt_readFunction, opt_signed); } catch (ex) { - self.log('error reading tag 0x' + tag.id.toString(16) + '/' + - tag.format + ', size ' + tag.componentCount + '*' + size + ' ' + - (ex.stack || '<no stack>') + ': ' + ex); + self.log( + 'error reading tag 0x' + tag.id.toString(16) + '/' + tag.format + + ', size ' + tag.componentCount + '*' + size + ' ' + + (ex.stack || '<no stack>') + ': ' + ex); tag.value = null; } } @@ -329,8 +335,8 @@ */ function unsafeRead(size, opt_readFunction, opt_signed) { const readFunction = opt_readFunction || (size => { - return br.readScalar(size, opt_signed); - }); + return br.readScalar(size, opt_signed); + }); const totalSize = tag.componentCount * size; if (totalSize < 1) { @@ -367,12 +373,12 @@ } switch (tag.format) { - case 1: // Byte - case 7: // Undefined + case 1: // Byte + case 7: // Undefined safeRead(1); break; - case 2: // String + case 2: // String safeRead(1); if (tag.componentCount === 0) { tag.value = ''; @@ -385,39 +391,41 @@ this.validateAndFixStringTag_(tag); break; - case 3: // Short + case 3: // Short safeRead(2); break; - case 4: // Long + case 4: // Long safeRead(4); break; - case 9: // Signed Long + case 9: // Signed Long safeRead(4, undefined, true); break; - case 5: // Rational + case 5: // Rational safeRead(8, () => { return [br.readScalar(4), br.readScalar(4)]; }); break; - case 10: // Signed Rational + case 10: // Signed Rational safeRead(8, () => { return [br.readScalar(4, true), br.readScalar(4, true)]; }); break; - default: // ??? - this.vlog('Unknown tag format 0x' + Number(tag.id).toString(16) + - ': ' + tag.format); + default: // ??? + this.vlog( + 'Unknown tag format 0x' + Number(tag.id).toString(16) + ': ' + + tag.format); safeRead(4); break; } - this.vlog('Read tag: 0x' + tag.id.toString(16) + '/' + tag.format + ': ' + - tag.value); + this.vlog( + 'Read tag: 0x' + tag.id.toString(16) + '/' + tag.format + ': ' + + tag.value); }; /** @@ -426,12 +434,13 @@ * @private */ ExifParser.prototype.validateAndFixStringTag_ = function(tag) { - if (tag.format === 2) { // string + if (tag.format === 2) { // string // String should end with null character. if (tag.value.charAt(tag.value.length - 1) !== '\0') { tag.value += '\0'; tag.componentCount = tag.value.length; - this.vlog('Invalid format: 0x' + tag.id.toString(16) + '/' + tag.format + + this.vlog( + 'Invalid format: 0x' + tag.id.toString(16) + '/' + tag.format + ': Did not end with null character. Null character is appended.'); } }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js index 19d1dd29..8fd5385 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
@@ -48,14 +48,14 @@ assertTrue(tag.componentCount > 4); let byteWriter = new ByteWriter(bytes.buffer, 0); - byteWriter.writeScalar(1, 2); // Number of fields. + byteWriter.writeScalar(1, 2); // Number of fields. byteWriter.writeScalar(tag.id, 2); byteWriter.writeScalar(tag.format, 2); byteWriter.writeScalar(tag.componentCount, 4); byteWriter.forward(tag.id, 4); - byteWriter.writeScalar(0, 4); // Offset to next IFD. + byteWriter.writeScalar(0, 4); // Offset to next IFD. byteWriter.resolveOffset(tag.id); const string = /** @type {string} */ (tag.value);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider.js index 84d8f7f..8f89ae17 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider.js
@@ -89,99 +89,101 @@ */ ExternalMetadataProvider.prototype.convertResults_ = (requests, nameMap, propertiesList) => { - const results = []; - for (let i = 0; i < propertiesList.length; i++) { - const prop = propertiesList[i]; - const item = new MetadataItem(); - if (prop.alternateUrl !== undefined || nameMap['alternateUrl']) { - item.alternateUrl = prop.alternateUrl; - } - if (prop.availableOffline !== undefined || nameMap['availableOffline']) { - item.availableOffline = prop.availableOffline; - } - if (prop.availableWhenMetered !== undefined || - nameMap['availableWhenMetered']) { - item.availableWhenMetered = prop.availableWhenMetered; - } - if (prop.contentMimeType !== undefined || nameMap['contentMimeType']) { - item.contentMimeType = prop.contentMimeType || ''; - } - if (prop.croppedThumbnailUrl !== undefined || - nameMap['croppedThumbnailUrl']) { - item.croppedThumbnailUrl = prop.croppedThumbnailUrl; - } - if (prop.customIconUrl !== undefined || nameMap['customIconUrl']) { - item.customIconUrl = prop.customIconUrl || ''; - } - if (prop.dirty !== undefined || nameMap['dirty']) { - item.dirty = prop.dirty; - } - if (prop.externalFileUrl !== undefined || nameMap['externalFileUrl']) { - item.externalFileUrl = prop.externalFileUrl; - } - if (prop.hosted !== undefined || nameMap['hosted']) { - item.hosted = prop.hosted; - } - if (prop.imageHeight !== undefined || nameMap['imageHeight']) { - item.imageHeight = prop.imageHeight; - } - if (prop.imageRotation !== undefined || nameMap['imageRotation']) { - item.imageRotation = prop.imageRotation; - } - if (prop.imageWidth !== undefined || nameMap['imageWidth']) { - item.imageWidth = prop.imageWidth; - } - if (prop.modificationTime !== undefined || nameMap['modificationTime']) { - item.modificationTime = new Date(prop.modificationTime); - } - if (prop.modificationByMeTime !== undefined || - nameMap['modificationByMeTime']) { - item.modificationByMeTime = new Date(prop.modificationByMeTime); - } - if (prop.pinned !== undefined || nameMap['pinned']) { - item.pinned = prop.pinned; - } - if (prop.present !== undefined || nameMap['present']) { - item.present = prop.present; - } - if (prop.shared !== undefined || nameMap['shared']) { - item.shared = prop.shared; - } - if (prop.sharedWithMe !== undefined || nameMap['sharedWithMe']) { - item.sharedWithMe = prop.sharedWithMe; - } - if (prop.size !== undefined || nameMap['size']) { - item.size = requests[i].entry.isFile ? (prop.size || 0) : -1; - } - if (prop.thumbnailUrl !== undefined || nameMap['thumbnailUrl']) { - item.thumbnailUrl = prop.thumbnailUrl; - } - if (prop.canCopy !== undefined || nameMap['canCopy']) { - item.canCopy = prop.canCopy; - } - if (prop.canDelete !== undefined || nameMap['canDelete']) { - item.canDelete = prop.canDelete; - } - if (prop.canRename !== undefined || nameMap['canRename']) { - item.canRename = prop.canRename; - } - if (prop.canAddChildren !== undefined || nameMap['canAddChildren']) { - item.canAddChildren = prop.canAddChildren; - } - if (prop.canShare !== undefined || nameMap['canShare']) { - item.canShare = prop.canShare; - } - if (prop.isMachineRoot !== undefined || nameMap['isMachineRoot']) { - item.isMachineRoot = prop.isMachineRoot; - } - if (prop.isExternalMedia !== undefined || nameMap['isExternalMedia']) { - item.isExternalMedia = prop.isExternalMedia; - } - if (prop.isArbitrarySyncFolder !== undefined || - nameMap['isArbitrarySyncFolder']) { - item.isArbitrarySyncFolder = prop.isArbitrarySyncFolder; - } - results.push(item); - } - return results; -}; + const results = []; + for (let i = 0; i < propertiesList.length; i++) { + const prop = propertiesList[i]; + const item = new MetadataItem(); + if (prop.alternateUrl !== undefined || nameMap['alternateUrl']) { + item.alternateUrl = prop.alternateUrl; + } + if (prop.availableOffline !== undefined || + nameMap['availableOffline']) { + item.availableOffline = prop.availableOffline; + } + if (prop.availableWhenMetered !== undefined || + nameMap['availableWhenMetered']) { + item.availableWhenMetered = prop.availableWhenMetered; + } + if (prop.contentMimeType !== undefined || nameMap['contentMimeType']) { + item.contentMimeType = prop.contentMimeType || ''; + } + if (prop.croppedThumbnailUrl !== undefined || + nameMap['croppedThumbnailUrl']) { + item.croppedThumbnailUrl = prop.croppedThumbnailUrl; + } + if (prop.customIconUrl !== undefined || nameMap['customIconUrl']) { + item.customIconUrl = prop.customIconUrl || ''; + } + if (prop.dirty !== undefined || nameMap['dirty']) { + item.dirty = prop.dirty; + } + if (prop.externalFileUrl !== undefined || nameMap['externalFileUrl']) { + item.externalFileUrl = prop.externalFileUrl; + } + if (prop.hosted !== undefined || nameMap['hosted']) { + item.hosted = prop.hosted; + } + if (prop.imageHeight !== undefined || nameMap['imageHeight']) { + item.imageHeight = prop.imageHeight; + } + if (prop.imageRotation !== undefined || nameMap['imageRotation']) { + item.imageRotation = prop.imageRotation; + } + if (prop.imageWidth !== undefined || nameMap['imageWidth']) { + item.imageWidth = prop.imageWidth; + } + if (prop.modificationTime !== undefined || + nameMap['modificationTime']) { + item.modificationTime = new Date(prop.modificationTime); + } + if (prop.modificationByMeTime !== undefined || + nameMap['modificationByMeTime']) { + item.modificationByMeTime = new Date(prop.modificationByMeTime); + } + if (prop.pinned !== undefined || nameMap['pinned']) { + item.pinned = prop.pinned; + } + if (prop.present !== undefined || nameMap['present']) { + item.present = prop.present; + } + if (prop.shared !== undefined || nameMap['shared']) { + item.shared = prop.shared; + } + if (prop.sharedWithMe !== undefined || nameMap['sharedWithMe']) { + item.sharedWithMe = prop.sharedWithMe; + } + if (prop.size !== undefined || nameMap['size']) { + item.size = requests[i].entry.isFile ? (prop.size || 0) : -1; + } + if (prop.thumbnailUrl !== undefined || nameMap['thumbnailUrl']) { + item.thumbnailUrl = prop.thumbnailUrl; + } + if (prop.canCopy !== undefined || nameMap['canCopy']) { + item.canCopy = prop.canCopy; + } + if (prop.canDelete !== undefined || nameMap['canDelete']) { + item.canDelete = prop.canDelete; + } + if (prop.canRename !== undefined || nameMap['canRename']) { + item.canRename = prop.canRename; + } + if (prop.canAddChildren !== undefined || nameMap['canAddChildren']) { + item.canAddChildren = prop.canAddChildren; + } + if (prop.canShare !== undefined || nameMap['canShare']) { + item.canShare = prop.canShare; + } + if (prop.isMachineRoot !== undefined || nameMap['isMachineRoot']) { + item.isMachineRoot = prop.isMachineRoot; + } + if (prop.isExternalMedia !== undefined || nameMap['isExternalMedia']) { + item.isExternalMedia = prop.isExternalMedia; + } + if (prop.isArbitrarySyncFolder !== undefined || + nameMap['isArbitrarySyncFolder']) { + item.isArbitrarySyncFolder = prop.isArbitrarySyncFolder; + } + results.push(item); + } + return results; + };
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js index c6dbfb38..283808e 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.js
@@ -61,24 +61,28 @@ installMockChrome(mockChrome); const provider = new ExternalMetadataProvider(); - reportPromise(provider.get([ - new MetadataRequest(entryA, ['modificationTime', 'size']), - new MetadataRequest(entryB, ['modificationTime', 'size']), - ]).then(results => { - assertEquals(2, results.length); - assertEquals( - new Date(2015, 0, 1).toString(), - results[0].modificationTime.toString()); - assertEquals(1024, results[0].size); - assertEquals(true, results[0].isMachineRoot); - assertEquals(true, results[0].isExternalMedia); - assertEquals(true, results[0].isArbitrarySyncFolder); - assertEquals( - new Date(2015, 1, 2).toString(), - results[1].modificationTime.toString()); - assertEquals(2048, results[1].size); - assertEquals(false, results[1].isMachineRoot); - assertEquals(false, results[1].isExternalMedia); - assertEquals(false, results[1].isArbitrarySyncFolder); - }), callback); + reportPromise( + provider + .get([ + new MetadataRequest(entryA, ['modificationTime', 'size']), + new MetadataRequest(entryB, ['modificationTime', 'size']), + ]) + .then(results => { + assertEquals(2, results.length); + assertEquals( + new Date(2015, 0, 1).toString(), + results[0].modificationTime.toString()); + assertEquals(1024, results[0].size); + assertEquals(true, results[0].isMachineRoot); + assertEquals(true, results[0].isExternalMedia); + assertEquals(true, results[0].isArbitrarySyncFolder); + assertEquals( + new Date(2015, 1, 2).toString(), + results[1].modificationTime.toString()); + assertEquals(2048, results[1].size); + assertEquals(false, results[1].isMachineRoot); + assertEquals(false, results[1].isExternalMedia); + assertEquals(false, results[1].isArbitrarySyncFolder); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider.js index 88bc9f61..b4e07324 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider.js
@@ -16,9 +16,8 @@ /** * @const {!Array<string>} */ -FileSystemMetadataProvider.PROPERTY_NAMES = [ - 'modificationTime', 'size', 'present', 'availableOffline' -]; +FileSystemMetadataProvider.PROPERTY_NAMES = + ['modificationTime', 'size', 'present', 'availableOffline']; FileSystemMetadataProvider.prototype.__proto__ = MetadataProvider.prototype; @@ -31,20 +30,24 @@ } return Promise.all(requests.map(request => { return new Promise((fulfill, reject) => { - request.entry.getMetadata(fulfill, reject); - }).then(result => { - const item = new MetadataItem(); - item.modificationTime = result.modificationTime; - item.size = request.entry.isDirectory ? -1 : result.size; - item.present = true; - item.availableOffline = true; - return item; - }, error => { - // Can't use console.error because some tests hit this line and - // console.error causes them to fail because of JSErrorCount. This error - // is an acceptable condition. - console.warn('getMetadata failure for: ' + request.entry.toURL(), error); - return new MetadataItem(); - }); + request.entry.getMetadata(fulfill, reject); + }) + .then( + result => { + const item = new MetadataItem(); + item.modificationTime = result.modificationTime; + item.size = request.entry.isDirectory ? -1 : result.size; + item.present = true; + item.availableOffline = true; + return item; + }, + error => { + // Can't use console.error because some tests hit this line and + // console.error causes them to fail because of JSErrorCount. This + // error is an acceptable condition. + console.warn( + 'getMetadata failure for: ' + request.entry.toURL(), error); + return new MetadataItem(); + }); })); };
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js index 212bfbc..8850fb6a 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
@@ -5,59 +5,64 @@ /** @const {!Entry} */ const entryA = /** @type {!Entry} */ ({ toURL: function() { - return "filesystem://A"; + return 'filesystem://A'; }, getMetadata: function(fulfill, reject) { - Promise.resolve({modificationTime: new Date(2015, 1, 1), size: 1024}).then( - fulfill, reject); + Promise.resolve({modificationTime: new Date(2015, 1, 1), size: 1024}) + .then(fulfill, reject); } }); /** @const {!Entry} */ const entryB = /** @type {!Entry} */ ({ toURL: function() { - return "filesystem://B"; + return 'filesystem://B'; }, getMetadata: function(fulfill, reject) { - Promise.resolve({modificationTime: new Date(2015, 2, 2), size: 2048}).then( - fulfill, reject); + Promise.resolve({modificationTime: new Date(2015, 2, 2), size: 2048}) + .then(fulfill, reject); } }); function testFileSystemMetadataProviderBasic(callback) { const provider = new FileSystemMetadataProvider(); const names = [ - 'modificationTime', 'size', 'contentMimeType', 'present', - 'availableOffline']; - reportPromise(provider.get([ - new MetadataRequest(entryA, names), - new MetadataRequest(entryB, names) - ]).then(results => { - assertEquals(2, results.length); - assertEquals( - new Date(2015, 1, 1).toString(), - results[0].modificationTime.toString()); - assertEquals(1024, results[0].size); - assertTrue(!!results[0].present); - assertTrue(!!results[0].availableOffline); - assertEquals( - new Date(2015, 2, 2).toString(), - results[1].modificationTime.toString()); - assertEquals(2048, results[1].size); - assertTrue(!!results[1].present); - assertTrue(!!results[1].availableOffline); - }), callback); + 'modificationTime', 'size', 'contentMimeType', 'present', 'availableOffline' + ]; + reportPromise( + provider + .get([ + new MetadataRequest(entryA, names), + new MetadataRequest(entryB, names) + ]) + .then(results => { + assertEquals(2, results.length); + assertEquals( + new Date(2015, 1, 1).toString(), + results[0].modificationTime.toString()); + assertEquals(1024, results[0].size); + assertTrue(!!results[0].present); + assertTrue(!!results[0].availableOffline); + assertEquals( + new Date(2015, 2, 2).toString(), + results[1].modificationTime.toString()); + assertEquals(2048, results[1].size); + assertTrue(!!results[1].present); + assertTrue(!!results[1].availableOffline); + }), + callback); } function testFileSystemMetadataProviderPartialRequest(callback) { const provider = new FileSystemMetadataProvider(); - reportPromise(provider.get( - [new MetadataRequest(entryA, ['modificationTime', 'size'])]).then( - results => { - assertEquals(1, results.length); - assertEquals( - new Date(2015, 1, 1).toString(), - results[0].modificationTime.toString()); - assertEquals(1024, results[0].size); - }), callback); + reportPromise( + provider.get([new MetadataRequest(entryA, ['modificationTime', 'size'])]) + .then(results => { + assertEquals(1, results.length); + assertEquals( + new Date(2015, 1, 1).toString(), + results[0].modificationTime.toString()); + assertEquals(1024, results[0].size); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/function_parallel.js b/ui/file_manager/file_manager/foreground/js/metadata/function_parallel.js index 8ddc267..2a0b7d4 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/function_parallel.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/function_parallel.js
@@ -62,8 +62,9 @@ * @param {...} var_args Arguments to be passed to all the steps. */ FunctionParallel.prototype.start = function(var_args) { - this.logger.vlog('Starting [' + this.steps_.length + '] parallel tasks ' + - 'with ' + arguments.length + ' argument(s)'); + this.logger.vlog( + 'Starting [' + this.steps_.length + '] parallel tasks ' + + 'with ' + arguments.length + ' argument(s)'); if (this.logger.verbose) { for (let j = 0; j < arguments.length; j++) { this.logger.vlog(arguments[j]);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js b/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js index 0d86b2f..98061efa 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js
@@ -55,8 +55,8 @@ * @private */ FunctionSequence.prototype.onError_ = function(err) { - this.logger.vlog('Failed step: ' + this.steps_[this.currentStepIdx_].name + - ': ' + err); + this.logger.vlog( + 'Failed step: ' + this.steps_[this.currentStepIdx_].name + ': ' + err); if (!this.failed_) { this.failed_ = true; this.failureCallback_(err); @@ -94,9 +94,9 @@ this.logger.vlog('Sequence ended'); this.callback_.apply(this, arguments); } else { - this.logger.vlog('Attempting to start step [' + - this.steps_[this.currentStepIdx_].name + - ']'); + this.logger.vlog( + 'Attempting to start step [' + this.steps_[this.currentStepIdx_].name + + ']'); try { this.steps_[this.currentStepIdx_].apply(this, arguments); } catch (e) {
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js index f9d7b7ad..089429d 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js
@@ -115,10 +115,8 @@ * @param {number} end Frame end position in reader. * @private */ -Id3Parser.prototype.readTextFrame_ = function(reader, - majorVersion, - frame, - end) { +Id3Parser.prototype.readTextFrame_ = function( + reader, majorVersion, frame, end) { frame.encoding = reader.readScalar(1, false, end); frame.value = this.readString_(reader, frame.encoding, end - reader.tell()); }; @@ -132,21 +130,14 @@ * @param {number} end Frame end position in reader. * @private */ -Id3Parser.prototype.readUserDefinedTextFrame_ = function(reader, - majorVersion, - frame, - end) { +Id3Parser.prototype.readUserDefinedTextFrame_ = function( + reader, majorVersion, frame, end) { frame.encoding = reader.readScalar(1, false, end); - frame.description = this.readString_( - reader, - frame.encoding, - end - reader.tell()); + frame.description = + this.readString_(reader, frame.encoding, end - reader.tell()); - frame.value = this.readString_( - reader, - frame.encoding, - end - reader.tell()); + frame.value = this.readString_(reader, frame.encoding, end - reader.tell()); }; /** @@ -160,9 +151,8 @@ frame.encoding = reader.readScalar(1, false, end); frame.format = reader.readNullTerminatedString(3, end - reader.tell()); frame.pictureType = reader.readScalar(1, false, end); - frame.description = this.readString_(reader, - frame.encoding, - end - reader.tell()); + frame.description = + this.readString_(reader, frame.encoding, end - reader.tell()); if (frame.format == '-->') { @@ -184,10 +174,8 @@ frame.encoding = reader.readScalar(1, false, end); frame.mime = reader.readNullTerminatedString(end - reader.tell()); frame.pictureType = reader.readScalar(1, false, end); - frame.description = this.readString_( - reader, - frame.encoding, - end - reader.tell()); + frame.description = + this.readString_(reader, frame.encoding, end - reader.tell()); if (frame.mime == '-->') { frame.imageUrl = reader.readNullTerminatedString(end - reader.tell()); @@ -245,17 +233,10 @@ if (Id3Parser.v2.HANDLERS[frame.name]) { Id3Parser.v2.HANDLERS[frame.name].call( - this, - reader, - majorVersion, - frame, - reader.tell() + frame.size); + this, reader, majorVersion, frame, reader.tell() + frame.size); } else if (frame.name.charAt(0) == 'T' || frame.name.charAt(0) == 'W') { this.readTextFrame_( - reader, - majorVersion, - frame, - reader.tell() + frame.size); + reader, majorVersion, frame, reader.tell() + frame.size); } reader.popSeek(); @@ -277,8 +258,7 @@ this.log('Starting id3 parser for ' + file.name); const id3v1Parser = new FunctionSequence( - 'id3v1parser', - [ + 'id3v1parser', [ /** * Reads last 128 bytes of file in bytebuffer, * which passes further. @@ -286,8 +266,8 @@ * @param {File} file File which bytes to read. */ function readTail(file) { - MetadataParser.readFileBytes(file, file.size - 128, file.size, - this.nextStep, this.onError); + MetadataParser.readFileBytes( + file, file.size - 128, file.size, this.nextStep, this.onError); }, /** @@ -324,16 +304,13 @@ this.nextStep(); } ], - this, - () => {}, - error => {}); + this, () => {}, error => {}); const id3v2Parser = new FunctionSequence( - 'id3v2parser', - [ + 'id3v2parser', [ function readHead(file) { - MetadataParser.readFileBytes(file, 0, 10, this.nextStep, - this.onError); + MetadataParser.readFileBytes( + file, 0, 10, this.nextStep, this.onError); }, /** @@ -351,8 +328,8 @@ id3v2.flags = reader.readScalar(1, false); id3v2.size = Id3Parser.readSynchSafe_(reader, 4); - MetadataParser.readFileBytes(file, 10, 10 + id3v2.size, - this.nextStep, this.onError); + MetadataParser.readFileBytes( + file, 10, 10 + id3v2.size, this.nextStep, this.onError); } else { this.finish(); } @@ -404,7 +381,7 @@ metadata.description = []; for (const key in id3v2) { - if (typeof(Id3Parser.v2.MAPPERS[key]) != 'undefined' && + if (typeof (Id3Parser.v2.MAPPERS[key]) != 'undefined' && id3v2[key].value.trim().length > 0) { metadata.description.push({ key: Id3Parser.v2.MAPPERS[key], @@ -433,23 +410,17 @@ metadata.description.sort((a, b) => { return Id3Parser.METADATA_ORDER.indexOf(a.key) - - Id3Parser.METADATA_ORDER.indexOf(b.key); + Id3Parser.METADATA_ORDER.indexOf(b.key); }); this.nextStep(); } ], - this, - () => {}, - error => {}); + this, () => {}, error => {}); const metadataParser = new FunctionParallel( - 'mp3metadataParser', - [id3v1Parser, id3v2Parser], - this, - () => { + 'mp3metadataParser', [id3v1Parser, id3v2Parser], this, () => { callback.call(null, metadata); - }, - onError); + }, onError); id3v1Parser.setCallback(metadataParser.nextStep); id3v2Parser.setCallback(metadataParser.nextStep); @@ -700,21 +671,21 @@ UTF_8: 3 }, HANDLERS: { - //User defined text information frame + // User defined text information frame TXX: Id3Parser.prototype.readUserDefinedTextFrame_, - //User defined URL link frame + // User defined URL link frame WXX: Id3Parser.prototype.readUserDefinedTextFrame_, - //User defined text information frame + // User defined text information frame TXXX: Id3Parser.prototype.readUserDefinedTextFrame_, - //User defined URL link frame + // User defined URL link frame WXXX: Id3Parser.prototype.readUserDefinedTextFrame_, - //User attached image + // User attached image PIC: Id3Parser.prototype.readPIC_, - //User attached image + // User attached image APIC: Id3Parser.prototype.readAPIC_ }, MAPPERS: {
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js index 067a568..62a6f07 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation.js
@@ -118,10 +118,8 @@ // |a c| |s_x 0 | |x| |a*s_x c*s_y| |x| // |b d| | 0 s_y| |y| = |b*s_x d*s_y| |y| return new ImageOrientation( - orientation.a * scaleX, - orientation.b * scaleX, - orientation.c * scaleY, - orientation.d * scaleY); + orientation.a * scaleX, orientation.b * scaleX, orientation.c * scaleY, + orientation.d * scaleY); }; /** @@ -136,7 +134,7 @@ const projectedY = this.b * imageWidth + this.d * imageHeight; return { width: Math.abs(projectedX), - height: Math.abs(projectedY) + height: Math.abs(projectedY), }; };
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js index 5eb900be6..7f306e6 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.js
@@ -23,12 +23,12 @@ const context = canvas.getContext('2d'); const imageData = context.createImageData(2, 1); imageData.data[0] = 255; // R - imageData.data[1] = 0; // G - imageData.data[2] = 0; // B + imageData.data[1] = 0; // G + imageData.data[2] = 0; // B imageData.data[3] = 100; // A - imageData.data[4] = 0; // R - imageData.data[5] = 0; // G - imageData.data[6] = 0; // B + imageData.data[4] = 0; // R + imageData.data[5] = 0; // G + imageData.data[6] = 0; // B imageData.data[7] = 100; // A context.putImageData(imageData, 0, 0); @@ -52,8 +52,8 @@ function testFromRotationAndScale() { const rotate270 = {scaleX: 1, scaleY: 1, rotate90: -1}; const rotate90 = {scaleX: 1, scaleY: 1, rotate90: 1}; - const flipX = {scaleX: -1, scaleY: 1, rotate90: 0 }; - const flipY = {scaleX: 1, scaleY: -1, rotate90: 0 }; + const flipX = {scaleX: -1, scaleY: 1, rotate90: 0}; + const flipY = {scaleX: 1, scaleY: -1, rotate90: 0}; const flipBoth = {scaleX: -1, scaleY: -1, rotate90: 0}; const rotate180 = {scaleX: 1, scaleY: 1, rotate90: 2}; const flipXAndRotate90 = {scaleX: -1, scaleY: 1, rotate90: 1}; @@ -67,26 +67,36 @@ | =====> | V e_y O----> e'_y = (1, 0)' = (c, d)' */ - assertImageOrientationEquals(new ImageOrientation(0, -1, 1, 0), + assertImageOrientationEquals( + new ImageOrientation(0, -1, 1, 0), ImageOrientation.fromRotationAndScale(rotate270), 'rotate270'); - assertImageOrientationEquals(new ImageOrientation(0, 1, -1, 0), + assertImageOrientationEquals( + new ImageOrientation(0, 1, -1, 0), ImageOrientation.fromRotationAndScale(rotate90), 'rotate90'); - assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, 1), + assertImageOrientationEquals( + new ImageOrientation(-1, 0, 0, 1), ImageOrientation.fromRotationAndScale(flipX), 'flipX'); - assertImageOrientationEquals(new ImageOrientation(1, 0, 0, -1), + assertImageOrientationEquals( + new ImageOrientation(1, 0, 0, -1), ImageOrientation.fromRotationAndScale(flipY), 'flipY'); - assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, -1), + assertImageOrientationEquals( + new ImageOrientation(-1, 0, 0, -1), ImageOrientation.fromRotationAndScale(flipBoth), 'flipBoth'); - assertImageOrientationEquals(new ImageOrientation(-1, 0, 0, -1), + assertImageOrientationEquals( + new ImageOrientation(-1, 0, 0, -1), ImageOrientation.fromRotationAndScale(rotate180), 'rotate180'); - assertImageOrientationEquals(new ImageOrientation(0, -1, -1, 0), + assertImageOrientationEquals( + new ImageOrientation(0, -1, -1, 0), ImageOrientation.fromRotationAndScale(flipXAndRotate90), 'flipXAndRotate90'); - assertImageOrientationEquals(new ImageOrientation(0, 1, 1, 0), + assertImageOrientationEquals( + new ImageOrientation(0, 1, 1, 0), ImageOrientation.fromRotationAndScale(flipYAndRotate90), 'flipYAndRotate90'); - assertTrue(ImageOrientation.fromRotationAndScale(flipBothAndRotate180) - .isIdentity(), 'flipBothAndRotate180'); - assertTrue(ImageOrientation.fromRotationAndScale(rotate1080).isIdentity(), + assertTrue( + ImageOrientation.fromRotationAndScale(flipBothAndRotate180).isIdentity(), + 'flipBothAndRotate180'); + assertTrue( + ImageOrientation.fromRotationAndScale(rotate1080).isIdentity(), 'rotate1080'); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_parsers.js b/ui/file_manager/file_manager/foreground/js/metadata/image_parsers.js index 87f9a66..1a3c1813 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/image_parsers.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/image_parsers.js
@@ -29,17 +29,14 @@ SimpleImageParser.prototype.parse = function( file, metadata, callback, errorCallback) { const self = this; - MetadataParser.readFileBytes( - file, 0, this.headerSize, - (file, br) => { - try { - self.parseHeader(metadata, br); - callback(metadata); - } catch (e) { - errorCallback(e.toString()); - } - }, - errorCallback); + MetadataParser.readFileBytes(file, 0, this.headerSize, (file, br) => { + try { + self.parseHeader(metadata, br); + callback(metadata); + } catch (e) { + errorCallback(e.toString()); + } + }, errorCallback); }; /** @@ -60,7 +57,9 @@ SimpleImageParser.call(this, parent, 'png', /\.png$/i, 24); } -PngParser.prototype = {__proto__: SimpleImageParser.prototype}; +PngParser.prototype = { + __proto__: SimpleImageParser.prototype +}; /** * @override @@ -96,7 +95,9 @@ SimpleImageParser.call(this, parent, 'bmp', /\.bmp$/i, 28); } -BmpParser.prototype = {__proto__: SimpleImageParser.prototype}; +BmpParser.prototype = { + __proto__: SimpleImageParser.prototype +}; /** * @override @@ -127,7 +128,9 @@ SimpleImageParser.call(this, parent, 'gif', /\.Gif$/i, 10); } -GifParser.prototype = {__proto__: SimpleImageParser.prototype}; +GifParser.prototype = { + __proto__: SimpleImageParser.prototype +}; /** * @override @@ -157,7 +160,9 @@ SimpleImageParser.call(this, parent, 'webp', /\.webp$/i, 30); } -WebpParser.prototype = {__proto__: SimpleImageParser.prototype}; +WebpParser.prototype = { + __proto__: SimpleImageParser.prototype +}; /** * @override @@ -183,8 +188,8 @@ br.seek(23); const lossySignature = br.readScalar(2) | (br.readScalar(1) << 16); if (lossySignature != 0x2a019d) { - throw new Error('Invalid VP8 lossy bitstream signature: ' + - lossySignature); + throw new Error( + 'Invalid VP8 lossy bitstream signature: ' + lossySignature); } var dimensionBits = br.readScalar(4); metadata.width = dimensionBits & 0x3fff; @@ -196,8 +201,8 @@ br.seek(20); const losslessSignature = br.readScalar(1); if (losslessSignature != 0x2f) { - throw new Error('Invalid VP8 lossless bitstream signature: ' + - losslessSignature); + throw new Error( + 'Invalid VP8 lossless bitstream signature: ' + losslessSignature); } var dimensionBits = br.readScalar(4); metadata.width = (dimensionBits & 0x3fff) + 1; @@ -229,7 +234,9 @@ SimpleImageParser.call(this, parent, 'ico', /\.ico$/i, 8); } -IcoParser.prototype = {__proto__: SimpleImageParser.prototype}; +IcoParser.prototype = { + __proto__: SimpleImageParser.prototype +}; /** * @override
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item.js index 9aab50a..05d1a99 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item.js
@@ -29,7 +29,7 @@ // Check if the property needs to be updated. if (this.properties_[name] && this.properties_[name].state !== - MetadataCacheItemPropertyState.INVALIDATED) { + MetadataCacheItemPropertyState.INVALIDATED) { continue; } loadRequested.push(name); @@ -62,7 +62,7 @@ */ MetadataCacheItem.prototype.storeProperties = function(requestId, typedObject) { let changed = false; - const object = /** @type {!Object} */(typedObject); + const object = /** @type {!Object} */ (typedObject); for (let name in object) { if (/.Error$/.test(name) && object[name]) { object[name.substr(0, name.length - 5)] = undefined; @@ -77,7 +77,7 @@ } if (requestId < this.properties_[name].requestId || this.properties_[name].state === - MetadataCacheItemPropertyState.FULFILLED) { + MetadataCacheItemPropertyState.FULFILLED) { continue; } changed = true; @@ -110,7 +110,7 @@ * @return {!MetadataItem} */ MetadataCacheItem.prototype.get = function(names) { - const result = /** @type {!Object} */(new MetadataItem()); + const result = /** @type {!Object} */ (new MetadataItem()); for (let i = 0; i < names.length; i++) { const name = names[i]; assert(!/Error$/.test(name)); @@ -119,7 +119,7 @@ result[name + 'Error'] = this.properties_[name].error; } } - return /** @type {!MetadataItem} */(result); + return /** @type {!MetadataItem} */ (result); }; /** @@ -148,7 +148,7 @@ for (let i = 0; i < names.length; i++) { if (!(this.properties_[names[i]] && this.properties_[names[i]].state === - MetadataCacheItemPropertyState.FULFILLED)) { + MetadataCacheItemPropertyState.FULFILLED)) { return false; } }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher.js index cf31374..55f0ef7 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher.js
@@ -188,7 +188,8 @@ * @param {string=} opt_stepName Step name. */ function onError(err, opt_stepName) { - self.error(fileURL, opt_stepName || steps[currentStep].name, err.toString(), + self.error( + fileURL, opt_stepName || steps[currentStep].name, err.toString(), metadata); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js index 8b99283..dadeafc 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
@@ -212,21 +212,27 @@ provider = /** @type {!ManualTestMetadataProvider} */ (model.getProvider()); provider.callback[0]([{propertyA: 'valueA1'}]); - reportPromise(promise.then(() => { - // 'propertyA' is cached here. - const promise1 = model.get([entryA], ['propertyA', 'propertyB']); - const promise2 = model.get([entryA], ['propertyC']); - // Returns propertyC. - provider = /** @type {!ManualTestMetadataProvider} */ (model.getProvider()); - provider.callback[2]([{propertyA: 'valueA2', propertyC: 'valueC'}]); - provider.callback[1]([{propertyB: 'valueB'}]); - return Promise.all([promise1, promise2]); - }).then(results => { - // The result should be cached value at the time when get was called. - assertEquals('valueA1', getProperty(results[0][0], 'propertyA')); - assertEquals('valueB', getProperty(results[0][0], 'propertyB')); - assertEquals('valueC', getProperty(results[1][0], 'propertyC')); - }), callback); + reportPromise( + promise + .then(() => { + // 'propertyA' is cached here. + const promise1 = model.get([entryA], ['propertyA', 'propertyB']); + const promise2 = model.get([entryA], ['propertyC']); + // Returns propertyC. + provider = /** @type {!ManualTestMetadataProvider} */ ( + model.getProvider()); + provider.callback[2]([{propertyA: 'valueA2', propertyC: 'valueC'}]); + provider.callback[1]([{propertyB: 'valueB'}]); + return Promise.all([promise1, promise2]); + }) + .then(results => { + // The result should be cached value at the time when get was + // called. + assertEquals('valueA1', getProperty(results[0][0], 'propertyA')); + assertEquals('valueB', getProperty(results[0][0], 'propertyB')); + assertEquals('valueC', getProperty(results[1][0], 'propertyC')); + }), + callback); } function testMetadataModelGetCache(callback) { @@ -237,12 +243,15 @@ const cache = model.getCache([entryA], ['property']); assertEquals(null, getProperty(cache[0], 'property')); - reportPromise(promise.then(() => { - const cache = model.getCache([entryA], ['property']); - provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); - assertEquals(1, provider.requestCount); - assertEquals('filesystem://A:property', getProperty(cache[0], 'property')); - }), callback); + reportPromise( + promise.then(() => { + const cache = model.getCache([entryA], ['property']); + provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + assertEquals( + 'filesystem://A:property', getProperty(cache[0], 'property')); + }), + callback); } function testMetadataModelUnknownProperty() {
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js index f9f4291..6de0e424 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_parser.js
@@ -47,10 +47,7 @@ * @return {Object} Metadata object with the minimal set of properties. */ MetadataParser.prototype.createDefaultMetadata = function() { - return { - type: this.type, - mimeType: this.mimeType - }; + return {type: this.type, mimeType: this.mimeType}; }; /** @@ -67,8 +64,10 @@ onError(event.type); }; fileReader.onloadend = () => { - callback(file, new ByteReader( - /** @type {ArrayBuffer} */ (fileReader.result))); + callback( + file, + new ByteReader( + /** @type {ArrayBuffer} */ (fileReader.result))); }; fileReader.readAsArrayBuffer(file.slice(begin, end)); }; @@ -87,4 +86,6 @@ this.mimeType = 'image/' + this.type; } -ImageParser.prototype = {__proto__: MetadataParser.prototype}; +ImageParser.prototype = { + __proto__: MetadataParser.prototype +};
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/mpeg_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/mpeg_parser.js index cb4696a..6d06258 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/mpeg_parser.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/mpeg_parser.js
@@ -13,7 +13,9 @@ this.mimeType = 'video/mpeg'; } -MpegParser.prototype = {__proto__: MetadataParser.prototype}; +MpegParser.prototype = { + __proto__: MetadataParser.prototype +}; /** * Size of the atom header. @@ -65,8 +67,12 @@ function findParentAtom(atom, name) { for (;;) { atom = atom.parent; - if (!atom) return null; - if (atom.name == name) return atom; + if (!atom) { + return null; + } + if (atom.name == name) { + return atom; + } } } @@ -110,10 +116,10 @@ // 'meta' atom can occur at one of the several places in the file structure. const parseMeta = { ilst: { - '©nam': { data: parseDataString.bind(null, 'title') }, - '©alb': { data: parseDataString.bind(null, 'album') }, - '©art': { data: parseDataString.bind(null, 'artist') }, - 'covr': { data: parseCovr } + '©nam': {data: parseDataString.bind(null, 'title')}, + '©alb': {data: parseDataString.bind(null, 'album')}, + '©art': {data: parseDataString.bind(null, 'artist')}, + 'covr': {data: parseCovr} }, versioned: true }; @@ -127,15 +133,13 @@ mdia: { hdlr: parseHdlr, minf: { - stbl: { - stsd: parseStsd - } - } + stbl: {stsd: parseStsd}, + }, }, meta: parseMeta }, udta: { - meta: parseMeta + meta: parseMeta, }, meta: parseMeta }, @@ -153,8 +157,9 @@ const rootParser = MpegParser.createRootParser(metadata); // Kick off the processing by reading the first atom's header. - this.requestRead(rootParser, file, 0, MpegParser.HEADER_SIZE, null, - onError, callback.bind(null, metadata)); + this.requestRead( + rootParser, file, 0, MpegParser.HEADER_SIZE, null, onError, + callback.bind(null, metadata)); }; /** @@ -180,9 +185,10 @@ } const start = atom.start - MpegParser.HEADER_SIZE; - this.vlog(path + ': ' + - '@' + (filePos + start) + ':' + (atom.end - start), - action); + this.vlog( + path + ': ' + + '@' + (filePos + start) + ':' + (atom.end - start), + action); } if (parser) { @@ -218,15 +224,13 @@ const name = MpegParser.readAtomName(br, parentAtom.end); this.applyParser( - parser[name], - br, - { start: offset + MpegParser.HEADER_SIZE, + parser[name], br, { + start: offset + MpegParser.HEADER_SIZE, end: offset + size, name: name, parent: parentAtom }, - filePos - ); + filePos); offset += size; } @@ -283,13 +287,9 @@ } // Process the top level atom. - if (name) { // name is null only the first time. + if (name) { // name is null only the first time. this.applyParser( - rootParser[name], - br, - {start: 0, end: atomEnd, name: name}, - filePos - ); + rootParser[name], br, {start: 0, end: atomEnd, name: name}, filePos); } filePos += bufLength; @@ -308,8 +308,8 @@ nextSize = MpegParser.HEADER_SIZE; } - this.requestRead(rootParser, file, filePos, nextSize, nextName, - onError, onSuccess); + this.requestRead( + rootParser, file, filePos, nextSize, nextName, onError, onSuccess); } else { // The previous read did not return the next atom header, EOF reached. this.vlog('EOF @' + filePos);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider.js index 1a800479..be8ac123 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider.js
@@ -12,15 +12,13 @@ * @struct */ function MultiMetadataProvider( - fileSystemMetadataProvider, - externalMetadataProvider, - contentMetadataProvider, - volumeManager) { + fileSystemMetadataProvider, externalMetadataProvider, + contentMetadataProvider, volumeManager) { MetadataProvider.call( this, - FileSystemMetadataProvider.PROPERTY_NAMES.concat( - ExternalMetadataProvider.PROPERTY_NAMES).concat( - ContentMetadataProvider.PROPERTY_NAMES)); + FileSystemMetadataProvider.PROPERTY_NAMES + .concat(ExternalMetadataProvider.PROPERTY_NAMES) + .concat(ContentMetadataProvider.PROPERTY_NAMES)); /** * @private {!FileSystemMetadataProvider} @@ -120,58 +118,67 @@ contentRequests, contentPropertyNames.concat(fallbackContentPropertyNames)); } + // We need to discard content requests when using a documents provider + // since the content sniffing code can't resolve the file path in the + // MediaGallery API. See crbug.com/942417 + if (volumeInfo && + volumeInfo.volumeType === + VolumeManagerCommon.VolumeType.DOCUMENTS_PROVIDER) { + contentRequests.length = 0; + } }); const get = (provider, inRequests) => { return provider.get(inRequests).then(results => { return { requests: inRequests, - results: results + results: results, }; }); }; - const fileSystemPromise = get( - this.fileSystemMetadataProvider_, fileSystemRequests); + const fileSystemPromise = + get(this.fileSystemMetadataProvider_, fileSystemRequests); const externalPromise = get(this.externalMetadataProvider_, externalRequests); const contentPromise = get(this.contentMetadataProvider_, contentRequests); - const fallbackContentPromise = externalPromise.then( - requestsAndResults => { - const requests = requestsAndResults.requests; - const results = requestsAndResults.results; - const dirtyMap = []; - for (let i = 0; i < results.length; i++) { - dirtyMap[requests[i].entry.toURL()] = results[i].present; - } - return get( - this.contentMetadataProvider_, - fallbackContentRequests.filter( - request => { - return dirtyMap[request.entry.toURL()]; - })); - }); + const fallbackContentPromise = externalPromise.then(requestsAndResults => { + const requests = requestsAndResults.requests; + const results = requestsAndResults.results; + const dirtyMap = []; + for (let i = 0; i < results.length; i++) { + dirtyMap[requests[i].entry.toURL()] = results[i].present; + } + return get( + this.contentMetadataProvider_, + fallbackContentRequests.filter(request => { + return dirtyMap[request.entry.toURL()]; + })); + }); // Merge results. - return Promise.all([ - fileSystemPromise, - externalPromise, - contentPromise, - fallbackContentPromise - ]).then(resultsList => { - const integratedResults = {}; - for (let i = 0; i < resultsList.length; i++) { - const inRequests = resultsList[i].requests; - const results = resultsList[i].results; - assert(inRequests.length === results.length); - for (let j = 0; j < results.length; j++) { - const url = inRequests[j].entry.toURL(); - integratedResults[url] = integratedResults[url] || new MetadataItem(); - for (const name in results[j]) { - integratedResults[url][name] = results[j][name]; + return Promise + .all([ + fileSystemPromise, + externalPromise, + contentPromise, + fallbackContentPromise, + ]) + .then(resultsList => { + const integratedResults = {}; + for (let i = 0; i < resultsList.length; i++) { + const inRequests = resultsList[i].requests; + const results = resultsList[i].results; + assert(inRequests.length === results.length); + for (let j = 0; j < results.length; j++) { + const url = inRequests[j].entry.toURL(); + integratedResults[url] = + integratedResults[url] || new MetadataItem(); + for (const name in results[j]) { + integratedResults[url][name] = results[j][name]; + } + } } - } - } - return requests.map(request => { - return integratedResults[request.entry.toURL()] || new MetadataItem(); - }); - }); + return requests.map(request => { + return integratedResults[request.entry.toURL()] || new MetadataItem(); + }); + }); };
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js index c93eebf..8457c623 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
@@ -77,24 +77,28 @@ }), volumeManager); - reportPromise(model.get([ - new MetadataRequest( - entryA, ['size', 'modificationTime', 'contentThumbnailUrl']), - new MetadataRequest( - entryB, ['size', 'modificationTime', 'contentThumbnailUrl']) - ]).then(results => { - assertEquals(2, results.length); - assertEquals( - new Date(2015, 0, 1).toString(), - results[0].modificationTime.toString()); - assertEquals(1024, results[0].size); - assertEquals('THUMBNAIL_URL_A', results[0].contentThumbnailUrl); - assertEquals( - new Date(2015, 1, 2).toString(), - results[1].modificationTime.toString()); - assertEquals(2048, results[1].size); - assertEquals('THUMBNAIL_URL_B', results[1].contentThumbnailUrl); - }), callback); + reportPromise( + model + .get([ + new MetadataRequest( + entryA, ['size', 'modificationTime', 'contentThumbnailUrl']), + new MetadataRequest( + entryB, ['size', 'modificationTime', 'contentThumbnailUrl']) + ]) + .then(results => { + assertEquals(2, results.length); + assertEquals( + new Date(2015, 0, 1).toString(), + results[0].modificationTime.toString()); + assertEquals(1024, results[0].size); + assertEquals('THUMBNAIL_URL_A', results[0].contentThumbnailUrl); + assertEquals( + new Date(2015, 1, 2).toString(), + results[1].modificationTime.toString()); + assertEquals(2048, results[1].size); + assertEquals('THUMBNAIL_URL_B', results[1].contentThumbnailUrl); + }), + callback); } function testMultiMetadataProviderExternalAndContentProperty(callback) { @@ -114,7 +118,7 @@ assertArrayEquals(['imageWidth', 'present'], requests[1].names); return Promise.resolve([ {present: false, imageWidth: 200}, - {present: true, imageWidth: 400} + {present: true, imageWidth: 400}, ]); } }), @@ -131,14 +135,18 @@ }), volumeManager); - reportPromise(model.get([ - new MetadataRequest(entryA, ['imageWidth']), - new MetadataRequest(entryB, ['imageWidth']), - new MetadataRequest(entryC, ['imageWidth']) - ]).then(results => { - assertEquals(3, results.length); - assertEquals(100, results[0].imageWidth); - assertEquals(200, results[1].imageWidth); - assertEquals(300, results[2].imageWidth); - }), callback); + reportPromise( + model + .get([ + new MetadataRequest(entryA, ['imageWidth']), + new MetadataRequest(entryB, ['imageWidth']), + new MetadataRequest(entryC, ['imageWidth']) + ]) + .then(results => { + assertEquals(3, results.length); + assertEquals(100, results[0].imageWidth); + assertEquals(200, results[1].imageWidth); + assertEquals(300, results[2].imageWidth); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js index 01faf8f..a53b38f 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js
@@ -60,8 +60,7 @@ thumbnail: {}, media: {} }; - const canUseContentThumbnail = - metadataList[i].present && + const canUseContentThumbnail = metadataList[i].present && (FileType.isImage(entries[i], metadataList[i].contentMimeType) || FileType.isAudio(entries[i], metadataList[i].contentMimeType)); if (canUseContentThumbnail) { @@ -69,13 +68,15 @@ } } if (contentRequestEntries.length) { - return this.metadataModel_.get( - contentRequestEntries, - [ - 'contentThumbnailUrl', - 'contentThumbnailTransform', - 'contentImageTransform' - ]).then(contentMetadataList => { + return this.metadataModel_ + .get( + contentRequestEntries, + [ + 'contentThumbnailUrl', + 'contentThumbnailTransform', + 'contentImageTransform', + ]) + .then(contentMetadataList => { for (let i = 0; i < contentRequestEntries.length; i++) { const url = contentRequestEntries[i].toURL(); results[url].thumbnail.url =
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js index 9d2bac3..1b25d084 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
@@ -55,47 +55,56 @@ } function testThumbnailModelGetBasic(callback) { - reportPromise(thumbnailModel.get([imageEntry]).then(results => { - assertEquals(1, results.length); - assertEquals( - new Date(2015, 0, 1).toString(), - results[0].filesystem.modificationTime.toString()); - assertEquals('EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); - assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); - assertTrue(results[0].external.present); - assertEquals('CONTENT_THUMBNAIL_URL', results[0].thumbnail.url); - assertEquals(contentThumbnailTransform, results[0].thumbnail.transform); - assertEquals(imageTransformation, results[0].media.imageTransform); - }), callback); + reportPromise( + thumbnailModel.get([imageEntry]).then(results => { + assertEquals(1, results.length); + assertEquals( + new Date(2015, 0, 1).toString(), + results[0].filesystem.modificationTime.toString()); + assertEquals( + 'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); + assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); + assertTrue(results[0].external.present); + assertEquals('CONTENT_THUMBNAIL_URL', results[0].thumbnail.url); + assertEquals(contentThumbnailTransform, results[0].thumbnail.transform); + assertEquals(imageTransformation, results[0].media.imageTransform); + }), + callback); } function testThumbnailModelGetNotPresent(callback) { metadata.present = false; - reportPromise(thumbnailModel.get([imageEntry]).then(results => { - assertEquals(1, results.length); - assertEquals( - new Date(2015, 0, 1).toString(), - results[0].filesystem.modificationTime.toString()); - assertEquals('EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); - assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); - assertFalse(results[0].external.present); - assertEquals(undefined, results[0].thumbnail.url); - assertEquals(undefined, results[0].thumbnail.transform); - assertEquals(undefined, results[0].media.imageTransform); - }), callback); + reportPromise( + thumbnailModel.get([imageEntry]).then(results => { + assertEquals(1, results.length); + assertEquals( + new Date(2015, 0, 1).toString(), + results[0].filesystem.modificationTime.toString()); + assertEquals( + 'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); + assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); + assertFalse(results[0].external.present); + assertEquals(undefined, results[0].thumbnail.url); + assertEquals(undefined, results[0].thumbnail.transform); + assertEquals(undefined, results[0].media.imageTransform); + }), + callback); } function testThumbnailModelGetNonImage(callback) { - reportPromise(thumbnailModel.get([nonImageEntry]).then(results => { - assertEquals(1, results.length); - assertEquals( - new Date(2015, 0, 1).toString(), - results[0].filesystem.modificationTime.toString()); - assertEquals('EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); - assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); - assertTrue(results[0].external.present); - assertEquals(undefined, results[0].thumbnail.url); - assertEquals(undefined, results[0].thumbnail.transform); - assertEquals(undefined, results[0].media.imageTransform); - }), callback); + reportPromise( + thumbnailModel.get([nonImageEntry]).then(results => { + assertEquals(1, results.length); + assertEquals( + new Date(2015, 0, 1).toString(), + results[0].filesystem.modificationTime.toString()); + assertEquals( + 'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl); + assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl); + assertTrue(results[0].external.present); + assertEquals(undefined, results[0].thumbnail.url); + assertEquals(undefined, results[0].thumbnail.transform); + assertEquals(undefined, results[0].media.imageTransform); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js index c1e1df8..4381ef2 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js +++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
@@ -51,10 +51,9 @@ const remainingActions = {}; if (actionsModel) { const actions = actionsModel.getActions(); - Object.keys(actions).forEach( - key => { - remainingActions[key] = actions[key]; - }); + Object.keys(actions).forEach(key => { + remainingActions[key] = actions[key]; + }); } // First add the sharing item (if available). @@ -82,15 +81,15 @@ // Removing shortcuts is not rendered in the submenu to keep the previous // behavior. Shortcuts can be removed in the left nav using the roots menu. // TODO(mtomasz): Consider rendering the menu item here for consistency. - util.queryDecoratedElement( - '#remove-folder-shortcut', cr.ui.Command).canExecuteChange(); + util.queryDecoratedElement('#remove-folder-shortcut', cr.ui.Command) + .canExecuteChange(); // Both save-for-offline and offline-not-necessary are handled by the single // #toggle-pinned command. - const saveForOfflineAction = remainingActions[ - ActionsModel.CommonActionId.SAVE_FOR_OFFLINE]; - const offlineNotNecessaryAction = remainingActions[ - ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY]; + const saveForOfflineAction = + remainingActions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE]; + const offlineNotNecessaryAction = + remainingActions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY]; if (saveForOfflineAction || offlineNotNecessaryAction) { const menuItem = this.addMenuItem_({}); menuItem.command = '#toggle-pinned'; @@ -98,18 +97,17 @@ delete remainingActions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE]; } if (offlineNotNecessaryAction) { - delete remainingActions[ - ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY - ]; + delete remainingActions[ActionsModel.CommonActionId + .OFFLINE_NOT_NECESSARY]; } } - util.queryDecoratedElement( - '#toggle-pinned', cr.ui.Command).canExecuteChange(); + util.queryDecoratedElement('#toggle-pinned', cr.ui.Command) + .canExecuteChange(); // Process all the rest as custom actions. Object.keys(remainingActions).forEach(key => { const action = remainingActions[key]; - const options = { label: action.getTitle() }; + const options = {label: action.getTitle()}; const menuItem = this.addMenuItem_(options); menuItem.addEventListener('activate', () => {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js index 77bb9f49..6a97b8a 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
@@ -41,9 +41,8 @@ function testSeparator() { assertTrue(separator.hidden); - submenu.setActionsModel(new MockActionsModel({ - id: new MockActionModel('title', null) - })); + submenu.setActionsModel( + new MockActionsModel({id: new MockActionModel('title', null)})); assertFalse(separator.hidden); submenu.setActionsModel(new MockActionsModel([])); @@ -51,9 +50,8 @@ } function testNullModel() { - submenu.setActionsModel(new MockActionsModel({ - id: new MockActionModel('title', null) - })); + submenu.setActionsModel( + new MockActionsModel({id: new MockActionModel('title', null)})); let item = menu.querySelector('cr-menu-item'); assertTrue(!!item); @@ -63,9 +61,8 @@ } function testCustomActionRendering() { - submenu.setActionsModel(new MockActionsModel({ - id: new MockActionModel('title', null) - })); + submenu.setActionsModel( + new MockActionsModel({id: new MockActionModel('title', null)})); const item = menu.querySelector('cr-menu-item'); assertTrue(!!item); assertEquals('title', item.textContent); @@ -73,9 +70,8 @@ } function testCommandActionRendering() { - submenu.setActionsModel(new MockActionsModel({ - SHARE: new MockActionModel('share with me!', null) - })); + submenu.setActionsModel(new MockActionsModel( + {SHARE: new MockActionModel('share with me!', null)})); const item = menu.querySelector('cr-menu-item'); assertTrue(!!item); assertEquals('Share', item.textContent);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js index b1a3cf0..5b369986 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -13,8 +13,7 @@ * @constructor * @extends {cr.EventTarget} */ -function Banners( - directoryModel, volumeManager, document, showWelcome) { +function Banners(directoryModel, volumeManager, document, showWelcome) { this.directoryModel_ = directoryModel; this.volumeManager_ = volumeManager; this.document_ = assert(document); @@ -27,14 +26,14 @@ const handler = this.checkSpaceAndMaybeShowWelcomeBanner_.bind(this); this.directoryModel_.addEventListener('scan-completed', handler); this.directoryModel_.addEventListener('rescan-completed', handler); - this.directoryModel_.addEventListener('directory-changed', - this.onDirectoryChanged_.bind(this)); + this.directoryModel_.addEventListener( + 'directory-changed', this.onDirectoryChanged_.bind(this)); this.unmountedPanel_ = this.document_.querySelector('#unmounted-panel'); this.volumeManager_.volumeInfoList.addEventListener( 'splice', this.onVolumeInfoListSplice_.bind(this)); - this.volumeManager_.addEventListener('drive-connection-changed', - this.onDriveConnectionChanged_.bind(this)); + this.volumeManager_.addEventListener( + 'drive-connection-changed', this.onDriveConnectionChanged_.bind(this)); chrome.storage.onChanged.addListener(this.onStorageChange_.bind(this)); this.welcomeHeaderCounter_ = WELCOME_HEADER_COUNTER_LIMIT; @@ -192,8 +191,8 @@ this.showWelcomeBanner_(type); - const container = queryRequiredElement( - '.drive-welcome.' + type, this.document_); + const container = + queryRequiredElement('.drive-welcome.' + type, this.document_); if (container.firstElementChild) { return; } // Do not re-create. @@ -284,7 +283,8 @@ const text = this.document_.createElement('div'); text.className = 'drive-text'; - text.textContent = strf('DRIVE_SPACE_AVAILABLE_LONG', + text.textContent = strf( + 'DRIVE_SPACE_AVAILABLE_LONG', util.bytesToString(opt_sizeStats.remainingSize)); box.appendChild(text); @@ -301,12 +301,13 @@ close.className = 'banner-close'; box.appendChild(close); close.addEventListener('click', ((total) => { - const values = {}; - values[DRIVE_WARNING_DISMISSED_KEY] = total; - chrome.storage.local.set(values); - box.hidden = true; - this.requestRelayout_(100); - }).bind(null, opt_sizeStats.totalSize)); + const values = {}; + values[DRIVE_WARNING_DISMISSED_KEY] = + total; + chrome.storage.local.set(values); + box.hidden = true; + this.requestRelayout_(100); + }).bind(null, opt_sizeStats.totalSize)); } if (box.hidden != !show) { @@ -396,7 +397,7 @@ return false; } return locationInfo.rootType === VolumeManagerCommon.RootType.DRIVE && - locationInfo.volumeInfo.profile.isCurrentProfile; + locationInfo.volumeInfo.profile.isCurrentProfile; }; /** @@ -466,8 +467,8 @@ return false; } return volumeInfo.profile.isCurrentProfile && - (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS || - volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE); + (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS || + volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE); }; /** @@ -519,31 +520,30 @@ return; } - chrome.fileManagerPrivate.getSizeStats( - volume.volumeId, sizeStats => { - const currentVolume = this.volumeManager_.getVolumeInfo( - assert(this.directoryModel_.getCurrentDirEntry())); - if (volume !== currentVolume) { - // This happens when the current directory is moved during requesting - // the file system size. Just ignore it. - return; - } - // sizeStats is undefined, if some error occurs. - if (!sizeStats || sizeStats.totalSize == 0) { - return; - } + chrome.fileManagerPrivate.getSizeStats(volume.volumeId, sizeStats => { + const currentVolume = this.volumeManager_.getVolumeInfo( + assert(this.directoryModel_.getCurrentDirEntry())); + if (volume !== currentVolume) { + // This happens when the current directory is moved during requesting + // the file system size. Just ignore it. + return; + } + // sizeStats is undefined, if some error occurs. + if (!sizeStats || sizeStats.totalSize == 0) { + return; + } - if (volume.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS) { - // Show the warning banner when the available space is less than 1GB. - this.showLowDownloadsSpaceWarning_( - sizeStats.remainingSize < DOWNLOADS_SPACE_WARNING_THRESHOLD_SIZE); - } else { - // Show the warning banner when the available space ls less than 10%. - const remainingRatio = sizeStats.remainingSize / sizeStats.totalSize; - this.showLowDriveSpaceWarning_( - remainingRatio < DRIVE_SPACE_WARNING_THRESHOLD_RATIO, sizeStats); - } - }); + if (volume.volumeType === VolumeManagerCommon.VolumeType.DOWNLOADS) { + // Show the warning banner when the available space is less than 1GB. + this.showLowDownloadsSpaceWarning_( + sizeStats.remainingSize < DOWNLOADS_SPACE_WARNING_THRESHOLD_SIZE); + } else { + // Show the warning banner when the available space ls less than 10%. + const remainingRatio = sizeStats.remainingSize / sizeStats.totalSize; + this.showLowDriveSpaceWarning_( + remainingRatio < DRIVE_SPACE_WARNING_THRESHOLD_RATIO, sizeStats); + } + }); }; /** @@ -648,8 +648,8 @@ create(panel, 'div', 'error', str('DRIVE_CANNOT_REACH')); - const learnMore = create(panel, 'a', 'learn-more plain-link', - str('DRIVE_LEARN_MORE')); + const learnMore = + create(panel, 'a', 'learn-more plain-link', str('DRIVE_LEARN_MORE')); learnMore.href = str('GOOGLE_DRIVE_ERROR_HELP_URL'); learnMore.target = '_blank'; }; @@ -702,8 +702,7 @@ */ Banners.prototype.maybeShowAuthFailBanner_ = function() { const connection = this.volumeManager_.getDriveConnectionState(); - const showDriveNotReachedMessage = - this.isOnCurrentProfileDrive() && + const showDriveNotReachedMessage = this.isOnCurrentProfileDrive() && connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && connection.reason == VolumeManagerCommon.DriveConnectionReason.NOT_READY; this.authFailedBanner_.hidden = !showDriveNotReachedMessage;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/combobutton.js b/ui/file_manager/file_manager/foreground/js/ui/combobutton.js index 8daffd9..af28c78 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/combobutton.js +++ b/ui/file_manager/file_manager/foreground/js/ui/combobutton.js
@@ -108,11 +108,11 @@ this.addEventListener('menushow', this.handleMenuShow_.bind(this)); this.addEventListener('menuhide', this.handleMenuHide_.bind(this)); - this.trigger_.addEventListener('click', - this.handleTriggerClicked_.bind(this)); + this.trigger_.addEventListener( + 'click', this.handleTriggerClicked_.bind(this)); - this.menu.addEventListener('activate', - this.handleMenuActivate_.bind(this)); + this.menu.addEventListener( + 'activate', this.handleMenuActivate_.bind(this)); // Remove mousedown event listener created by MenuButton::decorate, // and move it down to trigger_. @@ -132,7 +132,7 @@ } e.preventDefault(); break; - case 'Escape': // Maybe this is remote desktop playing a prank? + case 'Escape': // Maybe this is remote desktop playing a prank? this.hideMenu(); break; } @@ -181,6 +181,6 @@ cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR); return { - ComboButton: ComboButton + ComboButton: ComboButton, }; });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/commandbutton.js b/ui/file_manager/file_manager/foreground/js/ui/commandbutton.js index c792527..3d83b1e1 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/commandbutton.js +++ b/ui/file_manager/file_manager/foreground/js/ui/commandbutton.js
@@ -51,12 +51,15 @@ */ CommandButton.prototype.setCommand = function(command) { if (this.command_) { - this.command_.removeEventListener('labelChange', - /** @type {EventListener} */ (this)); - this.command_.removeEventListener('disabledChange', - /** @type {EventListener} */ (this)); - this.command_.removeEventListener('hiddenChange', - /** @type {EventListener} */ (this)); + this.command_.removeEventListener( + 'labelChange', + /** @type {EventListener} */ (this)); + this.command_.removeEventListener( + 'disabledChange', + /** @type {EventListener} */ (this)); + this.command_.removeEventListener( + 'hiddenChange', + /** @type {EventListener} */ (this)); } if (typeof command == 'string') { @@ -76,12 +79,15 @@ this.disabled = command.disabled; this.hidden = command.hidden; - this.command_.addEventListener('labelChange', - /** @type {EventListener} */ (this)); - this.command_.addEventListener('disabledChange', - /** @type {EventListener} */ (this)); - this.command_.addEventListener('hiddenChange', - /** @type {EventListener} */ (this)); + this.command_.addEventListener( + 'labelChange', + /** @type {EventListener} */ (this)); + this.command_.addEventListener( + 'disabledChange', + /** @type {EventListener} */ (this)); + this.command_.addEventListener( + 'hiddenChange', + /** @type {EventListener} */ (this)); } }; @@ -144,12 +150,10 @@ * Whether the button is disabled or not. * @type {boolean} */ -cr.defineProperty(CommandButton, 'disabled', - cr.PropertyKind.BOOL_ATTR); +cr.defineProperty(CommandButton, 'disabled', cr.PropertyKind.BOOL_ATTR); /** * Whether the button is hidden or not. * @type {boolean} */ -cr.defineProperty(CommandButton, 'hidden', - cr.PropertyKind.BOOL_ATTR); +cr.defineProperty(CommandButton, 'hidden', cr.PropertyKind.BOOL_ATTR);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js index a0181cb1..9e42d22 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js
@@ -8,7 +8,6 @@ * This dialog should be used as task picker for file operations. */ cr.define('cr.filebrowser', () => { - /** * Creates dialog in DOM tree. * @@ -48,9 +47,7 @@ }; } - DefaultTaskDialog.prototype = { - __proto__: FileManagerDialogBase.prototype - }; + DefaultTaskDialog.prototype = {__proto__: FileManagerDialogBase.prototype}; /** * Renders item for list. @@ -92,9 +89,8 @@ * @param {function(Object)} onSelectedItem Callback which is called when an * item is selected. */ - DefaultTaskDialog.prototype.showDefaultTaskDialog = - function(title, message, items, defaultIndex, onSelectedItem) { - + DefaultTaskDialog.prototype.showDefaultTaskDialog = function( + title, message, items, defaultIndex, onSelectedItem) { this.onSelectedItemCallback_ = onSelectedItem; const show = FileManagerDialogBase.prototype.showTitleAndTextDialog.call(
diff --git a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js index 7aff59d..f4112fd0 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js +++ b/ui/file_manager/file_manager/foreground/js/ui/dialog_footer.js
@@ -163,9 +163,11 @@ if (!description) { // Convert ['jpg', 'png'] to '*.jpg, *.png'. - description = fileType.extensions.map(s => { - return '*.' + s; - }).join(', '); + description = fileType.extensions + .map(s => { + return '*.' + s; + }) + .join(', '); } } option.innerText = description;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index 508d7f2..d9278f1 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -106,22 +106,23 @@ * @param {boolean} isRootEntry Whether the entry selected was a root entry. * @return */ -DirectoryItemTreeBaseMethods.recordUMASelectedEntry = (e, rootType, isRootEntry) => { - const expandIconSelected = e.target.classList.contains('expand-icon'); - let metricName = 'Location.OnEntrySelected.TopLevel'; - if (!expandIconSelected && isRootEntry) { - metricName = 'Location.OnEntrySelected.TopLevel'; - } else if (!expandIconSelected && !isRootEntry) { - metricName = 'Location.OnEntrySelected.NonTopLevel'; - } else if (expandIconSelected && isRootEntry) { - metricName = 'Location.OnEntryExpandedOrCollapsed.TopLevel'; - } else if (expandIconSelected && !isRootEntry) { - metricName = 'Location.OnEntryExpandedOrCollapsed.NonTopLevel'; - } +DirectoryItemTreeBaseMethods.recordUMASelectedEntry = + (e, rootType, isRootEntry) => { + const expandIconSelected = e.target.classList.contains('expand-icon'); + let metricName = 'Location.OnEntrySelected.TopLevel'; + if (!expandIconSelected && isRootEntry) { + metricName = 'Location.OnEntrySelected.TopLevel'; + } else if (!expandIconSelected && !isRootEntry) { + metricName = 'Location.OnEntrySelected.NonTopLevel'; + } else if (expandIconSelected && isRootEntry) { + metricName = 'Location.OnEntryExpandedOrCollapsed.TopLevel'; + } else if (expandIconSelected && !isRootEntry) { + metricName = 'Location.OnEntryExpandedOrCollapsed.NonTopLevel'; + } - metrics.recordEnum( - metricName, rootType, VolumeManagerCommon.RootTypesForUMA); -}; + metrics.recordEnum( + metricName, rootType, VolumeManagerCommon.RootTypesForUMA); + }; Object.freeze(DirectoryItemTreeBaseMethods); @@ -421,7 +422,7 @@ * @override */ DirectoryItem.prototype.remove = function(child) { - this.lastElementChild.removeChild(/** @type {!cr.ui.TreeItem} */(child)); + this.lastElementChild.removeChild(/** @type {!cr.ui.TreeItem} */ (child)); if (this.items.length == 0) { this.hasChildren = false; } @@ -616,8 +617,7 @@ // If the entry doesn't exist, updates sub directories and tries again. this.updateSubDirectories( - false /* recursive */, - this.searchAndSelectByEntry.bind(this, entry)); + false /* recursive */, this.searchAndSelectByEntry.bind(this, entry)); }; /** @@ -1064,12 +1064,10 @@ this.updateSubDirectories(false); }; - this.volumeInfo_.resolveDisplayRoot( - onEntryResolved, - () => { - // Error, the display root is not available. It may happen on Drive. - this.parentTree_.dataModel.onItemNotFoundError(this.modelItem); - }); + this.volumeInfo_.resolveDisplayRoot(onEntryResolved, () => { + // Error, the display root is not available. It may happen on Drive. + this.parentTree_.dataModel.onItemNotFoundError(this.modelItem); + }); }; /** @@ -1085,8 +1083,7 @@ if (backgroundImage !== 'none') { // The icon div is not yet added to DOM, therefore it is impossible to // use style.backgroundImage. - icon.setAttribute( - 'style', 'background-image: ' + backgroundImage); + icon.setAttribute('style', 'background-image: ' + backgroundImage); } icon.setAttribute('volume-type-icon', volumeInfo.volumeType); if (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.MEDIA_VIEW) { @@ -1137,12 +1134,12 @@ __proto__: VolumeItem.prototype, // Overrides the property 'expanded' to prevent Drive volume from shrinking. get expanded() { - return Object.getOwnPropertyDescriptor( - cr.ui.TreeItem.prototype, 'expanded').get.call(this); + return Object.getOwnPropertyDescriptor(cr.ui.TreeItem.prototype, 'expanded') + .get.call(this); }, set expanded(b) { - Object.getOwnPropertyDescriptor( - cr.ui.TreeItem.prototype, 'expanded').set.call(this, b); + Object.getOwnPropertyDescriptor(cr.ui.TreeItem.prototype, 'expanded') + .set.call(this, b); // When Google Drive is expanded while it is selected, select the My Drive. if (b) { if (this.selected && this.entry) { @@ -1581,9 +1578,7 @@ // For shortcuts we already have an Entry, but it has to be resolved again // in case, it points to a non-existing directory. window.webkitResolveLocalFileSystemURL( - this.entry.toURL(), - onEntryResolved, - () => { + this.entry.toURL(), onEntryResolved, () => { // Error, the entry can't be re-resolved. It may happen for shortcuts // which targets got removed after resolving the Entry during // initialization. @@ -1680,9 +1675,10 @@ * FakeItem doesn't really have sub-directories, it's defined here only to have * the same API of other Items on this file. */ -FakeItem.prototype.updateSubDirectories = (recursive, opt_successCallback, opt_errorCallback) => { - return opt_successCallback && opt_successCallback(); -}; +FakeItem.prototype.updateSubDirectories = + (recursive, opt_successCallback, opt_errorCallback) => { + return opt_successCallback && opt_successCallback(); + }; /** * FakeItem doesn't really have shared status/icon so we define here as no-op. @@ -1710,19 +1706,14 @@ * @param {!FileOperationManager} fileOperationManager * @param {boolean} fakeEntriesVisible True if it should show the fakeEntries. */ -DirectoryTree.decorate = ( - el, - directoryModel, - volumeManager, - metadataModel, - fileOperationManager, - fakeEntriesVisible -) => { - el.__proto__ = DirectoryTree.prototype; - /** @type {DirectoryTree} */ (el).decorateDirectoryTree( - directoryModel, volumeManager, metadataModel, fileOperationManager, - fakeEntriesVisible); -}; +DirectoryTree.decorate = + (el, directoryModel, volumeManager, metadataModel, fileOperationManager, + fakeEntriesVisible) => { + el.__proto__ = DirectoryTree.prototype; + /** @type {DirectoryTree} */ (el).decorateDirectoryTree( + directoryModel, volumeManager, metadataModel, fileOperationManager, + fakeEntriesVisible); + }; DirectoryTree.prototype = { __proto__: cr.ui.Tree.prototype, @@ -1871,7 +1862,7 @@ let addAt = 0; while (addAt < parentItem.items.length && - parentItem.items[addAt].entry.name < newDirectory.name) { + parentItem.items[addAt].entry.name < newDirectory.name) { addAt++; } @@ -2004,15 +1995,14 @@ this.models_ = []; this.fileFilter_ = this.directoryModel_.getFileFilter(); - this.fileFilter_.addEventListener('changed', - this.onFilterChanged_.bind(this)); + this.fileFilter_.addEventListener( + 'changed', this.onFilterChanged_.bind(this)); - this.directoryModel_.addEventListener('directory-changed', - this.onCurrentDirectoryChanged_.bind(this)); + this.directoryModel_.addEventListener( + 'directory-changed', this.onCurrentDirectoryChanged_.bind(this)); util.addEventListenerToBackgroundComponent( - fileOperationManager, - 'entries-changed', + fileOperationManager, 'entries-changed', this.onEntriesChanged_.bind(this)); this.addEventListener('click', (event) => { @@ -2052,13 +2042,13 @@ switch (event.kind) { case util.EntryChangedKind.CREATED: // Handle as change event of parent entry. - Promise.all( - directories.map((directory) => - new Promise(directory.getParent.bind(directory)))) + Promise + .all(directories.map( + (directory) => new Promise(directory.getParent.bind(directory)))) .then((parentDirectories) => { - parentDirectories.forEach((parentDirectory) => - this.updateTreeByEntry_(parentDirectory)); - }); + parentDirectories.forEach( + (parentDirectory) => this.updateTreeByEntry_(parentDirectory)); + }); break; case util.EntryChangedKind.DELETED: directories.forEach((directory) => this.updateTreeByEntry_(directory)); @@ -2170,7 +2160,8 @@ * @private */ DirectoryTree.prototype.updateTreeByEntry_ = function(entry) { - entry.getDirectory(entry.fullPath, {create: false}, + entry.getDirectory( + entry.fullPath, {create: false}, () => { // If entry exists. // e.g. /a/b is deleted while watching /a. @@ -2186,27 +2177,29 @@ // it. // e.g. /a/b is deleted while watching /a/b. Try to update /a in this // case. - entry.getParent((parentEntry) => { - this.updateTreeByEntry_(parentEntry); - }, (error) => { - // If it fails to get parent, update the subtree by volume. - // e.g. /a/b is deleted while watching /a/b/c. getParent of /a/b/c - // fails in this case. We falls back to volume update. - // - // TODO(yawano): Try to get parent path also in this case by - // manipulating path string. - const volumeInfo = this.volumeManager.getVolumeInfo(entry); - if (!volumeInfo) { - return; - } + entry.getParent( + (parentEntry) => { + this.updateTreeByEntry_(parentEntry); + }, + (error) => { + // If it fails to get parent, update the subtree by volume. + // e.g. /a/b is deleted while watching /a/b/c. getParent of /a/b/c + // fails in this case. We falls back to volume update. + // + // TODO(yawano): Try to get parent path also in this case by + // manipulating path string. + const volumeInfo = this.volumeManager.getVolumeInfo(entry); + if (!volumeInfo) { + return; + } - for (let i = 0; i < this.items.length; i++) { - if (this.items[i] instanceof VolumeItem && - this.items[i].volumeInfo === volumeInfo) { - this.items[i].updateSubDirectories(true /* recursive */); - } - } - }); + for (let i = 0; i < this.items.length; i++) { + if (this.items[i] instanceof VolumeItem && + this.items[i].volumeInfo === volumeInfo) { + this.items[i].updateSubDirectories(true /* recursive */); + } + } + }); }); };
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js index ef4091e4..f69bdac 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
@@ -389,7 +389,7 @@ */ function testCreateDirectoryTreeWithTeamDrivesAndComputers(callback) { // Setup entries returned by fakeFileSystemURLResults. - fakeFileSystemURLEntries ['filesystem:drive/team_drives/a'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] = new MockDirectoryEntry(driveFileSystem, '/team_drives/a'); fakeFileSystemURLEntries['filesystem:drive/Comuters/My Laptop'] = new MockDirectoryEntry(driveFileSystem, '/Computers/My Laptop'); @@ -499,10 +499,12 @@ directoryTree.updateSubElementsFromList(true); // There are 2 volumes, Drive and Downloads, at first. - assertArrayEquals([ - str('DRIVE_DIRECTORY_LABEL'), - str('DOWNLOADS_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabels(directoryTree)); + assertArrayEquals( + [ + str('DRIVE_DIRECTORY_LABEL'), + str('DOWNLOADS_DIRECTORY_LABEL'), + ], + getDirectoryTreeItemLabels(directoryTree)); // Mounts a removable volume. const removableVolume = MockVolumeManager.createMockVolumeInfo( @@ -511,18 +513,22 @@ volumeManager.volumeInfoList.add(removableVolume); // Asserts that the directoryTree is not updated before the update. - assertArrayEquals([ - str('DRIVE_DIRECTORY_LABEL'), - str('DOWNLOADS_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabels(directoryTree)); + assertArrayEquals( + [ + str('DRIVE_DIRECTORY_LABEL'), + str('DOWNLOADS_DIRECTORY_LABEL'), + ], + getDirectoryTreeItemLabels(directoryTree)); // Asserts that a removable directory is added after the update. directoryTree.updateSubElementsFromList(false); - assertArrayEquals([ - str('DRIVE_DIRECTORY_LABEL'), - str('DOWNLOADS_DIRECTORY_LABEL'), - str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabels(directoryTree)); + assertArrayEquals( + [ + str('DRIVE_DIRECTORY_LABEL'), + str('DOWNLOADS_DIRECTORY_LABEL'), + str('REMOVABLE_DIRECTORY_LABEL'), + ], + getDirectoryTreeItemLabels(directoryTree)); // Mounts an archive volume. const archiveVolume = MockVolumeManager.createMockVolumeInfo( @@ -531,11 +537,13 @@ volumeManager.volumeInfoList.add(archiveVolume); // Asserts that the directoryTree is not updated before the update. - assertArrayEquals([ - str('DRIVE_DIRECTORY_LABEL'), - str('DOWNLOADS_DIRECTORY_LABEL'), - str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabels(directoryTree)); + assertArrayEquals( + [ + str('DRIVE_DIRECTORY_LABEL'), + str('DOWNLOADS_DIRECTORY_LABEL'), + str('REMOVABLE_DIRECTORY_LABEL'), + ], + getDirectoryTreeItemLabels(directoryTree)); // Asserts that an archive directory is added before the removable directory. directoryTree.updateSubElementsFromList(false); @@ -563,11 +571,13 @@ // Asserts that an archive directory is deleted. directoryTree.updateSubElementsFromList(false); - assertArrayEquals([ - str('DRIVE_DIRECTORY_LABEL'), - str('DOWNLOADS_DIRECTORY_LABEL'), - str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabels(directoryTree)); + assertArrayEquals( + [ + str('DRIVE_DIRECTORY_LABEL'), + str('DOWNLOADS_DIRECTORY_LABEL'), + str('REMOVABLE_DIRECTORY_LABEL'), + ], + getDirectoryTreeItemLabels(directoryTree)); } /** @@ -658,8 +668,8 @@ }) .then(() => { return new Promise(resolve => { - fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] - .remove(resolve); + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'].remove( + resolve); }); }) .then(() => { @@ -779,8 +789,8 @@ }) .then(() => { return new Promise(resolve => { - fakeFileSystemURLEntries['filesystem:drive/Computers/a'] - .remove(resolve); + fakeFileSystemURLEntries['filesystem:drive/Computers/a'].remove( + resolve); }); }) .then(() => {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/drag_selector.js b/ui/file_manager/file_manager/foreground/js/ui/drag_selector.js index 82c94e3..b19c3570f 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/drag_selector.js +++ b/ui/file_manager/file_manager/foreground/js/ui/drag_selector.js
@@ -153,9 +153,9 @@ // Collect items within the selection rect. const currentSelection = (/** @type {DragTarget} */ (this.target_)) - .getHitElements( - borderBounds.left, borderBounds.top, - borderBounds.width, borderBounds.height); + .getHitElements( + borderBounds.left, borderBounds.top, + borderBounds.width, borderBounds.height); const pointedElements = (/** @type {DragTarget} */ (this.target_)).getHitElements(pos.x, pos.y); const leadIndex = pointedElements.length ? pointedElements[0] : -1;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js index 79ab172..3376f48 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
@@ -99,8 +99,8 @@ * @private {number} * @const */ - self.paddingStart_ = parseFloat( - isRTL() ? style.paddingRight : style.paddingLeft); + self.paddingStart_ = + parseFloat(isRTL() ? style.paddingRight : style.paddingLeft); /** * @private {number} * @const @@ -112,7 +112,7 @@ * Grid size. * @const {number} */ -FileGrid.GridSize = 180; // px +FileGrid.GridSize = 180; // px /** * Sets list thumbnail loader. @@ -164,22 +164,18 @@ if (entry) { const box = listItem.querySelector('.img-container'); if (box) { - const mimeType = this.metadataModel_.getCache( - [entry], ['contentMimeType'])[0].contentMimeType; + const mimeType = + this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; if (!event.dataUrl) { - FileGrid.clearThumbnailImage_( - assertInstanceof(box, HTMLDivElement)); + FileGrid.clearThumbnailImage_(assertInstanceof(box, HTMLDivElement)); FileGrid.setGenericThumbnail_( assertInstanceof(box, HTMLDivElement), entry); } else { FileGrid.setThumbnailImage_( - assertInstanceof(box, HTMLDivElement), - entry, - assert(event.dataUrl), - assert(event.width), - assert(event.height), - /* should animate */ true, - mimeType); + assertInstanceof(box, HTMLDivElement), entry, assert(event.dataUrl), + assert(event.width), assert(event.height), + /* should animate */ true, mimeType); } } listItem.classList.toggle('thumbnail-loaded', !!event.dataUrl); @@ -209,9 +205,9 @@ // Invisible pinned item could be outside of the // [beginIndex, endIndex). Ignore it. if (index >= beginIndex && nextIndex < endIndex && - (nextIndex < this.dataModel.getFolderCount() - ? nextIndex % columns == 0 - : (nextIndex - this.dataModel.getFolderCount()) % columns == 0)) { + (nextIndex < this.dataModel.getFolderCount() ? + nextIndex % columns == 0 : + (nextIndex - this.dataModel.getFolderCount()) % columns == 0)) { const isFolderSpacer = nextIndex === this.dataModel.getFolderCount(); if (isSpacer(next)) { // Leave the spacer on its place. @@ -232,7 +228,7 @@ function isSpacer(child) { return child.classList.contains('spacer') && - child != afterFiller; // Must not be removed. + child != afterFiller; // Must not be removed. } // Make sure that grid item's selected attribute is updated just after the @@ -341,24 +337,25 @@ } const itemHeight = index < this.dataModel.getFolderCount() ? - this.getFolderItemHeight_() : this.getFileItemHeight_(); + this.getFolderItemHeight_() : + this.getFileItemHeight_(); const scrollTop = this.scrollTop; const top = this.getItemTop(index); const clientHeight = this.clientHeight; const computedStyle = window.getComputedStyle(this); const paddingY = parseInt(computedStyle.paddingTop, 10) + - parseInt(computedStyle.paddingBottom, 10); + parseInt(computedStyle.paddingBottom, 10); const availableHeight = clientHeight - paddingY; const self = this; // Function to adjust the tops of viewport and row. const scrollToAdjustTop = () => { - self.scrollTop = top; + self.scrollTop = top; }; // Function to adjust the bottoms of viewport and row. const scrollToAdjustBottom = () => { - self.scrollTop = top + itemHeight - availableHeight; + self.scrollTop = top + itemHeight - availableHeight; }; // Check if the entire of given indexed row can be shown in the viewport. @@ -384,8 +381,8 @@ const beginRow = this.getRowForListOffset_(scrollTop); const endRow = this.getRowForListOffset_(scrollTop + clientHeight - 1) + 1; const beginIndex = this.getFirstItemInRow(beginRow); - const endIndex = Math.min(this.getFirstItemInRow(endRow), - this.dataModel.length); + const endIndex = + Math.min(this.getFirstItemInRow(endRow), this.dataModel.length); const result = { first: beginIndex, length: endIndex - beginIndex, @@ -403,7 +400,7 @@ const row = this.getItemRow(lastIndex - 1); if (row < folderRows) { let fillerHeight = (folderRows - 1 - row) * this.getFolderItemHeight_() + - fileRows * this.getFileItemHeight_(); + fileRows * this.getFileItemHeight_(); if (fileRows > 0) { fillerHeight += this.getSeparatorHeight_(); } @@ -511,7 +508,7 @@ */ FileGrid.prototype.updateListItemsMetadata = function(type, entries) { const urls = util.entriesToURLs(entries); - const boxes = /** @type {!NodeList<!HTMLElement>} */( + const boxes = /** @type {!NodeList<!HTMLElement>} */ ( this.querySelectorAll('.img-container')); for (let i = 0; i < boxes.length; i++) { const box = boxes[i]; @@ -588,8 +585,8 @@ const bottom = li.ownerDocument.createElement('div'); bottom.className = 'thumbnail-bottom'; - const mimeType = this.metadataModel_.getCache( - [entry], ['contentMimeType'])[0].contentMimeType; + const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; const locationInfo = this.volumeManager_.getLocationInfo(entry); const detailIcon = filelist.renderFileTypeIcon( li.ownerDocument, entry, locationInfo, mimeType); @@ -614,15 +611,12 @@ * @private */ FileGrid.prototype.decorateThumbnailBox_ = function(li, entry) { - const box = assertInstanceof(li.querySelector('.img-container'), - HTMLDivElement); - if (this.importStatusVisible_ && - importer.isEligibleType(entry)) { - this.historyLoader_.getHistory().then( - FileGrid.applyHistoryBadges_.bind( - null, - /** @type {!FileEntry} */ (entry), - box)); + const box = + assertInstanceof(li.querySelector('.img-container'), HTMLDivElement); + if (this.importStatusVisible_ && importer.isEligibleType(entry)) { + this.historyLoader_.getHistory().then(FileGrid.applyHistoryBadges_.bind( + null, + /** @type {!FileEntry} */ (entry), box)); } if (entry.isDirectory) { @@ -633,28 +627,26 @@ // Set thumbnail if it's already in cache, and the thumbnail data is not // empty. const thumbnailData = this.listThumbnailLoader_ ? - this.listThumbnailLoader_.getThumbnailFromCache(entry) : null; + this.listThumbnailLoader_.getThumbnailFromCache(entry) : + null; if (thumbnailData && thumbnailData.dataUrl) { - const mimeType = this.metadataModel_.getCache( - [entry], ['contentMimeType'])[0].contentMimeType; + const mimeType = + this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; FileGrid.setThumbnailImage_( - box, - entry, - thumbnailData.dataUrl, - thumbnailData.width, + box, entry, thumbnailData.dataUrl, thumbnailData.width, thumbnailData.height, - /* should not animate */ false, - mimeType); + /* should not animate */ false, mimeType); li.classList.toggle('thumbnail-loaded', true); } else { FileGrid.setGenericThumbnail_(box, entry); li.classList.toggle('thumbnail-loaded', false); } - const mimeType = this.metadataModel_.getCache( - [entry], ['contentMimeType'])[0].contentMimeType; - li.classList.toggle('can-hide-filename', - FileType.isImage(entry, mimeType) || - FileType.isRaw(entry, mimeType)); + const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; + li.classList.toggle( + 'can-hide-filename', + FileType.isImage(entry, mimeType) || FileType.isRaw(entry, mimeType)); }; /** @@ -716,37 +708,38 @@ * @param {string=} opt_mimeType Optional mime type for the image. * @private */ -FileGrid.setThumbnailImage_ = (box, entry, dataUrl, width, height, shouldAnimate, opt_mimeType) => { - const oldThumbnails = box.querySelectorAll('.thumbnail'); +FileGrid.setThumbnailImage_ = + (box, entry, dataUrl, width, height, shouldAnimate, opt_mimeType) => { + const oldThumbnails = box.querySelectorAll('.thumbnail'); - const thumbnail = box.ownerDocument.createElement('div'); - thumbnail.classList.add('thumbnail'); + const thumbnail = box.ownerDocument.createElement('div'); + thumbnail.classList.add('thumbnail'); - // If the image is JPEG or the thumbnail is larger than the grid size, resize - // it to cover the thumbnail box. - const type = FileType.getType(entry, opt_mimeType); - if ((type.type === 'image' && type.subtype === 'JPEG') || - width > FileGrid.GridSize || height > FileGrid.GridSize) { - thumbnail.style.backgroundSize = 'cover'; - } - - thumbnail.style.backgroundImage = 'url(' + dataUrl + ')'; - thumbnail.addEventListener('animationend', () => { - // Remove animation css once animation is completed in order not to animate - // again when an item is attached to the dom again. - thumbnail.classList.remove('animate'); - - for (let i = 0; i < oldThumbnails.length; i++) { - if (box.contains(oldThumbnails[i])) { - box.removeChild(oldThumbnails[i]); + // If the image is JPEG or the thumbnail is larger than the grid size, + // resize it to cover the thumbnail box. + const type = FileType.getType(entry, opt_mimeType); + if ((type.type === 'image' && type.subtype === 'JPEG') || + width > FileGrid.GridSize || height > FileGrid.GridSize) { + thumbnail.style.backgroundSize = 'cover'; } - } - }); - if (shouldAnimate) { - thumbnail.classList.add('animate'); - } - box.appendChild(thumbnail); -}; + + thumbnail.style.backgroundImage = 'url(' + dataUrl + ')'; + thumbnail.addEventListener('animationend', () => { + // Remove animation css once animation is completed in order not to + // animate again when an item is attached to the dom again. + thumbnail.classList.remove('animate'); + + for (let i = 0; i < oldThumbnails.length; i++) { + if (box.contains(oldThumbnails[i])) { + box.removeChild(oldThumbnails[i]); + } + } + }); + if (shouldAnimate) { + thumbnail.classList.add('animate'); + } + box.appendChild(thumbnail); + }; /** * Clears thumbnail image from the box. @@ -787,30 +780,28 @@ */ FileGrid.applyHistoryBadges_ = (entry, box, history) => { history.wasImported(entry, importer.Destination.GOOGLE_DRIVE) - .then( - imported => { - if (imported) { - // TODO(smckay): update badges when history changes - // "box" is currently the sibling of the elemement - // we want to style. So rather than employing - // a possibly-fragile sibling selector we just - // plop the imported class on the parent of both. - box.parentElement.classList.add('imported'); - } else { - history.wasCopied(entry, importer.Destination.GOOGLE_DRIVE) - .then( - copied => { - if (copied) { - // TODO(smckay): update badges when history changes - // "box" is currently the sibling of the elemement - // we want to style. So rather than employing - // a possibly-fragile sibling selector we just - // plop the imported class on the parent of both. - box.parentElement.classList.add('copied'); - } - }); - } - }); + .then(imported => { + if (imported) { + // TODO(smckay): update badges when history changes + // "box" is currently the sibling of the elemement + // we want to style. So rather than employing + // a possibly-fragile sibling selector we just + // plop the imported class on the parent of both. + box.parentElement.classList.add('imported'); + } else { + history.wasCopied(entry, importer.Destination.GOOGLE_DRIVE) + .then(copied => { + if (copied) { + // TODO(smckay): update badges when history changes + // "box" is currently the sibling of the elemement + // we want to style. So rather than employing + // a possibly-fragile sibling selector we just + // plop the imported class on the parent of both. + box.parentElement.classList.add('copied'); + } + }); + } + }); }; /** @@ -975,9 +966,8 @@ this.tapHandler_ = new FileTapHandler(); } -FileGridSelectionController.prototype = /** @struct */ { - __proto__: cr.ui.GridSelectionController.prototype -}; +FileGridSelectionController.prototype = + /** @struct */ {__proto__: cr.ui.GridSelectionController.prototype}; /** @override */ FileGridSelectionController.prototype.handlePointerDownUp = function(e, index) {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index e95e28c..7cfeb37 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -97,8 +97,7 @@ * @type {!cr.filebrowser.DefaultTaskDialog} * @const */ - this.defaultTaskPicker = - new cr.filebrowser.DefaultTaskDialog(this.element); + this.defaultTaskPicker = new cr.filebrowser.DefaultTaskDialog(this.element); /** * Suggest apps dialog. @@ -128,8 +127,8 @@ * @type {!cr.ui.Menu} * @const */ - this.textContextMenu = util.queryDecoratedElement( - '#text-context-menu', cr.ui.Menu); + this.textContextMenu = + util.queryDecoratedElement('#text-context-menu', cr.ui.Menu); /** * Location line. @@ -174,8 +173,8 @@ * @type {!EmptyFolder} * @const */ - this.emptyFolder = new EmptyFolder( - queryRequiredElement('#empty-folder', this.element)); + this.emptyFolder = + new EmptyFolder(queryRequiredElement('#empty-folder', this.element)); /** * Toggle-view button. @@ -189,8 +188,8 @@ * @type {!cr.ui.MenuButton} * @const */ - this.sortButton = util.queryDecoratedElement( - '#sort-button', cr.ui.MenuButton); + this.sortButton = + util.queryDecoratedElement('#sort-button', cr.ui.MenuButton); /** * Ripple effect of sort button. @@ -198,8 +197,8 @@ * @const */ this.sortButtonToggleRipple = - /** @type {!FilesToggleRipple} */ (queryRequiredElement( - 'files-toggle-ripple', this.sortButton)); + /** @type {!FilesToggleRipple} */ ( + queryRequiredElement('files-toggle-ripple', this.sortButton)); /** * The button to open gear menu. @@ -215,8 +214,8 @@ * @const */ this.gearButtonToggleRipple = - /** @type {!FilesToggleRipple} */ (queryRequiredElement( - 'files-toggle-ripple', this.gearButton)); + /** @type {!FilesToggleRipple} */ ( + queryRequiredElement('files-toggle-ripple', this.gearButton)); /** * @type {!GearMenu} @@ -262,8 +261,8 @@ * @type {!cr.ui.Menu} * @const */ - this.fileContextMenu = util.queryDecoratedElement( - '#file-context-menu', cr.ui.Menu); + this.fileContextMenu = + util.queryDecoratedElement('#file-context-menu', cr.ui.Menu); /** * @type {!HTMLMenuItemElement} @@ -284,8 +283,7 @@ * @type {!cr.ui.ComboButton} * @const */ - this.taskMenuButton = util.queryDecoratedElement( - '#tasks', cr.ui.ComboButton); + this.taskMenuButton = util.queryDecoratedElement('#tasks', cr.ui.ComboButton); this.taskMenuButton.showMenu = function(shouldSetFocus) { // Prevent the empty menu from opening. if (!this.menu.length) { @@ -335,7 +333,8 @@ * @public {!ProvidersMenu} * @const */ - this.providersMenu = new ProvidersMenu(providersModel, + this.providersMenu = new ProvidersMenu( + providersModel, util.queryDecoratedElement('#add-new-services-menu', cr.ui.Menu)); /** @@ -422,8 +421,7 @@ cr.ui.contextMenuHandler.setContextMenu(grid, this.fileContextMenu); cr.ui.contextMenuHandler.setContextMenu(table.list, this.fileContextMenu); cr.ui.contextMenuHandler.setContextMenu( - queryRequiredElement('.drive-welcome.page'), - this.fileContextMenu); + queryRequiredElement('.drive-welcome.page'), this.fileContextMenu); // Add handlers. document.defaultView.addEventListener('resize', this.relayout.bind(this)); @@ -438,8 +436,9 @@ let targetElement = null; if (this.dialogType_ == DialogType.SELECT_SAVEAS_FILE) { targetElement = this.dialogFooter.filenameInput; - } else if (this.listContainer.currentListType != - ListContainer.ListType.UNINITIALIZED) { + } else if ( + this.listContainer.currentListType != + ListContainer.ListType.UNINITIALIZED) { targetElement = this.listContainer.currentList; } @@ -466,11 +465,12 @@ // tree has to be notified to adjust its components (e.g. progress bar). const relayoutLimiter = new AsyncUtil.RateLimiter( directoryTree.relayout.bind(directoryTree), 200); - const observer = new MutationObserver( - relayoutLimiter.run.bind(relayoutLimiter)); - observer.observe(this.progressCenterPanel.element, - /** @type {MutationObserverInit} */ - ({subtree: true, attributes: true, childList: true})); + const observer = + new MutationObserver(relayoutLimiter.run.bind(relayoutLimiter)); + observer.observe( + this.progressCenterPanel.element, + /** @type {MutationObserverInit} */ + ({subtree: true, attributes: true, childList: true})); }; /** @@ -495,8 +495,8 @@ * items are decorated as cr.ui.MenuItem. */ FileManagerUI.prototype.decorateFilesMenuItems = () => { - const filesMenuItems = document.querySelectorAll( - 'cr-menu.files-menu > cr-menu-item'); + const filesMenuItems = + document.querySelectorAll('cr-menu.files-menu > cr-menu-item'); for (let i = 0; i < filesMenuItems.length; i++) { const filesMenuItem = filesMenuItems[i]; @@ -531,7 +531,7 @@ this.toggleViewButton.classList.toggle('thumbnail', isListView); const label = isListView ? str('CHANGE_TO_THUMBNAILVIEW_BUTTON_LABEL') : - str('CHANGE_TO_LISTVIEW_BUTTON_LABEL'); + str('CHANGE_TO_LISTVIEW_BUTTON_LABEL'); this.toggleViewButton.setAttribute('aria-label', label); this.relayout(); }; @@ -560,8 +560,8 @@ * @param {boolean=} opt_resizeNextElement * @private */ -FileManagerUI.prototype.decorateSplitter_ = function(splitterElement, - opt_resizeNextElement) { +FileManagerUI.prototype.decorateSplitter_ = function( + splitterElement, opt_resizeNextElement) { const self = this; const Splitter = cr.ui.Splitter; const customSplitter = cr.ui.define('div'); @@ -607,32 +607,31 @@ if (!entries.length) { return; } - chrome.fileManagerPrivate.getProfiles( - (profiles, currentId, displayedId) => { - // Find strings. - let displayName; - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].profileId === currentId) { - displayName = profiles[i].displayName; - break; - } + chrome.fileManagerPrivate.getProfiles((profiles, currentId, displayedId) => { + // Find strings. + let displayName; + for (let i = 0; i < profiles.length; i++) { + if (profiles[i].profileId === currentId) { + displayName = profiles[i].displayName; + break; } - if (!displayName) { - console.warn('Display name is not found.'); - return; - } + } + if (!displayName) { + console.warn('Display name is not found.'); + return; + } - const title = entries.length > 1 ? - entries[0].name + '\u2026' /* ellipsis */ : entries[0].name; - const message = strf(entries.length > 1 ? - 'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' : - 'OPEN_IN_OTHER_DESKTOP_MESSAGE', - displayName, - currentId); + const title = entries.length > 1 ? + entries[0].name + '\u2026' /* ellipsis */ : + entries[0].name; + const message = strf( + entries.length > 1 ? 'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' : + 'OPEN_IN_OTHER_DESKTOP_MESSAGE', + displayName, currentId); - // Show the dialog. - this.alertDialog.showWithTitle(title, message, null, null, null); - }); + // Show the dialog. + this.alertDialog.showWithTitle(title, message, null, null, null); + }); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js index 7420ffda..da00aa4 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
@@ -57,8 +57,8 @@ } else { // Make sure each cell has the minumum width. This is necessary when the // window size is too small to contain all the columns. - this.columns_[i].width = Math.max(FileTableColumnModel.MIN_WIDTH_, - newPos[i + 1] - newPos[i]); + this.columns_[i].width = + Math.max(FileTableColumnModel.MIN_WIDTH_, newPos[i + 1] - newPos[i]); } } }; @@ -270,9 +270,7 @@ FileTableColumnModel.ColumnSnapshot.prototype.setWidth = function( index, width) { // Skip to resize 'selection' column - if (index < 0 || - index >= this.columnPos_.length - 1 || - !this.columnPos_) { + if (index < 0 || index >= this.columnPos_.length - 1 || !this.columnPos_) { return; } @@ -289,10 +287,9 @@ } for (let i = index + 1; i < this.columnPos_.length - 1; i++) { const posStart = this.columnPos_[index + 1]; - this.newPos[i] = (posEnd - newPosStart) * - (this.columnPos_[i] - posStart) / - (posEnd - posStart) + - newPosStart; + this.newPos[i] = (posEnd - newPosStart) * (this.columnPos_[i] - posStart) / + (posEnd - posStart) + + newPosStart; this.newPos[i] = round(this.newPos[i]); } this.newPos[index] = this.columnPos_[index]; @@ -323,9 +320,8 @@ * @param {number} deltaX Horizontal mouse move offset. */ FileTableSplitter.prototype.handleSplitterDragMove = function(deltaX) { - this.table_.columnModel.setWidthAndKeepTotal(this.columnIndex, - this.columnWidth_ + deltaX, - true); + this.table_.columnModel.setWidthAndKeepTotal( + this.columnIndex, this.columnWidth_ + deltaX, true); }; /** @@ -360,141 +356,138 @@ * @param {boolean} fullPage True if it's full page File Manager, * False if a file open/save dialog. */ -FileTable.decorate = (self, metadataModel, volumeManager, historyLoader, fullPage) => { - cr.ui.Table.decorate(self); - self.__proto__ = FileTable.prototype; - FileTableList.decorate(self.list); - self.list.setOnMergeItems(self.updateHighPriorityRange_.bind(self)); - self.metadataModel_ = metadataModel; - self.volumeManager_ = volumeManager; - self.historyLoader_ = historyLoader; +FileTable.decorate = + (self, metadataModel, volumeManager, historyLoader, fullPage) => { + cr.ui.Table.decorate(self); + self.__proto__ = FileTable.prototype; + FileTableList.decorate(self.list); + self.list.setOnMergeItems(self.updateHighPriorityRange_.bind(self)); + self.metadataModel_ = metadataModel; + self.volumeManager_ = volumeManager; + self.historyLoader_ = historyLoader; - /** @private {ListThumbnailLoader} */ - self.listThumbnailLoader_ = null; + /** @private {ListThumbnailLoader} */ + self.listThumbnailLoader_ = null; - /** @private {number} */ - self.beginIndex_ = 0; + /** @private {number} */ + self.beginIndex_ = 0; - /** @private {number} */ - self.endIndex_ = 0; + /** @private {number} */ + self.endIndex_ = 0; - /** @private {function(!Event)} */ - self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self); + /** @private {function(!Event)} */ + self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self); - /** - * Reflects the visibility of import status in the UI. Assumption: import - * status is only enabled in import-eligible locations. See - * ImportController#onDirectoryChanged. For this reason, the code in this - * class checks if import status is visible, and if so, assumes that all the - * files are in an import-eligible location. - * TODO(kenobi): Clean this up once import status is queryable from metadata. - * - * @private {boolean} - */ - self.importStatusVisible_ = true; + /** + * Reflects the visibility of import status in the UI. Assumption: import + * status is only enabled in import-eligible locations. See + * ImportController#onDirectoryChanged. For this reason, the code in this + * class checks if import status is visible, and if so, assumes that all + * the files are in an import-eligible location. + * TODO(kenobi): Clean this up once import status is queryable from + * metadata. + * + * @private {boolean} + */ + self.importStatusVisible_ = true; - /** @private {boolean} */ - self.useModificationByMeTime_ = false; + /** @private {boolean} */ + self.useModificationByMeTime_ = false; - const nameColumn = new cr.ui.table.TableColumn( - 'name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324); - nameColumn.renderFunction = self.renderName_.bind(self); + const nameColumn = new cr.ui.table.TableColumn( + 'name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324); + nameColumn.renderFunction = self.renderName_.bind(self); - const sizeColumn = new cr.ui.table.TableColumn( - 'size', str('SIZE_COLUMN_LABEL'), 110, true); - sizeColumn.renderFunction = self.renderSize_.bind(self); - sizeColumn.defaultOrder = 'desc'; + const sizeColumn = new cr.ui.table.TableColumn( + 'size', str('SIZE_COLUMN_LABEL'), 110, true); + sizeColumn.renderFunction = self.renderSize_.bind(self); + sizeColumn.defaultOrder = 'desc'; - const statusColumn = new cr.ui.table.TableColumn( - 'status', str('STATUS_COLUMN_LABEL'), 60, true); - statusColumn.renderFunction = self.renderStatus_.bind(self); - statusColumn.visible = self.importStatusVisible_; + const statusColumn = new cr.ui.table.TableColumn( + 'status', str('STATUS_COLUMN_LABEL'), 60, true); + statusColumn.renderFunction = self.renderStatus_.bind(self); + statusColumn.visible = self.importStatusVisible_; - const typeColumn = new cr.ui.table.TableColumn( - 'type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110); - typeColumn.renderFunction = self.renderType_.bind(self); + const typeColumn = new cr.ui.table.TableColumn( + 'type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110); + typeColumn.renderFunction = self.renderType_.bind(self); - const modTimeColumn = new cr.ui.table.TableColumn( - 'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210); - modTimeColumn.renderFunction = self.renderDate_.bind(self); - modTimeColumn.defaultOrder = 'desc'; + const modTimeColumn = new cr.ui.table.TableColumn( + 'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210); + modTimeColumn.renderFunction = self.renderDate_.bind(self); + modTimeColumn.defaultOrder = 'desc'; - const columns = [ - nameColumn, - sizeColumn, - statusColumn, - typeColumn, - modTimeColumn - ]; + const columns = + [nameColumn, sizeColumn, statusColumn, typeColumn, modTimeColumn]; - const columnModel = new FileTableColumnModel(columns); + const columnModel = new FileTableColumnModel(columns); - self.columnModel = columnModel; + self.columnModel = columnModel; - self.formatter_ = new FileMetadataFormatter(); + self.formatter_ = new FileMetadataFormatter(); - const selfAsTable = /** @type {!cr.ui.Table} */ (self); - selfAsTable.setRenderFunction( - self.renderTableRow_.bind(self, selfAsTable.getRenderFunction())); + const selfAsTable = /** @type {!cr.ui.Table} */ (self); + selfAsTable.setRenderFunction( + self.renderTableRow_.bind(self, selfAsTable.getRenderFunction())); - // Keep focus on the file list when clicking on the header. - selfAsTable.header.addEventListener('mousedown', e => { - self.list.focus(); - e.preventDefault(); - }); + // Keep focus on the file list when clicking on the header. + selfAsTable.header.addEventListener('mousedown', e => { + self.list.focus(); + e.preventDefault(); + }); - self.relayoutRateLimiter_ = - new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self)); + self.relayoutRateLimiter_ = + new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self)); - // Override header#redraw to use FileTableSplitter. - /** @this {cr.ui.table.TableHeader} */ - selfAsTable.header.redraw = function() { - this.__proto__.redraw.call(this); - // Extend table splitters - const splitters = this.querySelectorAll('.table-header-splitter'); - for (let i = 0; i < splitters.length; i++) { - if (splitters[i] instanceof FileTableSplitter) { - continue; - } - FileTableSplitter.decorate(splitters[i]); - } - }; + // Override header#redraw to use FileTableSplitter. + /** @this {cr.ui.table.TableHeader} */ + selfAsTable.header.redraw = function() { + this.__proto__.redraw.call(this); + // Extend table splitters + const splitters = this.querySelectorAll('.table-header-splitter'); + for (let i = 0; i < splitters.length; i++) { + if (splitters[i] instanceof FileTableSplitter) { + continue; + } + FileTableSplitter.decorate(splitters[i]); + } + }; - // Save the last selection. This is used by shouldStartDragSelection. - self.list.addEventListener('mousedown', function(e) { - this.lastSelection_ = this.selectionModel.selectedIndexes; - }.bind(self), true); - self.list.addEventListener('touchstart', function(e) { - this.lastSelection_ = this.selectionModel.selectedIndexes; - }.bind(self), true); - self.list.shouldStartDragSelection = - self.shouldStartDragSelection_.bind(self); - self.list.hasDragHitElement = self.hasDragHitElement_.bind(self); + // Save the last selection. This is used by shouldStartDragSelection. + self.list.addEventListener('mousedown', function(e) { + this.lastSelection_ = this.selectionModel.selectedIndexes; + }.bind(self), true); + self.list.addEventListener('touchstart', function(e) { + this.lastSelection_ = this.selectionModel.selectedIndexes; + }.bind(self), true); + self.list.shouldStartDragSelection = + self.shouldStartDragSelection_.bind(self); + self.list.hasDragHitElement = self.hasDragHitElement_.bind(self); - /** - * Obtains the index list of elements that are hit by the point or the - * rectangle. - * - * @param {number} x X coordinate value. - * @param {number} y Y coordinate value. - * @param {number=} opt_width Width of the coordinate. - * @param {number=} opt_height Height of the coordinate. - * @return {Array<number>} Index list of hit elements. - * @this {cr.ui.List} - */ - self.list.getHitElements = function(x, y, opt_width, opt_height) { - const currentSelection = []; - const bottom = y + (opt_height || 0); - for (let i = 0; i < this.selectionModel_.length; i++) { - const itemMetrics = this.getHeightsForIndex(i); - if (itemMetrics.top < bottom && - itemMetrics.top + itemMetrics.height >= y) { - currentSelection.push(i); - } - } - return currentSelection; - }; -}; + /** + * Obtains the index list of elements that are hit by the point or the + * rectangle. + * + * @param {number} x X coordinate value. + * @param {number} y Y coordinate value. + * @param {number=} opt_width Width of the coordinate. + * @param {number=} opt_height Height of the coordinate. + * @return {Array<number>} Index list of hit elements. + * @this {cr.ui.List} + */ + self.list.getHitElements = function(x, y, opt_width, opt_height) { + const currentSelection = []; + const bottom = y + (opt_height || 0); + for (let i = 0; i < this.selectionModel_.length; i++) { + const itemMetrics = this.getHeightsForIndex(i); + if (itemMetrics.top < bottom && + itemMetrics.top + itemMetrics.height >= y) { + currentSelection.push(i); + } + } + return currentSelection; + }; + }; /** * Updates high priority range of list thumbnail loader based on current @@ -568,8 +561,7 @@ assertInstanceof(box, HTMLDivElement), event.dataUrl, true /* with animation */); } else { - this.clearThumbnailImage_( - assertInstanceof(box, HTMLDivElement)); + this.clearThumbnailImage_(assertInstanceof(box, HTMLDivElement)); } } } @@ -593,12 +585,12 @@ container.style.webkitBoxOrient = 'vertical'; // Select at most MAXIMUM_ROWS_TO_MEASURE items around visible area. - const items = this.list.getItemsInViewPort(this.list.scrollTop, - this.list.clientHeight); - const firstIndex = Math.floor(Math.max(0, - (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2)); - const lastIndex = Math.min(this.dataModel.length, - firstIndex + MAXIMUM_ROWS_TO_MEASURE); + const items = + this.list.getItemsInViewPort(this.list.scrollTop, this.list.clientHeight); + const firstIndex = Math.floor( + Math.max(0, (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2)); + const lastIndex = + Math.min(this.dataModel.length, firstIndex + MAXIMUM_ROWS_TO_MEASURE); for (let i = firstIndex; i < lastIndex; i++) { const item = this.dataModel.item(i); const div = this.ownerDocument.createElement('div'); @@ -744,8 +736,8 @@ const label = /** @type {!HTMLDivElement} */ (this.ownerDocument.createElement('div')); - const mimeType = this.metadataModel_.getCache([entry], - ['contentMimeType'])[0].contentMimeType; + const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; const locationInfo = this.volumeManager_.getLocationInfo(entry); const icon = filelist.renderFileTypeIcon( this.ownerDocument, entry, locationInfo, mimeType); @@ -789,8 +781,7 @@ * @private */ FileTable.prototype.updateSize_ = function(div, entry) { - const metadata = this.metadataModel_.getCache( - [entry], ['size', 'hosted'])[0]; + const metadata = this.metadataModel_.getCache([entry], ['size', 'hosted'])[0]; const size = metadata.size; const hosted = metadata.hosted; div.textContent = this.formatter_.formatSize(size, hosted); @@ -806,8 +797,8 @@ * @private */ FileTable.prototype.renderStatus_ = function(entry, columnId, table) { - const div = /** @type {!HTMLDivElement} */ ( - this.ownerDocument.createElement('div')); + const div = + /** @type {!HTMLDivElement} */ (this.ownerDocument.createElement('div')); div.className = 'status status-icon'; if (entry) { this.updateStatus_(div, entry); @@ -839,8 +830,8 @@ /** @param {!importer.ImportHistory} history */ history => { return Promise.all([ - history.wasImported(fileEntry, destination), - history.wasCopied(fileEntry, destination) + history.wasImported(fileEntry, destination), + history.wasCopied(fileEntry, destination) ]); }) .then( @@ -864,11 +855,12 @@ * @private */ FileTable.prototype.updateStatus_ = function(div, entry) { - this.getImportStatus_(entry, importer.Destination.GOOGLE_DRIVE).then( - /** @param {string} status */ - status => { - div.setAttribute('file-status-icon', status); - }); + this.getImportStatus_(entry, importer.Destination.GOOGLE_DRIVE) + .then( + /** @param {string} status */ + status => { + div.setAttribute('file-status-icon', status); + }); }; /** @@ -885,10 +877,10 @@ (this.ownerDocument.createElement('div')); div.className = 'type'; - const mimeType = this.metadataModel_.getCache([entry], - ['contentMimeType'])[0].contentMimeType; - div.textContent = FileListModel.getFileTypeString( - FileType.getType(entry, mimeType)); + const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; + div.textContent = + FileListModel.getFileTypeString(FileType.getType(entry, mimeType)); // For removable partitions, display file system type. if (!mimeType && entry.volumeInfo && entry.volumeInfo.diskFileSystemType) { @@ -1034,7 +1026,8 @@ // Set thumbnail if it's already in cache. const thumbnailData = this.listThumbnailLoader_ ? - this.listThumbnailLoader_.getThumbnailFromCache(entry) : null; + this.listThumbnailLoader_.getThumbnailFromCache(entry) : + null; if (thumbnailData && thumbnailData.dataUrl) { this.setThumbnailImage_( box, this.listThumbnailLoader_.getThumbnailFromCache(entry).dataUrl,
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js index da8d0a12..d0821cd 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
@@ -248,7 +248,9 @@ * @this {cr.ui.ListSelectionController} */ filelist.handleTap = function(e, index, eventType) { - const sm = /** @type {!FileListSelectionModel|!FileListSingleSelectionModel} */ + const sm = /** + @type {!FileListSelectionModel|!FileListSingleSelectionModel} + */ (this.selectionModel); if (eventType == FileTapHandler.TapEvent.TWO_FINGER_TAP) { // Prepare to open the context menu in the same manner as the right click. @@ -346,13 +348,15 @@ * @this {cr.ui.ListSelectionController} */ filelist.handlePointerDownUp = function(e, index) { - const sm = /** @type {!FileListSelectionModel|!FileListSingleSelectionModel} */ - (this.selectionModel); + const sm = /** + @type {!FileListSelectionModel|!FileListSingleSelectionModel} + */ + (this.selectionModel); const anchorIndex = sm.anchorIndex; const isDown = (e.type == 'mousedown'); const isTargetCheckmark = e.target.classList.contains('detail-checkmark') || - e.target.classList.contains('checkmark'); + e.target.classList.contains('checkmark'); // If multiple selection is allowed and the checkmark is clicked without // modifiers(Ctrl/Shift), the click should toggle the item's selection. // (i.e. same behavior as Ctrl+Click) @@ -458,8 +462,10 @@ return; } - const sm = /** @type {!FileListSelectionModel|!FileListSingleSelectionModel} */ - (this.selectionModel); + const sm = /** + @type {!FileListSelectionModel|!FileListSingleSelectionModel} + */ + (this.selectionModel); let newIndex = -1; const leadIndex = sm.leadIndex; let prevent = true;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js index 1af2089d..1fa82390 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.js
@@ -107,9 +107,9 @@ // Add FileTableList file entries, then draw and focus the table list. const entries = [ - new FakeEntry('entry1-label', VolumeManagerCommon.RootType.CROSTINI), - new FakeEntry('entry2-label', VolumeManagerCommon.RootType.CROSTINI), - new FakeEntry('entry3-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry1-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry2-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry3-label', VolumeManagerCommon.RootType.CROSTINI), ]; const dataModel = new FileListModel(metadataModel); dataModel.splice(0, 0, ...entries); @@ -238,9 +238,9 @@ // Add FileTableList file entries, then draw and focus the table list. const entries = [ - new FakeEntry('entry1-label', VolumeManagerCommon.RootType.CROSTINI), - new FakeEntry('entry2-label', VolumeManagerCommon.RootType.CROSTINI), - new FakeEntry('entry3-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry1-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry2-label', VolumeManagerCommon.RootType.CROSTINI), + new FakeEntry('entry3-label', VolumeManagerCommon.RootType.CROSTINI), ]; const dataModel = new FileListModel(metadataModel); dataModel.splice(0, 0, ...entries);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js index c824daf..d4c504e 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.js
@@ -107,7 +107,7 @@ // Change some column widths, then capture then. for (let i = 0; i < model.size; i++) { - model.setWidth(i, (i+1) * 50); + model.setWidth(i, (i + 1) * 50); } // Hide a column. model.setVisible(INDEX, false); @@ -134,7 +134,7 @@ // Change some column widths, then capture then. for (let i = 0; i < model.size; i++) { - model.setWidth(i, (i+1) * 50); + model.setWidth(i, (i + 1) * 50); } // Hide a column. model.setVisible(INDEX, false); @@ -163,7 +163,7 @@ // Change some column widths, then capture then. for (let i = 0; i < model.size; i++) { - model.setWidth(i, (i+1) * 50); + model.setWidth(i, (i + 1) * 50); } // Verify the precondition. assertTrue(model.isVisible(INDEX));
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js index 112cef7..c3952896 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js +++ b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js
@@ -89,15 +89,21 @@ } this.setMenuAsAnimating_(menu, true /* animating */); - const player = menu.animate([{ - opacity: 1, - offset: 0 - }, { - opacity: 0, - offset: 1 - }], 300); + const player = menu.animate( + [ + { + opacity: 1, + offset: 0, + }, + { + opacity: 0, + offset: 1, + }, + ], + 300); - player.addEventListener('finish', + player.addEventListener( + 'finish', this.setMenuAsAnimating_.bind(this, menu, false /* not animating */)); }, @@ -149,8 +155,8 @@ return this.hidden_; } - return Object.getOwnPropertyDescriptor( - HTMLElement.prototype, 'hidden').get.call(this); + return Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'hidden') + .get.call(this); }, /** @@ -164,8 +170,8 @@ return; } - Object.getOwnPropertyDescriptor( - HTMLElement.prototype, 'hidden').set.call(this, value); + Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'hidden') + .set.call(this, value); }, /** @@ -198,6 +204,6 @@ }; return { - FilesMenuItem: FilesMenuItem + FilesMenuItem: FilesMenuItem, }; });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js index 6c6b7475..349be8c 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js +++ b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
@@ -50,9 +50,8 @@ * @const * @private */ - this.volumeSpaceOuterBar_ = assertInstanceof( - this.volumeSpaceInnerBar_.parentElement, - HTMLElement); + this.volumeSpaceOuterBar_ = + assertInstanceof(this.volumeSpaceInnerBar_.parentElement, HTMLElement); /** * @type {!HTMLElement}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/list_container.js b/ui/file_manager/file_manager/foreground/js/ui/list_container.js index eae48256..f2eb1d3 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/list_container.js +++ b/ui/file_manager/file_manager/foreground/js/ui/list_container.js
@@ -296,7 +296,8 @@ const item = this.currentList.getListItemAncestor(node); // TODO(serya): list should check that. return item && this.currentList.isItem(item) ? - assertInstanceof(item, cr.ui.ListItem) : null; + assertInstanceof(item, cr.ui.ListItem) : + null; }; /** @@ -386,9 +387,7 @@ */ ListContainer.prototype.onKeyPress_ = function(event) { // Ignore keypress handler in the rename input box. - if (event.srcElement.tagName == 'INPUT' || - event.ctrlKey || - event.metaKey || + if (event.srcElement.tagName == 'INPUT' || event.ctrlKey || event.metaKey || event.altKey) { event.stopImmediatePropagation(); return; @@ -396,8 +395,8 @@ const now = new Date(); const character = String.fromCharCode(event.charCode).toLowerCase(); - const text = now - this.textSearchState.date > 1000 ? '' : - this.textSearchState.text; + const text = + now - this.textSearchState.date > 1000 ? '' : this.textSearchState.text; this.textSearchState.text = text + character; this.textSearchState.date = now;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js index f081ca4..ac11e59 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js +++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -98,12 +98,12 @@ displayRootFullPath = '/other'; } displayRootUrl = this.replaceRootName_(displayRootUrl, displayRootFullPath); - const sharedWithMeFakeEntry = locationInfo.volumeInfo.fakeEntries[ - VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME]; + const sharedWithMeFakeEntry = + locationInfo.volumeInfo + .fakeEntries[VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME]; components.push(new LocationLine.PathComponent( str('DRIVE_SHARED_WITH_ME_COLLECTION_LABEL'), - sharedWithMeFakeEntry.toURL(), - sharedWithMeFakeEntry)); + sharedWithMeFakeEntry.toURL(), sharedWithMeFakeEntry)); } else if ( locationInfo.rootType === VolumeManagerCommon.RootType.SHARED_DRIVE) { displayRootUrl = this.replaceRootName_( @@ -140,7 +140,8 @@ // currentUrl should be without trailing slash. let currentUrl = /^.+\/$/.test(displayRootUrl) ? - displayRootUrl.slice(0, displayRootUrl.length - 1) : displayRootUrl; + displayRootUrl.slice(0, displayRootUrl.length - 1) : + displayRootUrl; // Add directory components to the target path. const paths = relativePath.split('/'); @@ -272,8 +273,8 @@ const lastCrumbSeparatorWidth = lastSeparator.getBoundingClientRect().width; // Current directory name may occupy up to 70% of space or even more if the // path is short. - let maxPathWidth = Math.max(Math.round(containerWidth * 0.3), - containerWidth - currentWidth); + let maxPathWidth = + Math.max(Math.round(containerWidth * 0.3), containerWidth - currentWidth); maxPathWidth = Math.min(pathWidth, maxPathWidth); const parentCrumb = lastSeparator.previousSibling; @@ -291,8 +292,8 @@ // Show sign of hidden crumbs like this: // root > some di... > ... > current directory. parentCrumb.setAttribute('collapsed', ''); - collapsedWidth = Math.min(maxPathWidth, - parentCrumb.getBoundingClientRect().width); + collapsedWidth = + Math.min(maxPathWidth, parentCrumb.getBoundingClientRect().width); maxPathWidth -= collapsedWidth; if (parentCrumb.getBoundingClientRect().width != collapsedWidth) { parentCrumb.style.width = collapsedWidth + 'px'; @@ -318,7 +319,7 @@ // If the current separator and the following crumb don't fit in the // breadcrumbs area, hide remaining separators and crumbs. if (pathWidth + item.getBoundingClientRect().width + minCrumbWidth > - maxPathWidth) { + maxPathWidth) { item.setAttribute('hidden', ''); maxPathWidth = pathWidth; } else { @@ -337,8 +338,8 @@ } } - currentWidth = Math.min(currentWidth, - containerWidth - pathWidth - collapsedWidth); + currentWidth = + Math.min(currentWidth, containerWidth - pathWidth - collapsedWidth); this.breadcrumbs_.lastChild.style.width = (currentWidth - lastCrumbSeparatorWidth) + 'px'; };
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js index b03f433c..7a6589e 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
@@ -188,6 +188,7 @@ this.positionSubMenu_(item, subMenu); subMenu.show(); subMenu.parentMenuItem = item; + this.moveSelectionToSubMenu_(subMenu); } }, @@ -234,6 +235,7 @@ this.menu.selectedItem = null; this.currentMenu = subMenu; subMenu.selectedIndex = 0; + subMenu.focusSelectedItem(); }, /** @@ -245,6 +247,7 @@ subMenu.selectedItem = null; this.currentMenu = this.menu; this.menu.selectedItem = subMenu.parentMenuItem; + this.menu.focusSelectedItem(); }, /** @@ -570,6 +573,10 @@ if (!this.respondToArrowKeys) { break; } + // Hide any showing sub-menu if we're moving in the parent + if (this.currentMenu === this.menu) { + this.hideSubMenu_(); + } case 'Enter': case ' ': if (!this.isMenuShown()) {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js index b6735142..ef2eaa3 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.js
@@ -222,6 +222,8 @@ const subMenuPosition = subMenu.getBoundingClientRect(); // Reduce window innerHeight so sub-menu won't fit. window.innerHeight = subMenuPosition.bottom - 10; + // Navigate from sub-menu to the parent menu. + sendKeyDown('#test-menu-button', 'ArrowLeft'); // Call the internal hide method, then re-show it // to force the resizing behavior. menubutton.hideSubMenu_(); @@ -242,6 +244,8 @@ testShrinkWindowSizesSubMenu(); // Make the window taller than the sub-menu plus padding. window.innerHeight = subMenuPosition.bottom + 20; + // Navigate from sub-menu to the parent menu. + sendKeyDown('#test-menu-button', 'ArrowLeft'); // Call the internal hide method, then re-show it // to force the resizing behavior. menubutton.hideSubMenu_(); @@ -273,12 +277,8 @@ */ function testNavigateFromMenuToSubMenu() { prepareForKeyboardNavigation(); - // Check that the hosting menu-item is selected. + // Check that the hosting menu-item is not selected. const hostItem = document.querySelector('#host-sub-menu'); - assertTrue(hostItem.hasAttribute('selected')); - // Navigate across to the sub-menu using the keyboard. - sendKeyDown('#test-menu-button', 'ArrowRight'); - // Check that the host menu-item loses selection. assertFalse(hostItem.hasAttribute('selected')); // Check that the sub-menu has taken selection. const subItem = document.querySelector('#first'); @@ -313,3 +313,22 @@ assertTrue(hostItem.hasAttribute('selected')); assertFalse(firstItem.hasAttribute('selected')); } + +/** + * Tests that arrow up on the top level menu hides the + * sub menu when the sub-menu is visible. + */ +function testTopMenuArrowUpDismissesSubMenu() { + prepareForKeyboardNavigation(); + // Check that the hosting menu-item is not selected. + const hostItem = document.querySelector('#host-sub-menu'); + assertFalse(hostItem.hasAttribute('selected')); + // Navigate from sub-menu to the parent menu. + sendKeyDown('#test-menu-button', 'ArrowLeft'); + // Check that the hosting menu-item is not selected. + assertTrue(hostItem.hasAttribute('selected')); + // Navigate up the main menu. + sendKeyDown('#test-menu-button', 'ArrowUp'); + // Check that the sub-menu has been hidden. + assertTrue(subMenu.hasAttribute('hidden')); +}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js index 1915061..39230b43 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js
@@ -72,20 +72,18 @@ * @return {!Promise} Promise fulfilled with the result of dialog. If the dialog * is already opened, it returns null. */ -MultiProfileShareDialog.prototype.showMultiProfileShareDialog = - function(plural) { +MultiProfileShareDialog.prototype.showMultiProfileShareDialog = function( + plural) { return this.currentProfileId_.then(currentProfileId => { return new Promise((fulfill, reject) => { this.shareTypeSelect_.selectedIndex = 0; this.mailLabel_.textContent = currentProfileId; const result = FileManagerDialogBase.prototype.showOkCancelDialog.call( this, - str(plural ? - 'MULTI_PROFILE_SHARE_DIALOG_TITLE_PLURAL' : - 'MULTI_PROFILE_SHARE_DIALOG_TITLE'), - str(plural ? - 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE_PLURAL' : - 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE'), + str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_TITLE_PLURAL' : + 'MULTI_PROFILE_SHARE_DIALOG_TITLE'), + str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE_PLURAL' : + 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE'), () => { fulfill(this.shareTypeSelect_.value); },
diff --git a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js index 0f698b7..3e8049f 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js +++ b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
@@ -81,8 +81,8 @@ element = /** @type {ProgressCenterItemElement} */ (element); element.state_ = ProgressItemState.PROGRESSING; element.track_ = element.querySelector('.progress-track'); - element.track_.addEventListener('transitionend', - element.onTransitionEnd_.bind(element)); + element.track_.addEventListener( + 'transitionend', element.onTransitionEnd_.bind(element)); element.cancelTransition_ = null; return element; }; @@ -125,17 +125,19 @@ // Set track width. const setWidth = ((nextWidthFrame) => { - const currentWidthRate = parseInt(this.track_.style.width, 10); - // Prevent assigning the same width to avoid stopping the animation. - // animated == false may be intended to cancel the animation, so in that - // case, the assignment should be done. - if (currentWidthRate === nextWidthFrame && animated) { - return; - } - this.track_.hidden = false; - this.track_.style.width = nextWidthFrame + '%'; - this.track_.classList.toggle('animated', animated); - }).bind(null, item.progressRateInPercent); + const currentWidthRate = + parseInt(this.track_.style.width, 10); + // Prevent assigning the same width to avoid stopping the + // animation. animated == false may be intended to cancel + // the animation, so in that case, the assignment should be + // done. + if (currentWidthRate === nextWidthFrame && animated) { + return; + } + this.track_.hidden = false; + this.track_.style.width = nextWidthFrame + '%'; + this.track_.classList.toggle('animated', animated); + }).bind(null, item.progressRateInPercent); if (animated) { this.cancelTransition_ = @@ -167,8 +169,7 @@ } this.track_.classList.remove('animated'); this.dispatchEvent(new Event( - ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, - {bubbles: true})); + ProgressCenterItemElement.PROGRESS_ANIMATION_END_EVENT, {bubbles: true})); }; /** @@ -208,8 +209,8 @@ * @type {CSSKeyframesRule} * @private */ - this.toggleAnimation_ = ProgressCenterPanel.getToggleAnimation_( - element.ownerDocument); + this.toggleAnimation_ = + ProgressCenterPanel.getToggleAnimation_(element.ownerDocument); /** * Item group for normal priority items. @@ -230,20 +231,15 @@ * @type {Object<string>} * @private */ - this.itemQuery_ = Object.preventExtensions({ - normal: 'li:not(.quiet)', - quiet: 'li.quiet' - }); + this.itemQuery_ = + Object.preventExtensions({normal: 'li:not(.quiet)', quiet: 'li.quiet'}); /** * Timeout IDs of the inactive state of each group. * @type {Object<?number>} * @private */ - this.timeoutId_ = Object.preventExtensions({ - normal: null, - quiet: null - }); + this.timeoutId_ = Object.preventExtensions({normal: null, quiet: null}); /** * Callback to be called with the ID of the progress item when the cancel @@ -338,7 +334,8 @@ */ ProgressCenterPanel.prototype.onItemAnimationEnd_ = function(event) { const targetGroup = event.target.classList.contains('quiet') ? - this.quietItemGroup_ : this.normalItemGroup_; + this.quietItemGroup_ : + this.normalItemGroup_; if (event.target === this.closeView_) { targetGroup.completeSummarizedItemAnimation(); } else { @@ -384,8 +381,8 @@ } // Update the view state. - this.closeView_.update(normalSummarizedItem, - this.normalItemGroup_.isSummarizedAnimated()); + this.closeView_.update( + normalSummarizedItem, this.normalItemGroup_.isSummarizedAnimated()); this.element_.hidden = false; return; } @@ -394,8 +391,8 @@ const quietSummarizedItem = this.quietItemGroup_.getSummarizedItem(this.normalItemGroup_.numErrors); if (quietSummarizedItem) { - this.closeView_.update(quietSummarizedItem, - this.quietItemGroup_.isSummarizedAnimated()); + this.closeView_.update( + quietSummarizedItem, this.quietItemGroup_.isSummarizedAnimated()); this.element_.hidden = false; return; }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/search_box.js b/ui/file_manager/file_manager/foreground/js/ui/search_box.js index 82c4eb1e..dcd6a22 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/search_box.js +++ b/ui/file_manager/file_manager/foreground/js/ui/search_box.js
@@ -37,8 +37,8 @@ * @const */ this.searchButtonToggleRipple_ = - /** @type {!FilesToggleRipple} */ (queryRequiredElement( - 'files-toggle-ripple', this.searchButton)); + /** @type {!FilesToggleRipple} */ ( + queryRequiredElement('files-toggle-ripple', this.searchButton)); /** * Text input of the search box. @@ -59,18 +59,13 @@ this.inputElement.addEventListener('focus', this.onFocus_.bind(this)); this.inputElement.addEventListener('blur', this.onBlur_.bind(this)); this.inputElement.ownerDocument.addEventListener( - 'dragover', - this.onDragEnter_.bind(this), - true); + 'dragover', this.onDragEnter_.bind(this), true); this.inputElement.ownerDocument.addEventListener( - 'dragend', - this.onDragEnd_.bind(this)); + 'dragend', this.onDragEnd_.bind(this)); this.searchButton.addEventListener( - 'click', - this.onSearchButtonClick_.bind(this)); + 'click', this.onSearchButtonClick_.bind(this)); this.clearButton_.addEventListener( - 'click', - this.onClearButtonClick_.bind(this)); + 'click', this.onClearButtonClick_.bind(this)); const dispatchItemSelect = cr.dispatchSimpleEvent.bind(cr, this, SearchBox.EventType.ITEM_SELECT); this.autocompleteList.handleEnterKeydown = dispatchItemSelect;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js index d68bec7..83b415b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js
@@ -93,8 +93,8 @@ * when the dialog is closed, with a result code and an optionally an * extension id, if an extension was installed. */ -SuggestAppsDialog.prototype.showByExtensionAndMime = - function(extension, mime, onDialogClosed) { +SuggestAppsDialog.prototype.showByExtensionAndMime = function( + extension, mime, onDialogClosed) { assert(extension && extension[0] === '.'); const options = {file_extension: extension.substr(1)}; if (mime) { @@ -113,12 +113,8 @@ */ SuggestAppsDialog.prototype.showProviders = function(onDialogClosed) { this.showInternal_( - { - file_system_provider: true - }, - str('SUGGEST_DIALOG_FOR_PROVIDERS_TITLE'), - null /* webStoreUrl */, - onDialogClosed); + {file_system_provider: true}, str('SUGGEST_DIALOG_FOR_PROVIDERS_TITLE'), + null /* webStoreUrl */, onDialogClosed); }; /** @@ -169,11 +165,11 @@ */ installWebstoreItem: function(itemId, callback) { chrome.webstoreWidgetPrivate.installWebstoreItem( - itemId, - false /* show installation prompt */, - () => { - callback(chrome.runtime.lastError ? - chrome.runtime.lastError.message || 'UNKNOWN ERROR' : null); + itemId, false /* show installation prompt */, () => { + callback( + chrome.runtime.lastError ? + chrome.runtime.lastError.message || 'UNKNOWN ERROR' : + null); }); }, @@ -229,8 +225,8 @@ * extension id, if an extension was installed. * @private */ -SuggestAppsDialog.prototype.showInternal_ = - function(options, title, webStoreUrl, onDialogClosed) { +SuggestAppsDialog.prototype.showInternal_ = function( + options, title, webStoreUrl, onDialogClosed) { this.text_.hidden = true; this.dialogText_ = ''; @@ -244,50 +240,49 @@ this.widget_.ready() .then(/** @return {!Promise} */ - () => { - tokenObtained = true; - return this.showDialog_(title); - }) + () => { + tokenObtained = true; + return this.showDialog_(title); + }) .then(/** @return {!Promise<CWSWidgetContainer.ResolveReason>} */ - () => { - dialogShown = true; - // This is not set before so it doesn't pollute state if the - // previous dialog hasn't finished hiding. - this.onDialogClosed_ = onDialogClosed; - return this.widget_.start(options, webStoreUrl); - }) + () => { + dialogShown = true; + // This is not set before so it doesn't pollute state if the + // previous dialog hasn't finished hiding. + this.onDialogClosed_ = onDialogClosed; + return this.widget_.start(options, webStoreUrl); + }) .then(/** @param {CWSWidgetContainer.ResolveReason} reason */ - reason => { - if (reason !== CWSWidgetContainer.ResolveReason.RESET) { - this.hide(); - } - }) - .catch( - error => { - console.error('Failed to start CWS widget: ' + error); + reason => { + if (reason !== CWSWidgetContainer.ResolveReason.RESET) { + this.hide(); + } + }) + .catch(error => { + console.error('Failed to start CWS widget: ' + error); - if (!dialogShown) { - // Reset any widget state set in |this.widget_.ready()|. The - // returned value is ignored because it doesn't influence the - // value reported by dialog. - this.widget_.finalizeAndGetResult(); + if (!dialogShown) { + // Reset any widget state set in |this.widget_.ready()|. The + // returned value is ignored because it doesn't influence the + // value reported by dialog. + this.widget_.finalizeAndGetResult(); - const result = tokenObtained ? - // Got access token but the widget dialog was not shown. - // Consider the widget was cancelled. - SuggestAppsDialog.Result.CANCELLED : - // Access token was unavailable. - // This can happen in the Guest mode. crbug.com/694419 - // Callback shows an alert notifying the file was not opened - // because of the unsupported type. - SuggestAppsDialog.Result.FAILED; - onDialogClosed(result, null); - return; - } + const result = tokenObtained ? + // Got access token but the widget dialog was not shown. + // Consider the widget was cancelled. + SuggestAppsDialog.Result.CANCELLED : + // Access token was unavailable. + // This can happen in the Guest mode. crbug.com/694419 + // Callback shows an alert notifying the file was not opened + // because of the unsupported type. + SuggestAppsDialog.Result.FAILED; + onDialogClosed(result, null); + return; + } - this.result_ = SuggestAppsDialog.Result.FAILED; - this.hide(); - }); + this.result_ = SuggestAppsDialog.Result.FAILED; + this.hide(); + }); }; /** @@ -297,16 +292,15 @@ */ SuggestAppsDialog.prototype.showDialog_ = function(title) { return new Promise((resolve, reject) => { - const success = this.dialogText_ ? - FileManagerDialogBase.prototype.showTitleAndTextDialog.call( - this, title, this.dialogText_) : - FileManagerDialogBase.prototype.showTitleOnlyDialog.call( - this, title); - if (!success) { - reject('SuggestAppsDialog cannot be shown.'); - return; - } - resolve(); + const success = this.dialogText_ ? + FileManagerDialogBase.prototype.showTitleAndTextDialog.call( + this, title, this.dialogText_) : + FileManagerDialogBase.prototype.showTitleOnlyDialog.call(this, title); + if (!success) { + reject('SuggestAppsDialog cannot be shown.'); + return; + } + resolve(); }); }; @@ -336,7 +330,7 @@ break; case CWSWidgetContainer.Result.WEBSTORE_LINK_OPENED: case CWSWidgetContainer.Result.USER_CANCEL: - this.result_ = SuggestAppsDialog.Result.CANCELLED; + this.result_ = SuggestAppsDialog.Result.CANCELLED; break; default: this.result_ = SuggestAppsDialog.Result.FAILED; @@ -345,8 +339,7 @@ this.installedItemId_ = widgetResult.installedItemId; FileManagerDialogBase.prototype.hide.call( - this, - this.onHide_.bind(this, opt_originalOnHide)); + this, this.onHide_.bind(this, opt_originalOnHide)); }; /**
diff --git a/ui/file_manager/integration_tests/file_manager/file_display.js b/ui/file_manager/integration_tests/file_manager/file_display.js index 7371e56..a6b44f56 100644 --- a/ui/file_manager/integration_tests/file_manager/file_display.js +++ b/ui/file_manager/integration_tests/file_manager/file_display.js
@@ -708,3 +708,13 @@ testcase.fileDisplayUnmountLastPartition = () => { return unmountRemovableVolume('partition-2'); }; + +/** + * Tests files display in Downloads while the default blocking file I/O task + * runner is blocked. + */ +testcase.fileDisplayDownloadsWithBlockedFileTaskRunner = async () => { + await sendTestMessage({name: 'blockFileTaskRunner'}); + await fileDisplay(RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET); + await sendTestMessage({name: 'unblockFileTaskRunner'}); +};
diff --git a/ui/file_manager/integration_tests/file_manager/metadata.js b/ui/file_manager/integration_tests/file_manager/metadata.js index 6faa401..c2d2e027 100644 --- a/ui/file_manager/integration_tests/file_manager/metadata.js +++ b/ui/file_manager/integration_tests/file_manager/metadata.js
@@ -340,4 +340,44 @@ chrome.test.assertEq(0, metadataStats.invalidateCount); }; +/** + * Tests that fetching content metadata from a DocumentsProvider completes. + */ +testcase.metadataDocumentsProvider = async () => { + const documentsProviderVolumeQuery = + '[has-children="true"] [volume-type-icon="documents_provider"]'; + + // Open Files app. + const appId = await openNewWindow(RootPath.DOWNLOADS); + + // Add files to the DocumentsProvider volume. + await addEntries(['documents_provider'], BASIC_LOCAL_ENTRY_SET); + + // Wait for the DocumentsProvider volume to mount. + await remoteCall.waitForElement(appId, documentsProviderVolumeQuery); + + // Click to open the DocumentsProvider volume. + chrome.test.assertTrue( + !!await remoteCall.callRemoteTestUtil( + 'fakeMouseClick', appId, [documentsProviderVolumeQuery]), + 'fakeMouseClick failed'); + + // Check: the DocumentsProvider files should appear in the file list. + const files = TestEntryInfo.getExpectedRows(BASIC_LOCAL_ENTRY_SET); + await remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}); + + // Select file hello.txt in the file list. + chrome.test.assertTrue( + !!await remoteCall.callRemoteTestUtil( + 'selectFile', appId, [ENTRIES.hello.nameText]), + 'selectFile failed'); + + // Check that a request for content metadata completes. + const result = await await remoteCall.callRemoteTestUtil( + 'getContentMetadata', appId, [['mediaMimeType']]); + + // Check nothing in the result was returned. + chrome.test.checkDeepEq([], result); +}; + })();
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 98ef95f..e2a8557 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -633,6 +633,8 @@ "text_utils_unittest.cc", ] + include_dirs = [ "//third_party/skia/include/private" ] + data = [ "test/data/", "$root_out_dir/ui_test.pak",
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc index 7cf67c3..b11485d 100644 --- a/ui/gfx/color_transform.cc +++ b/ui/gfx/color_transform.cc
@@ -9,9 +9,9 @@ #include <list> #include <memory> #include <sstream> +#include <utility> #include "base/logging.h" -#include "base/strings/stringprintf.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/third_party/skcms/skcms.h" #include "ui/gfx/color_space.h" @@ -259,6 +259,9 @@ size_t step_index) const { NOTREACHED(); } + virtual void AppendSkShaderSource(std::stringstream* src) const { + NOTREACHED(); + } private: DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); @@ -281,6 +284,7 @@ } bool CanGetShaderSource() const override; std::string GetShaderSource() const override; + std::string GetSkShaderSource() const override; bool IsIdentity() const override { return steps_.empty(); } size_t NumberOfStepsForTesting() const override { return steps_.size(); } @@ -308,6 +312,7 @@ void AppendShaderSource(std::stringstream* hdr, std::stringstream* src, size_t step_index) const override {} + void AppendSkShaderSource(std::stringstream* src) const override {} }; class ColorTransformMatrix : public ColorTransformStep { @@ -358,6 +363,28 @@ } } + void AppendSkShaderSource(std::stringstream* src) const override { + const SkMatrix44& m = matrix_.matrix(); + *src << " color = half4x4("; + *src << m.get(0, 0) << ", " << m.get(1, 0) << ", " << m.get(2, 0) << ", 0,"; + *src << endl; + *src << " "; + *src << m.get(0, 1) << ", " << m.get(1, 1) << ", " << m.get(2, 1) << ", 0,"; + *src << endl; + *src << " "; + *src << m.get(0, 2) << ", " << m.get(1, 2) << ", " << m.get(2, 2) << ", 0,"; + *src << endl; + *src << "0, 0, 0, 1)"; + *src << " * color;" << endl; + + // Only print the translational component if it isn't the identity. + if (m.get(0, 3) != 0.f || m.get(1, 3) != 0.f || m.get(2, 3) != 0.f) { + *src << " color += half4("; + *src << m.get(0, 3) << ", " << m.get(1, 3) << ", " << m.get(2, 3); + *src << ", 0);" << endl; + } + } + private: class Transform matrix_; }; @@ -386,7 +413,8 @@ std::stringstream* src, size_t step_index) const override { *hdr << "float TransferFn" << step_index << "(float v) {" << endl; - AppendTransferShaderSource(hdr); + AppendTransferShaderSource(hdr, true /* is_glsl */); + *hdr << " return v;" << endl; *hdr << "}" << endl; if (extended_) { *src << " color.r = sign(color.r) * TransferFn" << step_index @@ -402,10 +430,33 @@ } } + void AppendSkShaderSource(std::stringstream* src) const override { + if (extended_) { + *src << "{ half v = abs(color.r);" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.r = sign(color.r) * v; }" << endl; + *src << "{ half v = abs(color.g);" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.g = sign(color.g) * v; }" << endl; + *src << "{ half v = abs(color.b);" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.b = sign(color.b) * v; }" << endl; + } else { + *src << "{ half v = color.r;" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.r = v; }" << endl; + *src << "{ half v = color.g;" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.g = v; }" << endl; + *src << "{ half v = color.b;" << endl; + AppendTransferShaderSource(src, false /* is_glsl */); + *src << " color.b = v; }" << endl; + } + } + virtual float Evaluate(float x) const = 0; - // Populate the body of a shader function that takes a float v and returns - // Evaluate(v). - virtual void AppendTransferShaderSource(std::stringstream* src) const = 0; + virtual void AppendTransferShaderSource(std::stringstream* src, + bool is_glsl) const = 0; protected: // True if the transfer function is extended to be defined for all real @@ -446,7 +497,8 @@ // Note that the sign-extension is performed by the caller. return SkTransferFnEvalUnclamped(fn_, v); } - void AppendTransferShaderSource(std::stringstream* result) const override { + void AppendTransferShaderSource(std::stringstream* result, + bool is_glsl) const override { const float kEpsilon = 1.f / 1024.f; // Construct the linear segment @@ -473,8 +525,9 @@ nonlinear = nonlinear + " + " + Str(fn_.e); *result << " if (v < " << Str(fn_.d) << ")" << endl; - *result << " return " << linear << ";" << endl; - *result << " return " << nonlinear << ";" << endl; + *result << " v = " << linear << ";" << endl; + *result << " else" << endl; + *result << " v = " << nonlinear << ";" << endl; } private: @@ -492,57 +545,65 @@ // ColorTransformPerChannelTransferFn implementation: float Evaluate(float v) const override { return FromLinear(transfer_, v); } - void AppendTransferShaderSource(std::stringstream* src) const override { + void AppendTransferShaderSource(std::stringstream* src, + bool is_glsl) const override { + std::string scalar_type = is_glsl ? "float" : "half"; // This is a string-ized copy-paste from FromLinear. switch (transfer_) { case ColorSpace::TransferID::LOG: *src << " if (v < 0.01)\n" - " return 0.0;\n" - " return 1.0 + log(v) / log(10.0) / 2.0;\n"; + " v = 0.0;\n" + " else\n" + " v = 1.0 + log(v) / log(10.0) / 2.0;\n"; return; case ColorSpace::TransferID::LOG_SQRT: *src << " if (v < sqrt(10.0) / 1000.0)\n" - " return 0.0;\n" - " return 1.0 + log(v) / log(10.0) / 2.5;\n"; + " v = 0.0;\n" + " else\n" + " v = 1.0 + log(v) / log(10.0) / 2.5;\n"; return; case ColorSpace::TransferID::IEC61966_2_4: - *src << " float a = 1.099296826809442;\n" - " float b = 0.018053968510807;\n" - " if (v < -b)\n" - " return -a * pow(-v, 0.45) + (a - 1.0);\n" + *src << " " << scalar_type << " a = 1.099296826809442;\n" + << " " << scalar_type << " b = 0.018053968510807;\n" + << " if (v < -b)\n" + " v = -a * pow(-v, 0.45) + (a - 1.0);\n" " else if (v <= b)\n" - " return 4.5 * v;\n" - " return a * pow(v, 0.45) - (a - 1.0);\n"; + " v = 4.5 * v;\n" + " else\n" + " v = a * pow(v, 0.45) - (a - 1.0);\n"; return; case ColorSpace::TransferID::BT1361_ECG: - *src << " float a = 1.099;\n" - " float b = 0.018;\n" - " float l = 0.0045;\n" - " if (v < -l)\n" - " return -(a * pow(-4.0 * v, 0.45) + (a - 1.0)) / 4.0;\n" + *src << " " << scalar_type << " a = 1.099;\n" + << " " << scalar_type << " b = 0.018;\n" + << " " << scalar_type << " l = 0.0045;\n" + << " if (v < -l)\n" + " v = -(a * pow(-4.0 * v, 0.45) + (a - 1.0)) / 4.0;\n" " else if (v <= b)\n" - " return 4.5 * v;\n" - " return a * pow(v, 0.45) - (a - 1.0);\n"; + " v = 4.5 * v;\n" + " else\n" + " v = a * pow(v, 0.45) - (a - 1.0);\n"; return; case ColorSpace::TransferID::SMPTEST2084: *src << " v *= 80.0 / 10000.0;\n" " v = max(0.0, v);\n" - " float m1 = (2610.0 / 4096.0) / 4.0;\n" - " float m2 = (2523.0 / 4096.0) * 128.0;\n" - " float c1 = 3424.0 / 4096.0;\n" - " float c2 = (2413.0 / 4096.0) * 32.0;\n" - " float c3 = (2392.0 / 4096.0) * 32.0;\n" - " return pow((c1 + c2 * pow(v, m1)) / \n" - " (1.0 + c3 * pow(v, m1)), m2);\n"; + << " " << scalar_type << " m1 = (2610.0 / 4096.0) / 4.0;\n" + << " " << scalar_type << " m2 = (2523.0 / 4096.0) * 128.0;\n" + << " " << scalar_type << " c1 = 3424.0 / 4096.0;\n" + << " " << scalar_type << " c2 = (2413.0 / 4096.0) * 32.0;\n" + << " " << scalar_type + << " c3 = (2392.0 / 4096.0) * 32.0;\n" + " v = pow((c1 + c2 * pow(v, m1)) / \n" + " (1.0 + c3 * pow(v, m1)), m2);\n"; return; case ColorSpace::TransferID::ARIB_STD_B67: - *src << " const float a = 0.17883277;\n" - " const float b = 0.28466892;\n" - " const float c = 0.55991073;\n" - " v = max(0.0, v);\n" + *src << " " << scalar_type << " a = 0.17883277;\n" + << " " << scalar_type << " b = 0.28466892;\n" + << " " << scalar_type << " c = 0.55991073;\n" + << " v = max(0.0, v);\n" " if (v <= 1.0)\n" - " return 0.5 * sqrt(v);\n" - " return a * log(v - b) + c;\n"; + " v = 0.5 * sqrt(v);\n" + " else\n" + " v = a * log(v - b) + c;\n"; return; default: break; @@ -575,68 +636,79 @@ // ColorTransformPerChannelTransferFn implementation: float Evaluate(float v) const override { return ToLinear(transfer_, v); } - void AppendTransferShaderSource(std::stringstream* src) const override { - // This is a string-ized copy-paste from ToLinear. + + // This is a string-ized copy-paste from ToLinear. + void AppendTransferShaderSource(std::stringstream* src, + bool is_glsl) const override { + std::string scalar_type = is_glsl ? "float" : "half"; switch (transfer_) { case ColorSpace::TransferID::LOG: *src << " if (v < 0.0)\n" - " return 0.0;\n" - " return pow(10.0, (v - 1.0) * 2.0);\n"; + " v = 0.0;\n" + " else\n" + " v = pow(10.0, (v - 1.0) * 2.0);\n"; return; case ColorSpace::TransferID::LOG_SQRT: *src << " if (v < 0.0)\n" - " return 0.0;\n" - " return pow(10.0, (v - 1.0) * 2.5);\n"; + " v = 0.0;\n" + " else\n" + " v = pow(10.0, (v - 1.0) * 2.5);\n"; return; case ColorSpace::TransferID::IEC61966_2_4: - *src << " float a = 1.099296826809442;\n" - " float from_linear_neg_a = -1.047844;\n" - " float from_linear_b = 0.081243;\n" - " if (v < from_linear_neg_a)\n" - " return -pow((a - 1.0 - v) / a, 1.0 / 0.45);\n" + *src << " " << scalar_type << " a = 1.099296826809442;\n" + << " " << scalar_type << " from_linear_neg_a = -1.047844;\n" + << " " << scalar_type << " from_linear_b = 0.081243;\n" + << " if (v < from_linear_neg_a)\n" + " v = -pow((a - 1.0 - v) / a, 1.0 / 0.45);\n" " else if (v <= from_linear_b)\n" - " return v / 4.5;\n" - " return pow((v + a - 1.0) / a, 1.0 / 0.45);\n"; + " v = v / 4.5;\n" + " else\n" + " v = pow((v + a - 1.0) / a, 1.0 / 0.45);\n"; return; case ColorSpace::TransferID::BT1361_ECG: - *src << " float a = 1.099;\n" - " float from_linear_neg_l = -0.020250;\n" - " float from_linear_b = 0.081000;\n" - " if (v < from_linear_neg_l)\n" - " return -pow((1.0 - a - v * 4.0) / a, 1.0 / 0.45) / 4.0;\n" + *src << " " << scalar_type << " a = 1.099;\n" + << " " << scalar_type << " from_linear_neg_l = -0.020250;\n" + << " " << scalar_type << " from_linear_b = 0.081000;\n" + << " if (v < from_linear_neg_l)\n" + " v = -pow((1.0 - a - v * 4.0) / a, 1.0 / 0.45) / 4.0;\n" " else if (v <= from_linear_b)\n" - " return v / 4.5;\n" - " return pow((v + a - 1.0) / a, 1.0 / 0.45);\n"; + " v = v / 4.5;\n" + " else\n" + " v = pow((v + a - 1.0) / a, 1.0 / 0.45);\n"; return; case ColorSpace::TransferID::SMPTEST2084: *src << " v = max(0.0, v);\n" - " float m1 = (2610.0 / 4096.0) / 4.0;\n" - " float m2 = (2523.0 / 4096.0) * 128.0;\n" - " float c1 = 3424.0 / 4096.0;\n" - " float c2 = (2413.0 / 4096.0) * 32.0;\n" - " float c3 = (2392.0 / 4096.0) * 32.0;\n" - " #ifdef GL_FRAGMENT_PRECISION_HIGH\n" - " highp float v2 = v;\n" - " #else\n" - " float v2 = v;\n" - " #endif\n" - " v2 = pow(max(pow(v2, 1.0 / m2) - c1, 0.0) /\n" + << " " << scalar_type << " m1 = (2610.0 / 4096.0) / 4.0;\n" + << " " << scalar_type << " m2 = (2523.0 / 4096.0) * 128.0;\n" + << " " << scalar_type << " c1 = 3424.0 / 4096.0;\n" + << " " << scalar_type << " c2 = (2413.0 / 4096.0) * 32.0;\n" + << " " << scalar_type << " c3 = (2392.0 / 4096.0) * 32.0;\n"; + if (is_glsl) { + *src << " #ifdef GL_FRAGMENT_PRECISION_HIGH\n" + " highp float v2 = v;\n" + " #else\n" + " float v2 = v;\n" + " #endif\n"; + } else { + *src << " float v2 = v\n"; + } + *src << " v2 = pow(max(pow(v2, 1.0 / m2) - c1, 0.0) /\n" " (c2 - c3 * pow(v2, 1.0 / m2)), 1.0 / m1);\n" - " v = v2 * 10000.0 / 80.0;\n" - " return v;\n"; + " v = v2 * 10000.0 / 80.0;\n"; return; case ColorSpace::TransferID::SMPTEST2084_NON_HDR: *src << " v = max(0.0, v);\n" - " return min(2.3 * pow(v, 2.8), v / 5.0 + 0.8);\n"; + " v = min(2.3 * pow(v, 2.8), v / 5.0 + 0.8);\n"; return; case ColorSpace::TransferID::ARIB_STD_B67: *src << " v = max(0.0, v);\n" - " float a = 0.17883277;\n" - " float b = 0.28466892;\n" - " float c = 0.55991073;\n" - " if (v <= 0.5)\n" - " return (v * 2.0) * (v * 2.0);\n" - " return exp((v - c) / a) + b;\n"; + << " " << scalar_type << " a = 0.17883277;\n" + << " " << scalar_type << " b = 0.28466892;\n" + << " " << scalar_type << " c = 0.55991073;\n" + << " if (v <= 0.5)\n" + " v = (v * 2.0) * (v * 2.0);\n" + " else\n" + " v = exp((v - c) / a) + b;\n"; return; default: break; @@ -654,17 +726,17 @@ static float Luma(const ColorTransform::TriStim& c) { return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; } - static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) { - float maximum = max(max(c.x(), c.y()), c.z()); + static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim* c) { + float maximum = max(max(c->x(), c->y()), c->z()); if (maximum > 1.0f) { - float l = Luma(c); - c.Scale(1.0f / maximum); + float l = Luma(*c); + c->Scale(1.0f / maximum); ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); - c += white - black; + *c += white - black; } - return c; + return *c; } void Transform(ColorTransform::TriStim* colors, size_t num) const override { for (size_t i = 0; i < num; i++) { @@ -678,7 +750,7 @@ ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()), ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z())); smpte2084.Scale(Luma(ret) / Luma(smpte2084)); - ret = ClipToWhite(smpte2084); + ret = ClipToWhite(&smpte2084); } colors[i] = ret; } @@ -1011,6 +1083,14 @@ return hdr.str() + src.str(); } +std::string ColorTransformInternal::GetSkShaderSource() const { + std::stringstream src; + InitStringStream(&src); + for (const auto& step : steps_) + step->AppendSkShaderSource(&src); + return src.str(); +} + bool ColorTransformInternal::CanGetShaderSource() const { for (const auto& step : steps_) { if (!step->CanAppendShaderSource())
diff --git a/ui/gfx/color_transform.h b/ui/gfx/color_transform.h index 8120a7b..064ad1c 100644 --- a/ui/gfx/color_transform.h +++ b/ui/gfx/color_transform.h
@@ -5,6 +5,9 @@ #ifndef UI_GFX_COLOR_TRANSFORM_H_ #define UI_GFX_COLOR_TRANSFORM_H_ +#include <memory> +#include <string> + #include "base/macros.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/point3_f.h" @@ -33,6 +36,10 @@ virtual bool CanGetShaderSource() const = 0; virtual std::string GetShaderSource() const = 0; + // Return SKSL shader sources that modifies an "inout half4 color" according + // to this transform. Input and output are non-premultiplied alpha. + virtual std::string GetSkShaderSource() const = 0; + // Returns true if this transform is the identity. virtual bool IsIdentity() const = 0;
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc index 8ea3e21..b135c81 100644 --- a/ui/gfx/color_transform_unittest.cc +++ b/ui/gfx/color_transform_unittest.cc
@@ -3,9 +3,11 @@ // found in the LICENSE file. #include <tuple> +#include <vector> #include "base/logging.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/src/sksl/SkSLCompiler.h" #include "ui/gfx/color_space.h" #include "ui/gfx/color_transform.h" #include "ui/gfx/icc_profile.h" @@ -469,13 +471,17 @@ std::string expected = "float TransferFn1(float v) {\n" " if (v < 4.04499359e-02)\n" - " return 7.73993805e-02 * v;\n" - " return pow(9.47867334e-01 * v + 5.21326549e-02, 2.40000010e+00);\n" + " v = 7.73993805e-02 * v;\n" + " else\n" + " v = pow(9.47867334e-01 * v + 5.21326549e-02, 2.40000010e+00);\n" + " return v;\n" "}\n" "float TransferFn3(float v) {\n" " if (v < 0.00000000e+00)\n" - " return 0.00000000e+00 * v;\n" - " return pow(v, 3.57142866e-01);\n" + " v = 0.00000000e+00 * v;\n" + " else\n" + " v = pow(v, 3.57142866e-01);\n" + " return v;\n" "}\n" "vec3 DoColorConversion(vec3 color) {\n" " color = mat3(1.16438353e+00, 1.16438353e+00, 1.16438353e+00,\n" @@ -498,6 +504,34 @@ EXPECT_EQ(source, expected); } +// Checks that the generated SkSL fragment shaders can be parsed by +// SkSL::Compiler. +TEST(SimpleColorSpace, CanParseSkShaderSource) { + std::vector<ColorSpace> common_color_spaces = { + ColorSpace::CreateSRGB(), ColorSpace::CreateDisplayP3D65(), + ColorSpace::CreateExtendedSRGB(), ColorSpace::CreateSCRGBLinear(), + ColorSpace::CreateJpeg(), ColorSpace::CreateREC601(), + ColorSpace::CreateREC709()}; + for (const auto& src : common_color_spaces) { + for (const auto& dst : common_color_spaces) { + auto transform = ColorTransform::NewColorTransform( + src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL); + if (!transform->CanGetShaderSource()) + continue; + + std::string source = "void main(inout half4 color) {" + + transform->GetSkShaderSource() + "}"; + SkSL::Program::Settings settings; + SkSL::Compiler compiler; + auto program = compiler.convertProgram( + SkSL::Program::kPipelineStage_Kind, + SkSL::String(source.c_str(), source.length()), settings); + EXPECT_NE(nullptr, program.get()); + EXPECT_EQ(0, compiler.errorCount()) << compiler.errorText(); + } + } +} + class TransferTest : public testing::TestWithParam<ColorSpace::TransferID> {}; TEST_P(TransferTest, basicTest) { @@ -666,4 +700,4 @@ testing::ValuesIn(all_matrices), testing::ValuesIn(all_ranges), testing::ValuesIn(intents))); -} // namespace +} // namespace gfx
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc index cd57a888..a2ffb6c5 100644 --- a/ui/gl/android/android_surface_control_compat.cc +++ b/ui/gl/android/android_surface_control_compat.cc
@@ -44,6 +44,10 @@ ADATASPACE_BT2020_PQ = 163971072, }; +enum { + AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY = 1ULL << 11, +}; + // ASurfaceTransaction using pASurfaceTransaction_create = ASurfaceTransaction* (*)(void); using pASurfaceTransaction_delete = void (*)(ASurfaceTransaction*); @@ -278,10 +282,8 @@ // static bool SurfaceControl::IsSupported() { - if (!base::android::BuildInfo::GetInstance()->is_at_least_q()) { - LOG(ERROR) << "SurfaceControl requires at least Q"; + if (!base::android::BuildInfo::GetInstance()->is_at_least_q()) return false; - } return SurfaceControlMethods::Get().supported; } @@ -289,6 +291,12 @@ return ColorSpaceToADataSpace(color_space) != ADATASPACE_UNKNOWN; } +uint64_t SurfaceControl::RequiredUsage() { + if (!IsSupported()) + return 0u; + return AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY; +} + SurfaceControl::Surface::Surface() = default; SurfaceControl::Surface::Surface(const Surface& parent, const char* name) {
diff --git a/ui/gl/android/android_surface_control_compat.h b/ui/gl/android/android_surface_control_compat.h index 580621d..7a292f4 100644 --- a/ui/gl/android/android_surface_control_compat.h +++ b/ui/gl/android/android_surface_control_compat.h
@@ -35,6 +35,10 @@ // Returns true if overlays with |color_space| are supported by the platform. static bool SupportsColorSpace(const gfx::ColorSpace& color_space); + // Returns the usage flags required for using an AHardwareBuffer with the + // SurfaceControl API, if it is supported. + static uint64_t RequiredUsage(); + class GL_EXPORT Surface : public base::RefCounted<Surface> { public: Surface();
diff --git a/ui/gl/gl_glx_api_implementation.cc b/ui/gl/gl_glx_api_implementation.cc index d7903a2..8aba57c 100644 --- a/ui/gl/gl_glx_api_implementation.cc +++ b/ui/gl/gl_glx_api_implementation.cc
@@ -5,11 +5,13 @@ #include "ui/gl/gl_glx_api_implementation.h" #include "base/command_line.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface_glx.h" +#include "ui/gl/gl_version_info.h" namespace gl { @@ -120,7 +122,8 @@ } } -bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfoGLX(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { Display* display = glXGetCurrentDisplay(); const int kDefaultScreen = 0; const char* vendor = @@ -136,7 +139,32 @@ info->version = version; if (extensions) info->extensions = extensions; - info->direct_rendering = !!glXIsDirect(display, glXGetCurrentContext()); + if (glXIsDirect(display, glXGetCurrentContext())) { + info->direct_rendering_version = "2"; + bool using_mesa = gl_info.driver_vendor.find("Mesa") != std::string::npos || + gl_info.driver_version.find("Mesa") != std::string::npos; + if (using_mesa) { + std::vector<std::string> split_version = + base::SplitString(gl_info.driver_version, ".", base::TRIM_WHITESPACE, + base::SPLIT_WANT_ALL); + int ext_code, first_event, first_error; + unsigned major_num = 0; + base::StringToUint(split_version[0], &major_num); + // Mesa after version 17 will reliably use DRI3 when available. + if (major_num >= 17 && XQueryExtension(display, "DRI3", &ext_code, + &first_event, &first_error)) { + info->direct_rendering_version = "2.3"; + } else if (XQueryExtension(display, "DRI2", &ext_code, &first_event, + &first_error)) { + info->direct_rendering_version = "2.2"; + } else if (XQueryExtension(display, "DRI", &ext_code, &first_event, + &first_error)) { + info->direct_rendering_version = "2.1"; + } + } + } else { + info->direct_rendering_version = "1"; + } return true; }
diff --git a/ui/gl/gl_glx_api_implementation.h b/ui/gl/gl_glx_api_implementation.h index f3ac47ec..b75b5f03 100644 --- a/ui/gl/gl_glx_api_implementation.h +++ b/ui/gl/gl_glx_api_implementation.h
@@ -14,12 +14,14 @@ namespace gl { +struct GLVersionInfo; struct GLWindowSystemBindingInfo; GL_EXPORT void InitializeStaticGLBindingsGLX(); GL_EXPORT void InitializeDebugGLBindingsGLX(); GL_EXPORT void ClearBindingsGLX(); -GL_EXPORT bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info); +GL_EXPORT bool GetGLWindowSystemBindingInfoGLX(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info); GL_EXPORT void SetDisabledExtensionsGLX(const std::string& disabled_extensions); GL_EXPORT bool InitializeExtensionSettingsOneOffGLX();
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc index 9234bb6..89fcb5cf 100644 --- a/ui/gl/gl_implementation.cc +++ b/ui/gl/gl_implementation.cc
@@ -220,8 +220,8 @@ SetNullDrawGLBindingsEnabled(initial_enabled_); } -GLWindowSystemBindingInfo::GLWindowSystemBindingInfo() - : direct_rendering(true) {} +GLWindowSystemBindingInfo::GLWindowSystemBindingInfo() {} +GLWindowSystemBindingInfo::~GLWindowSystemBindingInfo() {} std::string GetGLExtensionsFromCurrentContext() { return GetGLExtensionsFromCurrentContext(g_current_gl_context);
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h index fd6290c..8a2b295 100644 --- a/ui/gl/gl_implementation.h +++ b/ui/gl/gl_implementation.h
@@ -39,10 +39,11 @@ struct GL_EXPORT GLWindowSystemBindingInfo { GLWindowSystemBindingInfo(); + ~GLWindowSystemBindingInfo(); std::string vendor; std::string version; std::string extensions; - bool direct_rendering; + std::string direct_rendering_version; }; using GLFunctionPointerType = void (*)();
diff --git a/ui/gl/init/gl_factory.h b/ui/gl/init/gl_factory.h index b6dfd9c..44200f0 100644 --- a/ui/gl/init/gl_factory.h +++ b/ui/gl/init/gl_factory.h
@@ -20,10 +20,12 @@ namespace gl { class GLContext; -struct GLContextAttribs; class GLShareGroup; class GLSurface; +struct GLContextAttribs; +struct GLVersionInfo; + namespace init { // Returns a list of allowed GL implementations. The default implementation will @@ -55,6 +57,7 @@ // Return information about the GL window system binding implementation (e.g., // EGL, GLX, WGL). Returns true if the information was retrieved successfully. GL_INIT_EXPORT bool GetGLWindowSystemBindingInfo( + const GLVersionInfo& gl_info, GLWindowSystemBindingInfo* info); // Creates a GL context that is compatible with the given surface.
diff --git a/ui/gl/init/gl_factory_android.cc b/ui/gl/init/gl_factory_android.cc index a9e2d4cc..490f8ba8 100644 --- a/ui/gl/init/gl_factory_android.cc +++ b/ui/gl/init/gl_factory_android.cc
@@ -70,7 +70,8 @@ return impls; } -bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfo(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { switch (GetGLImplementation()) { case kGLImplementationEGLGLES2: return GetGLWindowSystemBindingInfoEGL(info);
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc index 56b8916..62d29a7 100644 --- a/ui/gl/init/gl_factory_mac.cc +++ b/ui/gl/init/gl_factory_mac.cc
@@ -72,7 +72,8 @@ return impls; } -bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfo(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { return false; }
diff --git a/ui/gl/init/gl_factory_ozone.cc b/ui/gl/init/gl_factory_ozone.cc index 1dfbf40..faba8ea6 100644 --- a/ui/gl/init/gl_factory_ozone.cc +++ b/ui/gl/init/gl_factory_ozone.cc
@@ -23,9 +23,10 @@ return GetSurfaceFactoryOzone()->GetAllowedGLImplementations(); } -bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfo(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { if (HasGLOzone()) - return GetGLOzone()->GetGLWindowSystemBindingInfo(info); + return GetGLOzone()->GetGLWindowSystemBindingInfo(gl_info, info); return false; }
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc index 2fd24ae..973fc4f 100644 --- a/ui/gl/init/gl_factory_win.cc +++ b/ui/gl/init/gl_factory_win.cc
@@ -31,7 +31,8 @@ return impls; } -bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfo(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { switch (GetGLImplementation()) { case kGLImplementationDesktopGL: return GetGLWindowSystemBindingInfoWGL(info);
diff --git a/ui/gl/init/gl_factory_x11.cc b/ui/gl/init/gl_factory_x11.cc index 4a09c1c..f6efd5d10 100644 --- a/ui/gl/init/gl_factory_x11.cc +++ b/ui/gl/init/gl_factory_x11.cc
@@ -31,10 +31,11 @@ return impls; } -bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) { +bool GetGLWindowSystemBindingInfo(const GLVersionInfo& gl_info, + GLWindowSystemBindingInfo* info) { switch (GetGLImplementation()) { case kGLImplementationDesktopGL: - return GetGLWindowSystemBindingInfoGLX(info); + return GetGLWindowSystemBindingInfoGLX(gl_info, info); case kGLImplementationEGLGLES2: return GetGLWindowSystemBindingInfoEGL(info); default:
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc index a1def8d..dc37ecae 100644 --- a/ui/message_center/views/message_popup_view.cc +++ b/ui/message_center/views/message_popup_view.cc
@@ -113,6 +113,9 @@ void MessagePopupView::Show() { views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); + // Make the widget explicitly activatable as TYPE_POPUP is not activatable by + // default but we need focus for the inline reply textarea. + params.activatable = views::Widget::InitParams::ACTIVATABLE_YES; params.keep_on_top = true; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
diff --git a/ui/message_center/views/notification_button.cc b/ui/message_center/views/notification_button.cc index 5f92deff7..6f50e00 100644 --- a/ui/message_center/views/notification_button.cc +++ b/ui/message_center/views/notification_button.cc
@@ -78,7 +78,7 @@ } void NotificationButton::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { + const views::ViewHierarchyChangedDetails& details) { // We disable view hierarchy change detection in the parent // because it resets the hoverstate, which we do not want // when we update the view to contain a new label or image.
diff --git a/ui/message_center/views/notification_button.h b/ui/message_center/views/notification_button.h index 21d54c43..7567a6c 100644 --- a/ui/message_center/views/notification_button.h +++ b/ui/message_center/views/notification_button.h
@@ -32,7 +32,7 @@ int GetHeightForWidth(int width) const override; void OnFocus() override; void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; + const views::ViewHierarchyChangedDetails& details) override; // Overridden from views::Button: void StateChanged(ButtonState old_state) override;
diff --git a/ui/ozone/common/gl_ozone_egl.cc b/ui/ozone/common/gl_ozone_egl.cc index 95da3290..9666f5f 100644 --- a/ui/ozone/common/gl_ozone_egl.cc +++ b/ui/ozone/common/gl_ozone_egl.cc
@@ -56,6 +56,7 @@ } bool GLOzoneEGL::GetGLWindowSystemBindingInfo( + const gl::GLVersionInfo& gl_info, gl::GLWindowSystemBindingInfo* info) { return gl::GetGLWindowSystemBindingInfoEGL(info); }
diff --git a/ui/ozone/common/gl_ozone_egl.h b/ui/ozone/common/gl_ozone_egl.h index 1607c25..0364db36 100644 --- a/ui/ozone/common/gl_ozone_egl.h +++ b/ui/ozone/common/gl_ozone_egl.h
@@ -28,6 +28,7 @@ bool InitializeExtensionSettingsOneOffPlatform() override; void ShutdownGL() override; bool GetGLWindowSystemBindingInfo( + const gl::GLVersionInfo& gl_info, gl::GLWindowSystemBindingInfo* info) override; scoped_refptr<gl::GLContext> CreateGLContext( gl::GLShareGroup* share_group,
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn index d68ecdf..d95bd9b7 100644 --- a/ui/ozone/platform/drm/BUILD.gn +++ b/ui/ozone/platform/drm/BUILD.gn
@@ -46,6 +46,8 @@ "gpu/drm_gpu_display_manager.h", "gpu/drm_gpu_util.cc", "gpu/drm_gpu_util.h", + "gpu/drm_overlay_manager_gpu.cc", + "gpu/drm_overlay_manager_gpu.h", "gpu/drm_overlay_plane.cc", "gpu/drm_overlay_plane.h", "gpu/drm_overlay_validator.cc",
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc new file mode 100644 index 0000000..36f852c --- /dev/null +++ b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h" + +#include <utility> + +#include "base/bind.h" +#include "base/trace_event/trace_event.h" +#include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h" +#include "ui/ozone/public/overlay_surface_candidate.h" + +namespace ui { + +DrmOverlayManagerGpu::DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy) + : drm_thread_proxy_(drm_thread_proxy), weak_ptr_factory_(this) {} + +DrmOverlayManagerGpu::~DrmOverlayManagerGpu() = default; + +void DrmOverlayManagerGpu::SendOverlayValidationRequest( + const std::vector<OverlaySurfaceCandidate>& candidates, + gfx::AcceleratedWidget widget) { + TRACE_EVENT_ASYNC_BEGIN0( + "hwoverlays", "DrmOverlayManagerGpu::SendOverlayValidationRequest", this); + + drm_thread_proxy_->CheckOverlayCapabilities( + widget, candidates, + base::BindOnce(&DrmOverlayManagerGpu::ReceiveOverlayValidationResponse, + weak_ptr_factory_.GetWeakPtr())); +} + +void DrmOverlayManagerGpu::ReceiveOverlayValidationResponse( + gfx::AcceleratedWidget widget, + const std::vector<OverlaySurfaceCandidate>& candidates, + const std::vector<OverlayStatus>& status) { + TRACE_EVENT_ASYNC_END0( + "hwoverlays", "DrmOverlayManagerGpu::SendOverlayValidationRequest", this); + + UpdateCacheForOverlayCandidates(candidates, status); +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h new file mode 100644 index 0000000..44d7d178 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_GPU_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_GPU_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "ui/ozone/platform/drm/common/drm_overlay_manager.h" + +namespace ui { +class DrmThreadProxy; + +// DrmOverlayManager implementation that runs in the GPU process. PostTasks +// overlay validations requests to the DRM thread. +class DrmOverlayManagerGpu : public DrmOverlayManager { + public: + explicit DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy); + ~DrmOverlayManagerGpu() override; + + // TODO(crbug.com/930173): Plumb some sort of display configuration + // information into this class. DrmOverlayManagerHost checks if the overlay + // candidates are contained by the display rect. The overlay configuration + // cache also needs to be reset when display configuration changes. + + private: + // DrmOverlayManager: + void SendOverlayValidationRequest( + const std::vector<OverlaySurfaceCandidate>& candidates, + gfx::AcceleratedWidget widget) override; + + void ReceiveOverlayValidationResponse( + gfx::AcceleratedWidget widget, + const std::vector<OverlaySurfaceCandidate>& candidates, + const std::vector<OverlayStatus>& status); + + DrmThreadProxy* const drm_thread_proxy_; + + base::WeakPtrFactory<DrmOverlayManagerGpu> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DrmOverlayManagerGpu); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_GPU_H_
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc index 4c97c66..6b0f4b8 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc +++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -4,6 +4,8 @@ #include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h" +#include <utility> + #include "base/bind.h" #include "ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h" #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" @@ -62,6 +64,19 @@ buffer, framebuffer)); } +void DrmThreadProxy::CheckOverlayCapabilities( + gfx::AcceleratedWidget widget, + const std::vector<OverlaySurfaceCandidate>& candidates, + OverlayCapabilitiesCallback callback) { + DCHECK(drm_thread_.task_runner()); + + drm_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&DrmThread::CheckOverlayCapabilities, + base::Unretained(&drm_thread_), widget, candidates, + CreateSafeOnceCallback(std::move(callback)))); +} + void DrmThreadProxy::AddBindingCursorDevice( ozone::mojom::DeviceCursorRequest request) { drm_thread_.task_runner()->PostTask(
diff --git a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h index f16bb1b2..dd72e7a 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread_proxy.h +++ b/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -6,22 +6,30 @@ #define UI_OZONE_PLATFORM_DRM_GPU_DRM_THREAD_PROXY_H_ #include <memory> +#include <vector> +#include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "ui/ozone/platform/drm/gpu/drm_thread.h" #include "ui/ozone/public/interfaces/device_cursor.mojom.h" +#include "ui/ozone/public/overlay_surface_candidate.h" namespace ui { class DrmWindowProxy; class InterThreadMessagingProxy; -// Mediates the communication between GPU main/IO threads and the DRM thread. It -// serves proxy objects that are safe to call on the GPU threads. The proxy -// objects then deal with safely posting the messages to the DRM thread. +// Mediates the communication between GPU main/compositor/IO threads and the DRM +// thread. It serves proxy objects that are safe to call on the GPU threads. The +// proxy objects then deal with safely posting the messages to the DRM thread. class DrmThreadProxy { public: + using OverlayCapabilitiesCallback = + base::OnceCallback<void(gfx::AcceleratedWidget, + const std::vector<OverlaySurfaceCandidate>&, + const std::vector<OverlayStatus>&)>; + DrmThreadProxy(); ~DrmThreadProxy(); @@ -48,6 +56,14 @@ std::unique_ptr<GbmBuffer>* buffer, scoped_refptr<DrmFramebuffer>* framebuffer); + // Checks if overlay |candidates| can be displayed asynchronously and then + // runs |callback|. Testing the overlay configuration requires posting a task + // to the DRM thread, but |callback| will be run on origin thread. + void CheckOverlayCapabilities( + gfx::AcceleratedWidget widget, + const std::vector<OverlaySurfaceCandidate>& candidates, + OverlayCapabilitiesCallback callback); + void AddBindingCursorDevice(ozone::mojom::DeviceCursorRequest request); void AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request);
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc index bb078a5d5..f8932280 100644 --- a/ui/ozone/platform/drm/ozone_platform_gbm.cc +++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -31,6 +31,7 @@ #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h" +#include "ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h" #include "ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h" #include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h" #include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" @@ -278,6 +279,11 @@ drm_thread_proxy_->BindThreadIntoMessagingProxy(itmp); } + if (args.viz_display_compositor) { + overlay_manager_ = + std::make_unique<DrmOverlayManagerGpu>(drm_thread_proxy_.get()); + } + // If InitializeGPU and InitializeUI are invoked on the same thread, startup // sequencing is complicated because tasks are queued on the unbound mojo // pipe connecting the UI (the host) to the DRM thread before the DRM thread
diff --git a/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/ui/ozone/platform/scenic/ozone_platform_scenic.cc index 7ef1eaaf..66e988f 100644 --- a/ui/ozone/platform/scenic/ozone_platform_scenic.cc +++ b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -132,14 +132,21 @@ } void InitializeGPU(const InitParams& params) override { - // TODO(spang, crbug.com/923445): Add message loop to GPU tests. - if (base::ThreadTaskRunnerHandle::IsSet()) { + if (params.single_process) { + if (!surface_factory_) { + // Without calling InitializeForUI, window surfaces cannot be created. + // Some test such as gpu_unittests do this. + // TODO(spang): This is not ideal; perhaps we should move the GL & + // vulkan initializers out of SurfaceFactoryOzone. + surface_factory_ = std::make_unique<ScenicSurfaceFactory>(nullptr); + } + } else { + DCHECK(!surface_factory_); scenic_gpu_service_ = std::make_unique<ScenicGpuService>( mojo::MakeRequest(&scenic_gpu_host_ptr_)); + surface_factory_ = + std::make_unique<ScenicSurfaceFactory>(scenic_gpu_host_ptr_.get()); } - DCHECK(!surface_factory_); - surface_factory_ = - std::make_unique<ScenicSurfaceFactory>(scenic_gpu_host_ptr_.get()); } base::MessageLoop::Type GetMessageLoopTypeForGpu() override {
diff --git a/ui/ozone/platform/scenic/scenic_surface_factory.cc b/ui/ozone/platform/scenic/scenic_surface_factory.cc index c896272..8187064 100644 --- a/ui/ozone/platform/scenic/scenic_surface_factory.cc +++ b/ui/ozone/platform/scenic/scenic_surface_factory.cc
@@ -137,6 +137,7 @@ std::unique_ptr<PlatformWindowSurface> ScenicSurfaceFactory::CreatePlatformWindowSurface( gfx::AcceleratedWidget widget) { + DCHECK(gpu_host_); auto surface = std::make_unique<ScenicSurface>(this, widget, CreateScenicSession()); main_thread_task_runner_->PostTask( @@ -202,11 +203,20 @@ fuchsia::ui::scenic::SessionPtr session; fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener_handle; auto listener_request = listener_handle.NewRequest(); - main_thread_task_runner_->PostTask( - FROM_HERE, + auto create_session_task = base::BindOnce(&ScenicSurfaceFactory::CreateScenicSessionOnMainThread, weak_ptr_factory_.GetWeakPtr(), session.NewRequest(), - listener_handle.Bind())); + listener_handle.Bind()); + if (main_thread_task_runner_->BelongsToCurrentThread()) { + // In a single threaded environment, we need to connect the session + // before returning so that synchronous calls do not deadlock the + // current thread. + std::move(create_session_task).Run(); + } else { + main_thread_task_runner_->PostTask(FROM_HERE, + std::move(create_session_task)); + } + return {std::move(session), std::move(listener_request)}; }
diff --git a/ui/ozone/platform/x11/gl_ozone_glx.cc b/ui/ozone/platform/x11/gl_ozone_glx.cc index ab78a370..a11dc42 100644 --- a/ui/ozone/platform/x11/gl_ozone_glx.cc +++ b/ui/ozone/platform/x11/gl_ozone_glx.cc
@@ -87,8 +87,9 @@ } bool GLOzoneGLX::GetGLWindowSystemBindingInfo( + const gl::GLVersionInfo& gl_info, gl::GLWindowSystemBindingInfo* info) { - return gl::GetGLWindowSystemBindingInfoGLX(info); + return gl::GetGLWindowSystemBindingInfoGLX(gl_info, info); } scoped_refptr<gl::GLContext> GLOzoneGLX::CreateGLContext(
diff --git a/ui/ozone/platform/x11/gl_ozone_glx.h b/ui/ozone/platform/x11/gl_ozone_glx.h index 2423800..0fd54f3 100644 --- a/ui/ozone/platform/x11/gl_ozone_glx.h +++ b/ui/ozone/platform/x11/gl_ozone_glx.h
@@ -24,6 +24,7 @@ bool InitializeExtensionSettingsOneOffPlatform() override; void ShutdownGL() override; bool GetGLWindowSystemBindingInfo( + const gl::GLVersionInfo& gl_info, gl::GLWindowSystemBindingInfo* info) override; scoped_refptr<gl::GLContext> CreateGLContext( gl::GLShareGroup* share_group,
diff --git a/ui/ozone/public/gl_ozone.h b/ui/ozone/public/gl_ozone.h index f406cfd..ba76bca 100644 --- a/ui/ozone/public/gl_ozone.h +++ b/ui/ozone/public/gl_ozone.h
@@ -17,9 +17,11 @@ namespace gl { class GLContext; -struct GLContextAttribs; class GLShareGroup; class GLSurface; + +struct GLContextAttribs; +struct GLVersionInfo; } namespace ui { @@ -58,6 +60,7 @@ // Returns information about the GL window system binding implementation (eg. // EGL, GLX, WGL). Returns true if the information was retrieved successfully. virtual bool GetGLWindowSystemBindingInfo( + const gl::GLVersionInfo& gl_info, gl::GLWindowSystemBindingInfo* info) = 0; // Creates a GL context that is compatible with the given surface.
diff --git a/ui/views/animation/ink_drop_event_handler.cc b/ui/views/animation/ink_drop_event_handler.cc index 19180f1..8eabb46 100644 --- a/ui/views/animation/ink_drop_event_handler.cc +++ b/ui/views/animation/ink_drop_event_handler.cc
@@ -98,6 +98,19 @@ } } +void InkDropEventHandler::OnViewHierarchyChanged( + View* observed_view, + const ViewHierarchyChangedDetails& details) { + DCHECK_EQ(host_view_, observed_view); + // If we're being removed hide the ink-drop so if we're highlighted now the + // highlight won't be active if we're added back again. + if (!details.is_add && details.child == host_view_ && + delegate_->HasInkDrop()) { + delegate_->GetInkDrop()->SnapToHidden(); + delegate_->GetInkDrop()->SetHovered(false); + } +} + void InkDropEventHandler::OnViewBoundsChanged(View* observed_view) { DCHECK_EQ(host_view_, observed_view); if (delegate_->HasInkDrop())
diff --git a/ui/views/animation/ink_drop_event_handler.h b/ui/views/animation/ink_drop_event_handler.h index c7d91c2..29e25e6 100644 --- a/ui/views/animation/ink_drop_event_handler.h +++ b/ui/views/animation/ink_drop_event_handler.h
@@ -17,9 +17,9 @@ } // namespace ui namespace views { -class View; class InkDrop; enum class InkDropState; +struct ViewHierarchyChangedDetails; // This class handles ink-drop changes due to events on its host. class VIEWS_EXPORT InkDropEventHandler : public ui::EventHandler, @@ -55,6 +55,9 @@ // ViewObserver: void OnViewVisibilityChanged(View* observed_view) override; + void OnViewHierarchyChanged( + View* observed_view, + const ViewHierarchyChangedDetails& details) override; void OnViewBoundsChanged(View* observed_view) override; void OnViewFocused(View* observed_view) override; void OnViewBlurred(View* observed_view) override;
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc index c199cc5..f524f1e4 100644 --- a/ui/views/animation/ink_drop_host_view.cc +++ b/ui/views/animation/ink_drop_host_view.cc
@@ -136,19 +136,6 @@ GetInkDrop()->AnimateToState(state); } -void InkDropHostView::ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) { - // If we're being removed hide the ink-drop so if we're highlighted now the - // highlight won't be active if we're added back again. - // TODO(pbos): Consider adding this to the ViewObserver model so that we can - // observe when the host gets removed. - if (!details.is_add && details.child == this && ink_drop_) { - GetInkDrop()->SnapToHidden(); - GetInkDrop()->SetHovered(false); - } - View::ViewHierarchyChanged(details); -} - std::unique_ptr<InkDropImpl> InkDropHostView::CreateDefaultInkDropImpl() { auto ink_drop = std::make_unique<InkDropImpl>(this, size()); ink_drop->SetAutoHighlightMode(
diff --git a/ui/views/animation/ink_drop_host_view.h b/ui/views/animation/ink_drop_host_view.h index 0574cad..d638cdf 100644 --- a/ui/views/animation/ink_drop_host_view.h +++ b/ui/views/animation/ink_drop_host_view.h
@@ -127,10 +127,6 @@ // Called after a new InkDrop instance is created. virtual void OnInkDropCreated() {} - // View: - void ViewHierarchyChanged( - const ViewHierarchyChangedDetails& details) override; - // Returns an InkDropImpl suitable for use with a square ink drop. // TODO(pbos): Rename to CreateDefaultSquareInkDropImpl. std::unique_ptr<InkDropImpl> CreateDefaultInkDropImpl();
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc index d8cf558..d5b6438 100644 --- a/ui/views/controls/button/md_text_button.cc +++ b/ui/views/controls/button/md_text_button.cc
@@ -128,9 +128,9 @@ // Skia counts the number of pixels outside the mask area whereas // gfx::ShadowValue counts together the number of pixels inside and outside // the mask bounds. - shadows.push_back(gfx::ShadowValue( + shadows.emplace_back( gfx::Vector2d(0, kYOffset), 2 * kSkiaBlurRadius, - SkColorSetA(shadow_color, is_dark_mode ? 0x7F : shadow_alpha))); + SkColorSetA(shadow_color, is_dark_mode ? 0x7F : shadow_alpha)); const SkColor fill_color = SkColorSetA(SK_ColorWHITE, is_prominent_ ? 0x0D : 0x05); return std::make_unique<InkDropHighlight>(
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc index 1ca6f75e..b30fd95c 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.cc +++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -16,6 +16,7 @@ #include "build/build_config.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/base/ime/text_input_type.h" #include "ui/base/models/combobox_model.h" #include "ui/base/models/combobox_model_observer.h" #include "ui/base/models/menu_model.h" @@ -26,6 +27,7 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image.h" +#include "ui/gfx/render_text.h" #include "ui/native_theme/native_theme.h" #include "ui/views/controls/editable_combobox/editable_combobox_listener.h" #include "ui/views/controls/menu/menu_runner.h" @@ -57,7 +59,7 @@ combobox_model_(combobox_model), filter_on_edit_(filter_on_edit), show_on_empty_(show_on_empty) { - UpdateItemsShown(base::string16()); + UpdateItemsShown(); combobox_model_->AddObserver(this); } @@ -65,16 +67,15 @@ combobox_model_->RemoveObserver(this); } - void UpdateItemsShown(const base::string16& text) { + void UpdateItemsShown() { if (!update_items_shown_enabled_) return; - text_ = text; items_shown_.clear(); items_shown_enabled_.clear(); - if (show_on_empty_ || !text.empty()) { + if (show_on_empty_ || !owner_->GetText().empty()) { for (int i = 0; i < combobox_model_->GetItemCount(); ++i) { if (!filter_on_edit_ || - base::StartsWith(combobox_model_->GetItemAt(i), text, + base::StartsWith(combobox_model_->GetItemAt(i), owner_->GetText(), base::CompareCase::INSENSITIVE_ASCII)) { items_shown_.push_back(combobox_model_->GetItemAt(i)); items_shown_enabled_.push_back(combobox_model_->IsItemEnabledAt(i)); @@ -92,7 +93,7 @@ ////////////////////////////////////////////////////////////////////////////// // Overridden from ComboboxModelObserver: void OnComboboxModelChanged(ui::ComboboxModel* model) override { - UpdateItemsShown(text_); + UpdateItemsShown(); } ////////////////////////////////////////////////////////////////////////////// @@ -103,7 +104,11 @@ base::string16 GetLabelAt(int index) const override { // Inserting the Unicode formatting characters if necessary so that the text // is displayed correctly in right-to-left UIs. - base::string16 text = items_shown_[index]; + base::string16 text = + owner_->showing_password_text_ + ? items_shown_[index] + : base::string16(items_shown_[index].length(), + gfx::RenderText::kPasswordReplacementChar); base::i18n::AdjustStringForLocaleDirection(&text); return text; } @@ -164,9 +169,6 @@ std::vector<base::string16> items_shown_; std::vector<bool> items_shown_enabled_; - // The current content of |owner_|'s textfield. - base::string16 text_; - // When false, UpdateItemsShown doesn't do anything. bool update_items_shown_enabled_ = true; @@ -179,9 +181,11 @@ std::unique_ptr<ui::ComboboxModel> combobox_model, const bool filter_on_edit, const bool show_on_empty, + const Type type, const int text_context, const int text_style) - : combobox_model_(std::move(combobox_model)), + : textfield_(new Textfield()), + combobox_model_(std::move(combobox_model)), menu_model_( std::make_unique<EditableComboboxMenuModel>(this, combobox_model_.get(), @@ -189,10 +193,15 @@ show_on_empty)), text_context_(text_context), text_style_(text_style), - textfield_(new Textfield()), - listener_(nullptr) { + type_(type), + listener_(nullptr), + showing_password_text_(type != Type::kPassword) { textfield_->AddObserver(this); textfield_->set_controller(this); + textfield_->SetFontList(GetFontList()); + textfield_->SetTextInputType((type == Type::kPassword) + ? ui::TEXT_INPUT_TYPE_PASSWORD + : ui::TEXT_INPUT_TYPE_TEXT); AddChildView(textfield_); SetLayoutManager(std::make_unique<views::FillLayout>()); } @@ -206,6 +215,14 @@ return textfield_->text(); } +void EditableCombobox::SetText(const base::string16& text) { + textfield_->SetText(text); + // SetText does not actually notify the TextfieldController, so we call the + // handling code directly. + HandleNewContent(text); + ShowDropDownMenu(); +} + const gfx::FontList& EditableCombobox::GetFontList() const { return style::GetFont(text_context_, text_style_); } @@ -218,6 +235,17 @@ textfield_->SetAssociatedLabel(labelling_view); } +void EditableCombobox::RevealPasswords(bool revealed) { + DCHECK_EQ(Type::kPassword, type_); + if (revealed == showing_password_text_) + return; + showing_password_text_ = revealed; + textfield_->SetTextInputType(revealed ? ui::TEXT_INPUT_TYPE_TEXT + : ui::TEXT_INPUT_TYPE_PASSWORD); + menu_model_->UpdateItemsShown(); + ShowDropDownMenu(); +} + int EditableCombobox::GetItemCountForTest() { return menu_model_->GetItemCount(); } @@ -226,14 +254,6 @@ return menu_model_->GetLabelAt(index); } -void EditableCombobox::SetTextForTest(const base::string16& text) { - textfield_->SetText(text); - // SetText does not actually notify the TextfieldController, so we call the - // handling code directly. - HandleNewContent(text); - ShowDropDownMenu(); -} - //////////////////////////////////////////////////////////////////////////////// // EditableCombobox, View overrides: @@ -266,10 +286,19 @@ // EditableCombobox, Private methods: void EditableCombobox::OnItemSelected(int index) { - textfield_->SetText(menu_model_->GetLabelAt(index)); + // We set |showing_password_text_| to true before calling GetLabelAt on the + // selected item so that even if it was false we still get the actual + // characters before setting them in the textfield, which can hide them on its + // own. Otherwise we would be setting + // gfx::RenderText::kPasswordReplacementChar characters. + bool showing_password_text = showing_password_text_; + showing_password_text_ = true; + base::string16 selected_item_text = menu_model_->GetLabelAt(index); + showing_password_text_ = showing_password_text; + textfield_->SetText(selected_item_text); // SetText does not actually notify the TextfieldController, so we call the // handling code directly. - HandleNewContent(menu_model_->GetLabelAt(index)); + HandleNewContent(selected_item_text); NotifyAccessibilityEvent(ax::mojom::Event::kValueChanged, /*xsend_native_event=*/true); } @@ -287,7 +316,7 @@ listener_->OnContentChanged(this); menu_model_->EnableUpdateItemsShown(); } - menu_model_->UpdateItemsShown(new_content); + menu_model_->UpdateItemsShown(); } void EditableCombobox::OnMenuClosed() {
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h index 9fba33c..9b1a1aa6 100644 --- a/ui/views/controls/editable_combobox/editable_combobox.h +++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -37,6 +37,11 @@ public TextfieldController, public ViewObserver { public: + enum class Type { + kRegular, + kPassword, + }; + // The class name. static const char kViewClassName[]; static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON; @@ -51,13 +56,14 @@ explicit EditableCombobox(std::unique_ptr<ui::ComboboxModel> combobox_model, bool filter_on_edit, bool show_on_empty, + Type type = Type::kRegular, int text_context = kDefaultTextContext, int text_style = kDefaultTextStyle); ~EditableCombobox() override; - // Gets the text currently in the textfield. const base::string16& GetText() const; + void SetText(const base::string16& text); const gfx::FontList& GetFontList() const; @@ -74,13 +80,16 @@ // is a label associated with this combobox. void SetAssociatedLabel(View* labelling_view); + // For Type::kPassword, sets whether the textfield and + // drop-down menu will reveal their current content. + void RevealPasswords(bool revealed); + // Accessors of private members for tests. ui::ComboboxModel* GetComboboxModelForTest() { return combobox_model_.get(); } int GetItemCountForTest(); base::string16 GetItemForTest(int index); MenuRunner* GetMenuRunnerForTest() { return menu_runner_.get(); } Textfield* GetTextfieldForTest() { return textfield_; } - void SetTextForTest(const base::string16& text); private: class EditableComboboxMenuModel; @@ -109,6 +118,8 @@ void OnViewFocused(View* observed_view) override; void OnViewBlurred(View* observed_view) override; + Textfield* textfield_; + std::unique_ptr<ui::ComboboxModel> combobox_model_; // The EditableComboboxMenuModel used by |menu_runner_|. @@ -122,7 +133,7 @@ // shown in the drop-down menu. const int text_style_; - Textfield* textfield_; + const Type type_; // Set while the drop-down is showing. std::unique_ptr<MenuRunner> menu_runner_; @@ -130,6 +141,10 @@ // Our listener. Not owned. Notified when the selected index changes. EditableComboboxListener* listener_; + // Whether we are currently showing the passwords for type + // Type::kPassword. + bool showing_password_text_; + DISALLOW_COPY_AND_ASSIGN(EditableCombobox); };
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index 8374ed2c..78b2113a8 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -24,6 +24,7 @@ #include "ui/events/test/event_generator.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/render_text.h" #include "ui/views/controls/editable_combobox/editable_combobox_listener.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/textfield/textfield.h" @@ -67,9 +68,11 @@ bool show_on_empty = true); // Initializes the combobox with the given items. - void InitEditableCombobox(const std::vector<base::string16>& items, - bool filter_on_edit, - bool show_on_empty = true); + void InitEditableCombobox( + const std::vector<base::string16>& items, + bool filter_on_edit, + bool show_on_empty = true, + EditableCombobox::Type type = EditableCombobox::Type::kRegular); // Initializes the widget where the combobox and the dummy control live. void InitWidget(); @@ -121,10 +124,11 @@ void EditableComboboxTest::InitEditableCombobox( const std::vector<base::string16>& items, const bool filter_on_edit, - const bool show_on_empty) { + const bool show_on_empty, + const EditableCombobox::Type type) { combobox_ = new EditableCombobox(std::make_unique<ui::SimpleComboboxModel>(items), - filter_on_edit, show_on_empty); + filter_on_edit, show_on_empty, type); listener_ = std::make_unique<DummyListener>(); combobox_->set_listener(listener_.get()); combobox_->set_id(1); @@ -269,7 +273,7 @@ InitEditableCombobox(); combobox_->GetTextfieldForTest()->RequestFocus(); - combobox_->SetTextForTest(ASCIIToUTF16("foo bar foobar")); + combobox_->SetText(ASCIIToUTF16("foo bar foobar")); SendKeyEvent(ui::VKEY_LEFT, /*alt=*/true, /*shift=*/false, /*ctrl_cmd=*/false); SendKeyEvent(ui::VKEY_LEFT, /*alt=*/true, /*shift=*/false, @@ -320,7 +324,7 @@ InitEditableCombobox(); combobox_->GetTextfieldForTest()->RequestFocus(); - combobox_->SetTextForTest(ASCIIToUTF16("foo bar foobar")); + combobox_->SetText(ASCIIToUTF16("foo bar foobar")); SendKeyEvent(ui::VKEY_LEFT, /*alt=*/false, /*shift=*/false, /*ctrl_cmd=*/true); SendKeyEvent(ui::VKEY_LEFT, /*alt=*/false, /*shift=*/false, @@ -491,7 +495,7 @@ ASCIIToUTF16("item1")}; InitEditableCombobox(items, /*filter_on_edit=*/false, /*show_on_empty=*/true); - combobox_->SetTextForTest(ASCIIToUTF16("z")); + combobox_->SetText(ASCIIToUTF16("z")); ASSERT_EQ(2, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("item0"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("item1"), combobox_->GetItemForTest(1)); @@ -509,15 +513,15 @@ ASSERT_EQ(ASCIIToUTF16("bac"), combobox_->GetItemForTest(2)); ASSERT_EQ(ASCIIToUTF16("bad"), combobox_->GetItemForTest(3)); - combobox_->SetTextForTest(ASCIIToUTF16("b")); + combobox_->SetText(ASCIIToUTF16("b")); ASSERT_EQ(2, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("bac"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("bad"), combobox_->GetItemForTest(1)); - combobox_->SetTextForTest(ASCIIToUTF16("bc")); + combobox_->SetText(ASCIIToUTF16("bc")); ASSERT_EQ(0, combobox_->GetItemCountForTest()); - combobox_->SetTextForTest(base::string16()); + combobox_->SetText(base::string16()); ASSERT_EQ(4, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("abc"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("abd"), combobox_->GetItemForTest(1)); @@ -535,12 +539,12 @@ ASSERT_EQ(ASCIIToUTF16("aBcD"), combobox_->GetItemForTest(1)); ASSERT_EQ(ASCIIToUTF16("xyz"), combobox_->GetItemForTest(2)); - combobox_->SetTextForTest(ASCIIToUTF16("abcd")); + combobox_->SetText(ASCIIToUTF16("abcd")); ASSERT_EQ(2, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("AbCd"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("aBcD"), combobox_->GetItemForTest(1)); - combobox_->SetTextForTest(ASCIIToUTF16("ABCD")); + combobox_->SetText(ASCIIToUTF16("ABCD")); ASSERT_EQ(2, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("AbCd"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("aBcD"), combobox_->GetItemForTest(1)); @@ -553,7 +557,7 @@ /*show_on_empty=*/false); ASSERT_EQ(0, combobox_->GetItemCountForTest()); - combobox_->SetTextForTest(ASCIIToUTF16("a")); + combobox_->SetText(ASCIIToUTF16("a")); ASSERT_EQ(2, combobox_->GetItemCountForTest()); ASSERT_EQ(ASCIIToUTF16("item0"), combobox_->GetItemForTest(0)); ASSERT_EQ(ASCIIToUTF16("item1"), combobox_->GetItemForTest(1)); @@ -565,9 +569,9 @@ InitEditableCombobox(items, /*filter_on_edit=*/false, /*show_on_empty=*/true); ASSERT_EQ(0, listener_->change_count()); - combobox_->SetTextForTest(ASCIIToUTF16("a")); + combobox_->SetText(ASCIIToUTF16("a")); ASSERT_EQ(1, listener_->change_count()); - combobox_->SetTextForTest(ASCIIToUTF16("ab")); + combobox_->SetText(ASCIIToUTF16("ab")); ASSERT_EQ(2, listener_->change_count()); } @@ -577,13 +581,36 @@ InitEditableCombobox(items, /*filter_on_edit=*/true, /*show_on_empty=*/true); ASSERT_EQ(0, listener_->change_count()); - combobox_->SetTextForTest(ASCIIToUTF16("i")); + combobox_->SetText(ASCIIToUTF16("i")); ASSERT_EQ(1, listener_->change_count()); - combobox_->SetTextForTest(ASCIIToUTF16("ix")); + combobox_->SetText(ASCIIToUTF16("ix")); ASSERT_EQ(2, listener_->change_count()); - combobox_->SetTextForTest(ASCIIToUTF16("ixy")); + combobox_->SetText(ASCIIToUTF16("ixy")); ASSERT_EQ(3, listener_->change_count()); } +TEST_F(EditableComboboxTest, PasswordCanBeHiddenAndRevealed) { + std::vector<base::string16> items = {ASCIIToUTF16("item0"), + ASCIIToUTF16("item1")}; + InitEditableCombobox(items, /*filter_on_edit=*/false, /*show_on_empty=*/true, + EditableCombobox::Type::kPassword); + + ASSERT_EQ(2, combobox_->GetItemCountForTest()); + ASSERT_EQ(base::string16(5, gfx::RenderText::kPasswordReplacementChar), + combobox_->GetItemForTest(0)); + ASSERT_EQ(base::string16(5, gfx::RenderText::kPasswordReplacementChar), + combobox_->GetItemForTest(1)); + + combobox_->RevealPasswords(/*revealed=*/true); + ASSERT_EQ(ASCIIToUTF16("item0"), combobox_->GetItemForTest(0)); + ASSERT_EQ(ASCIIToUTF16("item1"), combobox_->GetItemForTest(1)); + + combobox_->RevealPasswords(/*revealed=*/false); + ASSERT_EQ(base::string16(5, gfx::RenderText::kPasswordReplacementChar), + combobox_->GetItemForTest(0)); + ASSERT_EQ(base::string16(5, gfx::RenderText::kPasswordReplacementChar), + combobox_->GetItemForTest(1)); +} + } // namespace } // namespace views
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index e814f741..fe30059d 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -234,6 +234,10 @@ return display_text_ ? display_text_->GetDisplayText() : base::string16(); } +base::i18n::TextDirection Label::GetTextDirectionForTesting() { + return full_text_->GetDisplayTextDirection(); +} + bool Label::IsSelectionSupported() const { return !obscured() && full_text_->IsSelectionSupported(); }
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h index 44c0a27f..9df5c85 100644 --- a/ui/views/controls/label.h +++ b/ui/views/controls/label.h
@@ -189,6 +189,9 @@ // Get the text as displayed to the user, respecting the obscured flag. base::string16 GetDisplayTextForTesting(); + // Get the text direction, as displayed to the user. + base::i18n::TextDirection GetTextDirectionForTesting(); + // Returns true if the label can be made selectable. For example, links do not // support text selection. // Subclasses should override this function in case they want to selectively
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc index 6f24765..26dfed4 100644 --- a/ui/views/controls/label_unittest.cc +++ b/ui/views/controls/label_unittest.cc
@@ -23,10 +23,12 @@ #include "ui/events/test/event_generator.h" #include "ui/gfx/canvas.h" #include "ui/gfx/render_text.h" +#include "ui/gfx/text_constants.h" #include "ui/gfx/text_elider.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/border.h" #include "ui/views/controls/link.h" +#include "ui/views/style/typography.h" #include "ui/views/test/focus_manager_test.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget.h" @@ -899,6 +901,47 @@ EXPECT_TRUE(concrete_link.GetPreferredSize().IsEmpty()); } +TEST_F(LabelTest, CanForceDirectionality) { + Label bidi_text_force_url(ToRTL("0123456") + base::ASCIIToUTF16(".com"), 0, + style::STYLE_PRIMARY, + gfx::DirectionalityMode::DIRECTIONALITY_AS_URL); + EXPECT_EQ(base::i18n::TextDirection::LEFT_TO_RIGHT, + bidi_text_force_url.GetTextDirectionForTesting()); + + Label rtl_text_force_ltr(ToRTL("0123456"), 0, style::STYLE_PRIMARY, + gfx::DirectionalityMode::DIRECTIONALITY_FORCE_LTR); + EXPECT_EQ(base::i18n::TextDirection::LEFT_TO_RIGHT, + rtl_text_force_ltr.GetTextDirectionForTesting()); + + Label ltr_text_force_rtl(base::ASCIIToUTF16("0123456"), 0, + style::STYLE_PRIMARY, + gfx::DirectionalityMode::DIRECTIONALITY_FORCE_RTL); + EXPECT_EQ(base::i18n::TextDirection::RIGHT_TO_LEFT, + ltr_text_force_rtl.GetTextDirectionForTesting()); + + SetRTL(true); + Label ltr_use_ui(base::ASCIIToUTF16("0123456"), 0, style::STYLE_PRIMARY, + gfx::DirectionalityMode::DIRECTIONALITY_FROM_UI); + EXPECT_EQ(base::i18n::TextDirection::RIGHT_TO_LEFT, + ltr_use_ui.GetTextDirectionForTesting()); + + SetRTL(false); + Label rtl_use_ui(ToRTL("0123456"), 0, style::STYLE_PRIMARY, + gfx::DirectionalityMode::DIRECTIONALITY_FROM_UI); + EXPECT_EQ(base::i18n::TextDirection::LEFT_TO_RIGHT, + rtl_use_ui.GetTextDirectionForTesting()); +} + +TEST_F(LabelTest, DefaultDirectionalityIsFromText) { + Label ltr(base::ASCIIToUTF16("Foo")); + EXPECT_EQ(base::i18n::TextDirection::LEFT_TO_RIGHT, + ltr.GetTextDirectionForTesting()); + + Label rtl(ToRTL("0123456")); + EXPECT_EQ(base::i18n::TextDirection::RIGHT_TO_LEFT, + rtl.GetTextDirectionForTesting()); +} + TEST_F(LabelSelectionTest, Selectable) { // By default, labels don't support text selection. EXPECT_FALSE(label()->selectable());
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index b537932..6ae1820 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -464,7 +464,7 @@ state_.hot_button = hot_button_; hot_button_ = nullptr; // We're already showing, push the current state. - menu_stack_.push_back(std::make_pair(state_, std::move(pressed_lock_))); + menu_stack_.emplace_back(state_, std::move(pressed_lock_)); // The context menu should be owned by the same parent. DCHECK_EQ(owner_, parent); @@ -929,7 +929,7 @@ void MenuController::ViewHierarchyChanged( SubmenuView* source, - const View::ViewHierarchyChangedDetails& details) { + const ViewHierarchyChangedDetails& details) { if (!details.is_add) { // If the current mouse handler is removed, remove it as the handler. if (details.child == current_mouse_event_target_) {
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index 78e4224..a6e4b7d 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -172,7 +172,7 @@ void OnTouchEvent(SubmenuView* source, ui::TouchEvent* event); View* GetTooltipHandlerForPoint(SubmenuView* source, const gfx::Point& point); void ViewHierarchyChanged(SubmenuView* source, - const View::ViewHierarchyChangedDetails& details); + const ViewHierarchyChangedDetails& details); bool GetDropFormats(SubmenuView* source, int* formats,
diff --git a/ui/views/controls/menu/menu_model_adapter_unittest.cc b/ui/views/controls/menu/menu_model_adapter_unittest.cc index 8ebf856..79ecef2 100644 --- a/ui/views/controls/menu/menu_model_adapter_unittest.cc +++ b/ui/views/controls/menu/menu_model_adapter_unittest.cc
@@ -142,9 +142,8 @@ class SubmenuModel : public MenuModelBase { public: SubmenuModel() : MenuModelBase(kSubmenuIdBase) { - items_.push_back( - Item(TYPE_COMMAND, "submenu item 0", nullptr, false, true)); - items_.push_back(Item(TYPE_COMMAND, "submenu item 1", nullptr)); + items_.emplace_back(TYPE_COMMAND, "submenu item 0", nullptr, false, true); + items_.emplace_back(TYPE_COMMAND, "submenu item 1", nullptr); } ~SubmenuModel() override = default; @@ -156,8 +155,8 @@ class ActionableSubmenuModel : public MenuModelBase { public: ActionableSubmenuModel() : MenuModelBase(kActionableSubmenuIdBase) { - items_.push_back(Item(TYPE_COMMAND, "actionable submenu item 0", nullptr)); - items_.push_back(Item(TYPE_COMMAND, "actionable submenu item 1", nullptr)); + items_.emplace_back(TYPE_COMMAND, "actionable submenu item 0", nullptr); + items_.emplace_back(TYPE_COMMAND, "actionable submenu item 1", nullptr); } ~ActionableSubmenuModel() override = default; @@ -171,13 +170,13 @@ submenu_model_ = std::make_unique<SubmenuModel>(); actionable_submenu_model_ = std::make_unique<ActionableSubmenuModel>(); - items_.push_back(Item(TYPE_COMMAND, "command 0", nullptr, false, false)); - items_.push_back(Item(TYPE_CHECK, "check 1", nullptr)); - items_.push_back(Item(TYPE_SEPARATOR, "", nullptr)); - items_.push_back(Item(TYPE_SUBMENU, "submenu 3", submenu_model_.get())); - items_.push_back(Item(TYPE_RADIO, "radio 4", nullptr)); - items_.push_back(Item(TYPE_ACTIONABLE_SUBMENU, "actionable 5", - actionable_submenu_model_.get())); + items_.emplace_back(TYPE_COMMAND, "command 0", nullptr, false, false); + items_.emplace_back(TYPE_CHECK, "check 1", nullptr); + items_.emplace_back(TYPE_SEPARATOR, "", nullptr); + items_.emplace_back(TYPE_SUBMENU, "submenu 3", submenu_model_.get()); + items_.emplace_back(TYPE_RADIO, "radio 4", nullptr); + items_.emplace_back(TYPE_ACTIONABLE_SUBMENU, "actionable 5", + actionable_submenu_model_.get()); } ~RootModel() override = default;
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc index 2e5b731..0e33efb 100644 --- a/ui/views/controls/message_box_view.cc +++ b/ui/views/controls/message_box_view.cc
@@ -242,7 +242,7 @@ column_set->AddPaddingColumn(0, horizontal_insets.right()); } - views::View* message_contents = new views::View(); + auto message_contents = std::make_unique<views::View>(); // We explicitly set insets on the message contents instead of the scroll view // so that the scroll view borders are not capped by dialog insets. message_contents->SetBorder(CreateEmptyBorder(horizontal_insets)); @@ -254,7 +254,7 @@ scroll_view->ClipHeightTo(0, provider->GetDistanceMetric( DISTANCE_DIALOG_SCROLLABLE_AREA_MAX_HEIGHT)); - scroll_view->SetContents(message_contents); + scroll_view->SetContents(std::move(message_contents)); layout->StartRow(0, kMessageViewColumnSetId); layout->AddView(scroll_view);
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc index ceb423fe..1a2a40f9 100644 --- a/ui/views/controls/scroll_view.cc +++ b/ui/views/controls/scroll_view.cc
@@ -250,7 +250,7 @@ return scroll_view; } -void ScrollView::SetContents(View* a_view) { +void ScrollView::SetContentsImpl(std::unique_ptr<View> a_view) { // Protect against clients passing a contents view that has its own Layer. DCHECK(!a_view->layer()); if (ScrollsWithLayers()) { @@ -271,11 +271,19 @@ a_view->layer()->SetScrollable(contents_viewport_->bounds().size()); a_view->layer()->SetFillsBoundsOpaquely(fills_opaquely); } - SetHeaderOrContents(contents_viewport_, a_view, &contents_); + SetHeaderOrContents(contents_viewport_, std::move(a_view), &contents_); } -void ScrollView::SetHeader(View* header) { - SetHeaderOrContents(header_viewport_, header, &header_); +void ScrollView::SetContents(std::nullptr_t) { + SetContentsImpl(nullptr); +} + +void ScrollView::SetHeaderImpl(std::unique_ptr<View> a_header) { + SetHeaderOrContents(header_viewport_, std::move(a_header), &header_); +} + +void ScrollView::SetHeader(std::nullptr_t) { + SetHeaderImpl(nullptr); } void ScrollView::SetBackgroundColor(SkColor color) { @@ -696,15 +704,13 @@ } void ScrollView::SetHeaderOrContents(View* parent, - View* new_view, + std::unique_ptr<View> new_view, View** member) { - if (*member == new_view) - return; - delete *member; - *member = new_view; - if (*member) - parent->AddChildView(*member); + if (new_view.get()) + *member = parent->AddChildView(std::move(new_view)); + else + *member = nullptr; Layout(); }
diff --git a/ui/views/controls/scroll_view.h b/ui/views/controls/scroll_view.h index e0e279c..7a63d50 100644 --- a/ui/views/controls/scroll_view.h +++ b/ui/views/controls/scroll_view.h
@@ -5,7 +5,9 @@ #ifndef UI_VIEWS_CONTROLS_SCROLL_VIEW_H_ #define UI_VIEWS_CONTROLS_SCROLL_VIEW_H_ +#include <memory> #include <string> +#include <utility> #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" @@ -56,12 +58,24 @@ // Set the contents. Any previous contents will be deleted. The contents // is the view that needs to scroll. - void SetContents(View* a_view); + template <typename T> + T* SetContents(std::unique_ptr<T> a_view) { + T* content_view = a_view.get(); + SetContentsImpl(std::move(a_view)); + return content_view; + } + void SetContents(std::nullptr_t); const View* contents() const { return contents_; } View* contents() { return contents_; } // Sets the header, deleting the previous header. - void SetHeader(View* header); + template <typename T> + T* SetHeader(std::unique_ptr<T> a_header) { + T* header_view = a_header.get(); + SetHeaderImpl(std::move(a_header)); + return header_view; + } + void SetHeader(std::nullptr_t); // The background color can be configured in two distinct ways: // . By way of SetBackgroundThemeColorId(). This is the default and when @@ -146,9 +160,15 @@ // otherwise it doesn't. void UpdateViewportLayerForClipping(); - // Used internally by SetHeader() and SetContents() to reset the view. Sets - // |member| to |new_view|. If |new_view| is non-null it is added to |parent|. - void SetHeaderOrContents(View* parent, View* new_view, View** member); + void SetContentsImpl(std::unique_ptr<View> a_view); + void SetHeaderImpl(std::unique_ptr<View> a_header); + + // Used internally by SetHeaderImpl() and SetContentsImpl() to reset the view. + // Sets |member| to |new_view|. If |new_view| is non-null it is added to + // |parent|. + void SetHeaderOrContents(View* parent, + std::unique_ptr<View> new_view, + View** member); // Scrolls the minimum amount necessary to make the specified rectangle // visible, in the coordinates of the contents view. The specified rectangle
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc index 8b32877..dc2fba3 100644 --- a/ui/views/controls/scroll_view_unittest.cc +++ b/ui/views/controls/scroll_view_unittest.cc
@@ -4,6 +4,9 @@ #include "ui/views/controls/scroll_view.h" +#include <memory> +#include <utility> + #include "base/macros.h" #include "base/run_loop.h" #include "base/test/icu_test_util.h" @@ -192,10 +195,9 @@ View* InstallContents() { const gfx::Rect default_outer_bounds(0, 0, 100, 100); - View* contents = new View; - scroll_view_->SetContents(contents); + scroll_view_->SetContents(std::make_unique<View>()); scroll_view_->SetBoundsRect(default_outer_bounds); - return contents; + return scroll_view_->contents(); } protected: @@ -247,7 +249,7 @@ } // Adds a ScrollView with the given |contents_view| and does layout. - ScrollView* AddScrollViewWithContents(View* contents, + ScrollView* AddScrollViewWithContents(std::unique_ptr<View> contents, bool commit_layers = true) { #if defined(OS_MACOSX) scroller_style_.reset( @@ -258,7 +260,7 @@ widget_ = CreateTopLevelFramelessPlatformWidget(); ScrollView* scroll_view = new ScrollView(); - scroll_view->SetContents(contents); + scroll_view->SetContents(std::move(contents)); widget_->SetBounds(default_bounds); widget_->Show(); @@ -280,9 +282,9 @@ // Adds a ScrollView with a contents view of the given |size| and does layout. ScrollView* AddScrollViewWithContentSize(const gfx::Size& contents_size, bool commit_layers = true) { - View* contents = new View; + auto contents = std::make_unique<View>(); contents->SetSize(contents_size); - return AddScrollViewWithContents(contents, commit_layers); + return AddScrollViewWithContents(std::move(contents), commit_layers); } // Wait for a commit to be observed on the compositor. @@ -428,8 +430,7 @@ // contents whose height always matches the height of the viewport. TEST_F(ScrollViewTest, VerticalScrollbarDoesNotAppearUnnecessarily) { const gfx::Rect default_outer_bounds(0, 0, 100, 100); - View* contents = new VerticalResizingView; - scroll_view_->SetContents(contents); + scroll_view_->SetContents(std::make_unique<VerticalResizingView>()); scroll_view_->SetBoundsRect(default_outer_bounds); scroll_view_->Layout(); EXPECT_FALSE(scroll_view_->vertical_scroll_bar()->visible()); @@ -544,8 +545,7 @@ // Assertions around adding a header. TEST_F(ScrollViewTest, Header) { - CustomView* header = new CustomView; - scroll_view_->SetHeader(header); + auto* header = scroll_view_->SetHeader(std::make_unique<CustomView>()); View* header_parent = header->parent(); View* contents = InstallContents(); @@ -585,8 +585,7 @@ // Verifies the scrollbars are added as necessary when a header is present. TEST_F(ScrollViewTest, ScrollBarsWithHeader) { - CustomView* header = new CustomView; - scroll_view_->SetHeader(header); + auto* header = scroll_view_->SetHeader(std::make_unique<CustomView>()); View* contents = InstallContents(); header->SetPreferredSize(gfx::Size(10, 20)); @@ -657,12 +656,11 @@ // Verifies the header scrolls horizontally with the content. TEST_F(ScrollViewTest, HeaderScrollsWithContent) { ScrollViewTestApi test_api(scroll_view_.get()); - CustomView* contents = new CustomView; - scroll_view_->SetContents(contents); + auto contents = std::make_unique<CustomView>(); contents->SetPreferredSize(gfx::Size(500, 500)); + scroll_view_->SetContents(std::move(contents)); - CustomView* header = new CustomView; - scroll_view_->SetHeader(header); + auto* header = scroll_view_->SetHeader(std::make_unique<CustomView>()); header->SetPreferredSize(gfx::Size(500, 20)); scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); @@ -713,9 +711,9 @@ // Verifies ScrollRectToVisible() on the child works. TEST_F(ScrollViewTest, ScrollRectToVisible) { ScrollViewTestApi test_api(scroll_view_.get()); - CustomView* contents = new CustomView; - scroll_view_->SetContents(contents); + auto contents = std::make_unique<CustomView>(); contents->SetPreferredSize(gfx::Size(500, 1000)); + auto* contents_ptr = scroll_view_->SetContents(std::move(contents)); scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); scroll_view_->Layout(); @@ -723,7 +721,7 @@ // Scroll to y=405 height=10, this should make the y position of the content // at (405 + 10) - viewport_height (scroll region bottom aligned). - contents->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10)); + contents_ptr->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10)); const int viewport_height = test_api.contents_viewport()->height(); // Expect there to be a horizontal scrollbar, making the viewport shorter. @@ -733,20 +731,20 @@ EXPECT_EQ(415 - viewport_height, offset.y()); // Scroll to the current y-location and 10x10; should do nothing. - contents->ScrollRectToVisible(gfx::Rect(0, offset.y(), 10, 10)); + contents_ptr->ScrollRectToVisible(gfx::Rect(0, offset.y(), 10, 10)); EXPECT_EQ(415 - viewport_height, test_api.CurrentOffset().y()); } // Verifies that child scrolls into view when it's focused. TEST_F(ScrollViewTest, ScrollChildToVisibleOnFocus) { ScrollViewTestApi test_api(scroll_view_.get()); - CustomView* contents = new CustomView; - scroll_view_->SetContents(contents); + auto contents = std::make_unique<CustomView>(); contents->SetPreferredSize(gfx::Size(500, 1000)); + auto* contents_ptr = scroll_view_->SetContents(std::move(contents)); FixedView* child = new FixedView; child->SetPreferredSize(gfx::Size(10, 10)); child->SetPosition(gfx::Point(0, 405)); - contents->AddChildView(child); + contents_ptr->AddChildView(child); scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); scroll_view_->Layout(); @@ -771,8 +769,8 @@ scroll_view_->ClipHeightTo(kMinHeight, kMaxHeight); const int kNormalContentHeight = 75; - scroll_view_->SetContents( - new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight))); + scroll_view_->SetContents(std::make_unique<views::StaticSizedView>( + gfx::Size(kWidth, kNormalContentHeight))); EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view_->GetPreferredSize()); @@ -792,8 +790,8 @@ const int kShortContentHeight = 10; View* contents = - new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight)); - scroll_view_->SetContents(contents); + scroll_view_->SetContents(std::make_unique<views::StaticSizedView>( + gfx::Size(kWidth, kShortContentHeight))); EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view_->GetPreferredSize()); @@ -816,8 +814,8 @@ scroll_view_->ClipHeightTo(kMinHeight, kMaxHeight); const int kTallContentHeight = 1000; - scroll_view_->SetContents( - new views::StaticSizedView(gfx::Size(kWidth, kTallContentHeight))); + scroll_view_->SetContents(std::make_unique<views::StaticSizedView>( + gfx::Size(kWidth, kTallContentHeight))); EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view_->GetPreferredSize()); @@ -836,7 +834,8 @@ scroll_view_->ClipHeightTo(kMinHeight, kMaxHeight); // Create a view that will be much taller than it is wide. - scroll_view_->SetContents(new views::ProportionallySizedView(1000)); + scroll_view_->SetContents( + std::make_unique<views::ProportionallySizedView>(1000)); // Without any width, it will default to 0,0 but be overridden by min height. scroll_view_->SizeToPreferredSize(); @@ -1118,9 +1117,9 @@ TEST_F(ScrollViewTest, ContentScrollNotResetOnLayout) { ScrollViewTestApi test_api(scroll_view_.get()); - CustomView* contents = new CustomView; + auto* contents = scroll_view_->SetContents(std::make_unique<CustomView>()); + contents->SetPreferredSize(gfx::Size(300, 300)); - scroll_view_->SetContents(contents); scroll_view_->ClipHeightTo(0, 150); scroll_view_->SizeToPreferredSize(); // ScrollView preferred width matches that of |contents|, with the height @@ -1154,9 +1153,9 @@ ScrollViewTestApi test_api(scroll_view_.get()); // Set up with vertical scrollbar. - FixedView* contents = new FixedView; + auto contents = std::make_unique<FixedView>(); contents->SetPreferredSize(gfx::Size(kWidth, kMaxHeight * 5)); - scroll_view_->SetContents(contents); + scroll_view_->SetContents(std::move(contents)); scroll_view_->ClipHeightTo(0, kMaxHeight); // Make sure the size is set such that no horizontal scrollbar gets shown. @@ -1219,9 +1218,8 @@ ScrollViewTestApi test_api(scroll_view_.get()); // Set up with horizontal scrollbar. - FixedView* contents = new FixedView; + auto* contents = scroll_view_->SetContents(std::make_unique<FixedView>()); contents->SetPreferredSize(gfx::Size(kWidth * 5, kHeight)); - scroll_view_->SetContents(contents); // Make sure the size is set such that no vertical scrollbar gets shown. scroll_view_->SetSize(gfx::Size( @@ -1284,9 +1282,9 @@ ScrollViewTestApi test_api(scroll_view_.get()); // Set up with both horizontal and vertical scrollbars. - FixedView* contents = new FixedView; + auto contents = std::make_unique<FixedView>(); contents->SetPreferredSize(gfx::Size(kWidth * 5, kHeight * 5)); - scroll_view_->SetContents(contents); + scroll_view_->SetContents(std::move(contents)); // Make sure the size is set such that both scrollbars are shown. scroll_view_->SetSize(gfx::Size(kWidth, kHeight)); @@ -1410,18 +1408,18 @@ ScrollViewTestApi test_api(scroll_view_.get()); // Set up with vertical scrollbar and a header. - FixedView* contents = new FixedView; - CustomView* header = new CustomView; + auto contents = std::make_unique<FixedView>(); + auto header = std::make_unique<CustomView>(); contents->SetPreferredSize(gfx::Size(kWidth, kMaxHeight * 5)); - scroll_view_->SetContents(contents); header->SetPreferredSize(gfx::Size(10, 20)); - scroll_view_->SetHeader(header); - scroll_view_->ClipHeightTo(0, kMaxHeight + header->height()); + scroll_view_->SetContents(std::move(contents)); + auto* header_ptr = scroll_view_->SetHeader(std::move(header)); + scroll_view_->ClipHeightTo(0, kMaxHeight + header_ptr->height()); // Make sure the size is set such that no horizontal scrollbar gets shown. scroll_view_->SetSize( gfx::Size(kWidth + test_api.GetBaseScrollBar(VERTICAL)->GetThickness(), - kMaxHeight + header->height())); + kMaxHeight + header_ptr->height())); // Make sure the initial origin is 0,0 EXPECT_EQ(gfx::ScrollOffset(0, 0), test_api.CurrentOffset()); @@ -1508,33 +1506,35 @@ // Test that LocatedEvents are transformed correctly when scrolling. TEST_F(WidgetScrollViewTest, EventLocation) { // Set up with both scrollers. - CustomView* contents = new CustomView; + auto contents = std::make_unique<CustomView>(); + auto* contents_ptr = contents.get(); contents->SetPreferredSize(gfx::Size(kDefaultHeight * 5, kDefaultHeight * 5)); - AddScrollViewWithContents(contents); + AddScrollViewWithContents(std::move(contents)); const gfx::Point location_in_widget(10, 10); // Click without scrolling. TestClickAt(location_in_widget); - EXPECT_EQ(location_in_widget, contents->last_location()); + EXPECT_EQ(location_in_widget, contents_ptr->last_location()); // Scroll down a page. - contents->ScrollRectToVisible( + contents_ptr->ScrollRectToVisible( gfx::Rect(0, kDefaultHeight, 1, kDefaultHeight)); TestClickAt(location_in_widget); - EXPECT_EQ(gfx::Point(10, 10 + kDefaultHeight), contents->last_location()); + EXPECT_EQ(gfx::Point(10, 10 + kDefaultHeight), contents_ptr->last_location()); // Scroll right a page (and back up). - contents->ScrollRectToVisible(gfx::Rect(kDefaultWidth, 0, kDefaultWidth, 1)); + contents_ptr->ScrollRectToVisible( + gfx::Rect(kDefaultWidth, 0, kDefaultWidth, 1)); TestClickAt(location_in_widget); - EXPECT_EQ(gfx::Point(10 + kDefaultWidth, 10), contents->last_location()); + EXPECT_EQ(gfx::Point(10 + kDefaultWidth, 10), contents_ptr->last_location()); // Scroll both directions. - contents->ScrollRectToVisible( + contents_ptr->ScrollRectToVisible( gfx::Rect(kDefaultWidth, kDefaultHeight, kDefaultWidth, kDefaultHeight)); TestClickAt(location_in_widget); EXPECT_EQ(gfx::Point(10 + kDefaultWidth, 10 + kDefaultHeight), - contents->last_location()); + contents_ptr->last_location()); } // Ensure behavior of ScrollRectToVisible() is consistent when scrolling with
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc index eba7f1a..5c82cb6 100644 --- a/ui/views/controls/slider.cc +++ b/ui/views/controls/slider.cc
@@ -45,21 +45,24 @@ constexpr SkColor kDisabledColor = SkColorSetARGB(0xFF, 0xBD, 0xBD, 0xBD); constexpr uint8_t kHighlightColorAlpha = 0x4D; +// Color of the empty portion of the slider +const SkColor kEmptySliderColor = SkColorSetARGB(0xFF, 0xBD, 0xBD, 0xBD); + // The thickness of the slider. constexpr int kLineThickness = 2; // The radius used to draw rounded slider ends. constexpr float kSliderRoundedRadius = 2.f; +// The padding used to hide the slider underneath the thumb. +constexpr int kSliderPadding = 2; + // The radius of the thumb and the highlighted thumb of the slider, // respectively. constexpr float kThumbRadius = 6.f; constexpr float kThumbWidth = 2 * kThumbRadius; constexpr float kThumbHighlightRadius = 10.f; -// The stroke of the thumb when the slider is disabled. -constexpr int kSliderThumbStroke = 2; - // Duration of the thumb highlight growing effect animation. constexpr int kSlideHighlightChangeDurationMs = 150; @@ -271,19 +274,23 @@ const int x = content.x() + full + kThumbRadius; const SkColor current_thumb_color = is_active_ ? kActiveColor : kDisabledColor; + const SkColor empty_slider_color = + is_active_ ? kEmptySliderColor + : SkColorSetA(kEmptySliderColor, kHighlightColorAlpha); - // Extra space used to hide slider ends behind the thumb. - constexpr int kExtraPadding = 1; + // Extra space used to hide slider ends behind the thumb when slider is + // disabled. + const int extra_padding = is_active_ ? 0 : kSliderPadding; cc::PaintFlags slider_flags; slider_flags.setAntiAlias(true); slider_flags.setColor(current_thumb_color); canvas->DrawRoundRect( - gfx::Rect(content.x(), y, full + kExtraPadding, kLineThickness), + gfx::Rect(content.x(), y, full - extra_padding, kLineThickness), kSliderRoundedRadius, slider_flags); - slider_flags.setColor(kDisabledColor); - canvas->DrawRoundRect(gfx::Rect(x + kThumbRadius - kExtraPadding, y, - empty + kExtraPadding, kLineThickness), + slider_flags.setColor(empty_slider_color); + canvas->DrawRoundRect(gfx::Rect(x + kThumbRadius + extra_padding, y, + empty - extra_padding, kLineThickness), kSliderRoundedRadius, slider_flags); gfx::Point thumb_center(x, content.height() / 2); @@ -291,10 +298,11 @@ // Paint the thumb highlight if it exists. const int thumb_highlight_radius = HasFocus() ? kThumbHighlightRadius : thumb_highlight_radius_; - if (is_active_ && thumb_highlight_radius > kThumbRadius) { + if (thumb_highlight_radius > kThumbRadius) { cc::PaintFlags highlight; - SkColor kHighlightColor = SkColorSetA(kActiveColor, kHighlightColorAlpha); - highlight.setColor(kHighlightColor); + SkColor highlight_color = + SkColorSetA(current_thumb_color, kHighlightColorAlpha); + highlight.setColor(highlight_color); highlight.setAntiAlias(true); canvas->DrawCircle(thumb_center, thumb_highlight_radius, highlight); } @@ -304,14 +312,7 @@ flags.setColor(current_thumb_color); flags.setAntiAlias(true); - if (!is_active_) { - flags.setStrokeWidth(kSliderThumbStroke); - flags.setStyle(cc::PaintFlags::kStroke_Style); - } - canvas->DrawCircle( - thumb_center, - is_active_ ? kThumbRadius : (kThumbRadius - kSliderThumbStroke / 2), - flags); + canvas->DrawCircle(thumb_center, kThumbRadius, flags); } void Slider::OnFocus() {
diff --git a/ui/views/controls/table/table_utils_unittest.cc b/ui/views/controls/table/table_utils_unittest.cc index f6a97d9..ae445a2 100644 --- a/ui/views/controls/table/table_utils_unittest.cc +++ b/ui/views/controls/table/table_utils_unittest.cc
@@ -63,8 +63,8 @@ TEST(TableUtilsTest, LastColumnGetsAllSpace) { TestTableModel model(4); std::vector<TableColumn> columns; - columns.push_back(ui::TableColumn()); - columns.push_back(ui::TableColumn()); + columns.emplace_back(); + columns.emplace_back(); gfx::FontList font_list; std::vector<int> result(CalculateTableColumnSizes( 500, 0, font_list, font_list, 0, 0, columns, &model)); @@ -78,9 +78,9 @@ TEST(TableUtilsTest, SingleResizableColumn) { TestTableModel model(4); std::vector<TableColumn> columns; - columns.push_back(ui::TableColumn()); - columns.push_back(ui::TableColumn()); - columns.push_back(ui::TableColumn()); + columns.emplace_back(); + columns.emplace_back(); + columns.emplace_back(); columns[2].percent = 1.0f; gfx::FontList font_list; std::vector<int> result(CalculateTableColumnSizes(
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index e1297ac..5ca8897 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -181,6 +181,16 @@ model_->SetObserver(nullptr); } +// static +std::unique_ptr<ScrollView> TableView::CreateScrollViewWithTable( + std::unique_ptr<TableView> table) { + auto scroll_view = base::WrapUnique(ScrollView::CreateScrollViewWithBorder()); + auto* table_ptr = table.get(); + scroll_view->SetContents(std::move(table)); + table_ptr->CreateHeaderIfNecessary(scroll_view.get()); + return scroll_view; +} + // TODO: this doesn't support arbitrarily changing the model, rename this to // ClearModel() or something. void TableView::SetModel(ui::TableModel* model) { @@ -195,15 +205,6 @@ model_->SetObserver(this); } -View* TableView::CreateParentIfNecessary() { - ScrollView* scroll_view = ScrollView::CreateScrollViewWithBorder(); - scroll_view->SetContents(this); - CreateHeaderIfNecessary(); - if (header_) - scroll_view->SetHeader(header_); - return scroll_view; -} - void TableView::SetGrouper(TableGrouper* grouper) { grouper_ = grouper; SortItemsAndUpdateMapping(); @@ -911,13 +912,13 @@ bounds->set_width(std::max(0, bounds->right() - cell_margin - text_x)); } -void TableView::CreateHeaderIfNecessary() { +void TableView::CreateHeaderIfNecessary(ScrollView* scroll_view) { // Only create a header if there is more than one column or the title of the // only column is not empty. if (header_ || (columns_.size() == 1 && columns_[0].title.empty())) return; - header_ = new TableHeader(this); + header_ = scroll_view->SetHeader(std::make_unique<TableHeader>(this)); UpdateVirtualAccessibilityChildren(); }
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index aa9a297..cb83328 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h
@@ -44,6 +44,7 @@ class AXVirtualView; class FocusRing; struct GroupRange; +class ScrollView; class TableGrouper; class TableHeader; class TableViewObserver; @@ -113,6 +114,10 @@ bool single_selection); ~TableView() override; + // Returns a new ScrollView that contains the given |table|. + static std::unique_ptr<ScrollView> CreateScrollViewWithTable( + std::unique_ptr<TableView> table); + // Assigns a new model to the table view, detaching the old one if present. // If |model| is NULL, the table view cannot be used after this call. This // should be called in the containing view's destructor to avoid destruction @@ -120,9 +125,6 @@ void SetModel(ui::TableModel* model); ui::TableModel* model() const { return model_; } - // Returns a new ScrollView that contains the receiver. - View* CreateParentIfNecessary(); - // Sets the TableGrouper. TableView does not own |grouper| (common use case is // to have TableModel implement TableGrouper). void SetGrouper(TableGrouper* grouper); @@ -277,7 +279,7 @@ gfx::Rect* bounds) const; // Creates |header_| if necessary. - void CreateHeaderIfNecessary(); + void CreateHeaderIfNecessary(ScrollView* scroll_view); // Updates the |x| and |width| of each of the columns in |visible_columns_|. void UpdateVisibleColumnSizes();
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index 94b09e3..43b30a12f 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc
@@ -18,6 +18,7 @@ #include "ui/gfx/text_utils.h" #include "ui/views/accessibility/ax_virtual_view.h" #include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/table/table_grouper.h" #include "ui/views/controls/table/table_header.h" #include "ui/views/controls/table/table_view_observer.h" @@ -269,10 +270,12 @@ columns[1].title = base::ASCIIToUTF16("Title Column 1"); columns[1].id = 1; columns[1].sortable = true; - table_ = new TableView(model_.get(), columns, TEXT_ONLY, false); - View* parent = table_->CreateParentIfNecessary(); - parent->SetBounds(0, 0, 10000, 10000); - parent->Layout(); + auto table = + std::make_unique<TableView>(model_.get(), columns, TEXT_ONLY, false); + table_ = table.get(); + auto scroll_view = TableView::CreateScrollViewWithTable(std::move(table)); + scroll_view->SetBounds(0, 0, 10000, 10000); + scroll_view->Layout(); helper_ = std::make_unique<TableViewTestHelper>(table_); widget_ = std::make_unique<Widget>(); @@ -281,7 +284,7 @@ params.bounds = gfx::Rect(0, 0, 650, 650); params.delegate = GetWidgetDelegate(widget_.get()); widget_->Init(params); - widget_->GetContentsView()->AddChildView(parent); + widget_->GetContentsView()->AddChildView(std::move(scroll_view)); widget_->Show(); }
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc index f5157820..3e3d357 100644 --- a/ui/views/controls/tree/tree_view.cc +++ b/ui/views/controls/tree/tree_view.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/i18n/rtl.h" +#include "base/memory/ptr_util.h" #include "build/build_config.h" #include "components/vector_icons/vector_icons.h" #include "ui/accessibility/ax_node_data.h" @@ -120,8 +121,8 @@ } View* TreeView::CreateParentIfNecessary() { - ScrollView* scroll_view = ScrollView::CreateScrollViewWithBorder(); - scroll_view->SetContents(this); + auto* scroll_view = ScrollView::CreateScrollViewWithBorder(); + scroll_view->SetContents(base::WrapUnique(this)); return scroll_view; }
diff --git a/ui/views/examples/scroll_view_example.cc b/ui/views/examples/scroll_view_example.cc index 0fba398..59a3662 100644 --- a/ui/views/examples/scroll_view_example.cc +++ b/ui/views/examples/scroll_view_example.cc
@@ -80,9 +80,8 @@ big_square_ = new LabelButton(this, ASCIIToUTF16("Big Square")); small_square_ = new LabelButton(this, ASCIIToUTF16("Small Square")); scroll_to_ = new LabelButton(this, ASCIIToUTF16("Scroll to")); - scrollable_ = new ScrollableView(); scroll_view_ = new ScrollView(); - scroll_view_->SetContents(scrollable_); + scrollable_ = scroll_view_->SetContents(std::make_unique<ScrollableView>()); scrollable_->SetBounds(0, 0, 1000, 100); scrollable_->SetColor(SK_ColorYELLOW, SK_ColorCYAN);
diff --git a/ui/views/examples/table_example.cc b/ui/views/examples/table_example.cc index c2e4291f..72985b1 100644 --- a/ui/views/examples/table_example.cc +++ b/ui/views/examples/table_example.cc
@@ -12,6 +12,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/controls/button/checkbox.h" +#include "ui/views/controls/scroll_view.h" #include "ui/views/layout/grid_layout.h" using base::ASCIIToUTF16; @@ -63,9 +64,9 @@ columns.push_back(TestTableColumn(2, "Origin")); columns.push_back(TestTableColumn(3, "Price")); columns.back().alignment = ui::TableColumn::RIGHT; - table_ = new TableView(this, columns, ICON_AND_TEXT, true); - table_->SetGrouper(this); - table_->set_observer(this); + auto table = std::make_unique<TableView>(this, columns, ICON_AND_TEXT, true); + table->SetGrouper(this); + table->set_observer(this); icon1_.allocN32Pixels(16, 16); SkCanvas canvas1(icon1_); canvas1.drawColor(SK_ColorRED); @@ -78,7 +79,9 @@ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); layout->StartRow(1 /* expand */, 0); - layout->AddView(table_->CreateParentIfNecessary()); + table_ = table.get(); + layout->AddView( + TableView::CreateScrollViewWithTable(std::move(table)).release()); column_set = layout->AddColumnSet(1); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
diff --git a/ui/views/focus/focus_traversal_unittest.cc b/ui/views/focus/focus_traversal_unittest.cc index dd322025..88e48f0 100644 --- a/ui/views/focus/focus_traversal_unittest.cc +++ b/ui/views/focus/focus_traversal_unittest.cc
@@ -433,11 +433,12 @@ inner_container->AddChildView(scroll_view); scroll_view->SetBounds(1, 1, 148, 178); - View* scroll_content = new View(); + auto scroll_content = std::make_unique<View>(); scroll_content->SetBounds(0, 0, 200, 200); scroll_content->SetBackground( CreateSolidBackground(SkColorSetRGB(200, 200, 200))); - scroll_view->SetContents(scroll_content); + auto* scroll_content_ptr = + scroll_view->SetContents(std::move(scroll_content)); static const char* const kTitles[] = { "Rosetta", "Stupeur et tremblement", "The diner game", @@ -460,7 +461,7 @@ Link* link = new Link(ASCIIToUTF16(kTitles[i])); link->SetHorizontalAlignment(gfx::ALIGN_LEFT); link->set_id(kIDs[i]); - scroll_content->AddChildView(link); + scroll_content_ptr->AddChildView(link); link->SetBounds(5, y, 300, 15); y += 15; }
diff --git a/ui/views/test/focus_manager_test.cc b/ui/views/test/focus_manager_test.cc index b3ee165c..7b68bfc 100644 --- a/ui/views/test/focus_manager_test.cc +++ b/ui/views/test/focus_manager_test.cc
@@ -104,7 +104,7 @@ void TestFocusChangeListener::OnWillChangeFocus(View* focused_before, View* focused_now) { - focus_changes_.push_back(ViewPair(focused_before, focused_now)); + focus_changes_.emplace_back(focused_before, focused_now); } void TestFocusChangeListener::OnDidChangeFocus(View* focused_before, View* focused_now) {
diff --git a/ui/views/view.cc b/ui/views/view.cc index 0c8a7f4e..d96b9c06 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -2103,6 +2103,9 @@ } ViewHierarchyChanged(details); + for (ViewObserver& observer : observers_) + observer.OnViewHierarchyChanged(this, details); + details.parent->needs_layout_ = true; }
diff --git a/ui/views/view.h b/ui/views/view.h index b3858e0..a93aec7c 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -89,6 +89,35 @@ class ScopedChildrenLock; } // namespace internal +// Struct used to describe how a View hierarchy has changed. See +// View::ViewHierarchyChanged. +// TODO(pbos): Move to a separate view_hierarchy_changed_details.h header. +struct VIEWS_EXPORT ViewHierarchyChangedDetails { + ViewHierarchyChangedDetails() + : ViewHierarchyChangedDetails(false, nullptr, nullptr, nullptr) {} + + ViewHierarchyChangedDetails(bool is_add, + View* parent, + View* child, + View* move_view) + : is_add(is_add), parent(parent), child(child), move_view(move_view) {} + + bool is_add; + // New parent if |is_add| is true, old parent if |is_add| is false. + View* parent; + // The view being added or removed. + View* child; + // If this is a move (reparent), meaning AddChildViewAt() is invoked with an + // existing parent, then a notification for the remove is sent first, + // followed by one for the add. This case can be distinguished by a + // non-NULL |move_view|. + // For the remove part of move, |move_view| is the new parent of the View + // being removed. + // For the add part of move, |move_view| is the old parent of the View being + // added. + View* move_view; +}; + ///////////////////////////////////////////////////////////////////////////// // // View class @@ -135,35 +164,6 @@ ACCESSIBLE_ONLY, }; - struct ViewHierarchyChangedDetails { - ViewHierarchyChangedDetails() - : is_add(false), parent(nullptr), child(nullptr), move_view(nullptr) {} - - ViewHierarchyChangedDetails(bool is_add, - View* parent, - View* child, - View* move_view) - : is_add(is_add), - parent(parent), - child(child), - move_view(move_view) {} - - bool is_add; - // New parent if |is_add| is true, old parent if |is_add| is false. - View* parent; - // The view being added or removed. - View* child; - // If this is a move (reparent), meaning AddChildViewAt() is invoked with an - // existing parent, then a notification for the remove is sent first, - // followed by one for the add. This case can be distinguished by a - // non-NULL |move_view|. - // For the remove part of move, |move_view| is the new parent of the View - // being removed. - // For the add part of move, |move_view| is the old parent of the View being - // added. - View* move_view; - }; - // During paint, the origin of each view in physical pixel is calculated by // view_origin_pixel = ROUND(view.origin() * device_scale_factor) //
diff --git a/ui/views/view_observer.h b/ui/views/view_observer.h index 34cc6e4..bcd0a61 100644 --- a/ui/views/view_observer.h +++ b/ui/views/view_observer.h
@@ -10,6 +10,7 @@ namespace views { class View; +struct ViewHierarchyChangedDetails; // ViewObserver is used to observe changes to a View. The first argument to all // ViewObserver functions is the View the observer was added to. @@ -34,6 +35,11 @@ // Called when the bounds of |observed_view| change. virtual void OnViewBoundsChanged(View* observed_view) {} + // Called when View::ViewHierarchyChanged() is called. + virtual void OnViewHierarchyChanged( + View* observed_view, + const ViewHierarchyChangedDetails& details) {} + // Called when a child is reordered among its siblings, specifically // View::ReorderChildView() is called on |observed_view|. virtual void OnChildViewReordered(View* observed_view, View* child) {}
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index e31a2704..7dfba9b 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -154,6 +154,7 @@ urgency_hint_set_(false), has_pointer_grab_(false), activatable_(true), + override_redirect_(false), has_pointer_(false), has_window_focus_(false), has_pointer_focus_(false), @@ -736,7 +737,9 @@ Time timestamp = ui::X11EventSource::GetInstance()->GetTimestamp(); - if (wm_supports_active_window) { + // override_redirect windows ignore _NET_ACTIVE_WINDOW. + // https://crbug.com/940924 + if (wm_supports_active_window && !override_redirect_) { XEvent xclient; memset(&xclient, 0, sizeof(xclient)); xclient.type = ClientMessage; @@ -1437,7 +1440,8 @@ if (!activatable_) swa.override_redirect = x11::True; - if (swa.override_redirect) + override_redirect_ = swa.override_redirect == x11::True; + if (override_redirect_) attribute_mask |= CWOverrideRedirect; bool enable_transparent_visuals;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h index 8fdc869..ca1a738 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -413,8 +413,12 @@ // Does |xwindow_| have the pointer grab (XI2 or normal)? bool has_pointer_grab_; + // Is this window able to receive focus? bool activatable_; + // Was this window initialized with the override_redirect window attribute? + bool override_redirect_; + // The focus-tracking state variables are as described in // gtk/docs/focus_tracking.txt //
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index a6cda6e..5834c423 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -427,8 +427,7 @@ return false; } -void Widget::ViewHierarchyChanged( - const View::ViewHierarchyChangedDetails& details) { +void Widget::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) { if (!details.is_add) { if (details.child == dragged_view_) dragged_view_ = nullptr;
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 9660aa54..66b6d6b 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -396,7 +396,7 @@ virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator) const; // Forwarded from the RootView so that the widget can do any cleanup. - void ViewHierarchyChanged(const View::ViewHierarchyChangedDetails& details); + void ViewHierarchyChanged(const ViewHierarchyChangedDetails& details); // Called right before changing the widget's parent NativeView to do any // cleanup.