diff --git a/DEPS b/DEPS index ab7491b..c326cdd6 100644 --- a/DEPS +++ b/DEPS
@@ -172,11 +172,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': 'e8356ad35d3c2cbc9812585ecdd0dd21917f1443', + 'skia_revision': '7a13b461e6e08eaea9dea2a90ca4724e9c1979eb', # 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': '9ab48dcceb41e68cc02d83193f32a71572609ee0', + 'v8_revision': '4abff70fe7c566671a9c711c34c1c3c0b7bbac93', # 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. @@ -184,15 +184,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': 'ac36a55cc2deadc3c77eebcf55f05241b1667bbe', + 'angle_revision': '1bae56151db3158c03fb9d21302975be19a68a2e', # 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': 'aaa64b76c0b40c2958a18cfdc623157c8c6e1b7d', + 'swiftshader_revision': 'b0a1f0a9680601d66c5ab518d03158943c9fd87c', # 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': '69dd6b02511ca608412a1501cdbd692e8a406ada', + 'pdfium_revision': '14c3436191d30549054c0b6a4d7fc88bd2cfa886', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -235,7 +235,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': 'a05f421623d78ccfa4e3f8224416e7d6e4e6a6d6', + 'catapult_revision': 'bce667b745aac67b5786eaf352f2c140564c91a7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -243,7 +243,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '2cf0518ef4462b1f51dc447f7797f8191c4a365f', + 'devtools_frontend_revision': '879d97b05dfe9f26ede820b0296b125d4a68e5ff', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -307,7 +307,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'dbf9f7c39cbe44f9a627855a949018dc03214054', + 'dawn_revision': 'c277c38d90645962ec25d326c840f0843e37002e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -822,7 +822,7 @@ }, 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'c46151db0ffd1a8dae914e45f1212ef427f61ed3', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '5915ea929c43d61e77b68b64bc91d8709f5c9876', 'src/third_party/byte_buddy': { 'packages': [ @@ -1311,7 +1311,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd66586f2421010425a6933fe190c778be32e89ad', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '287edca9b43763fadc8e528ebd0a5720a724d181', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1512,7 +1512,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'dd55f3ca8f2ea716ca917a4aaf36f0729fe902b1', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd5a7838926b839469db1072d72a92e6814f2faeb', + Var('webrtc_git') + '/src.git' + '@' + '4c04d8e10c3c1e9d5ad1b65b5ce24227a8394d5d', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1579,7 +1579,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3b1f341d002824feadb69e9be9f0d003a7c1d615', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e600381cfd175c3c6fc27bddf79e3ca2fb3f5025', 'condition': 'checkout_src_internal', }, @@ -3292,7 +3292,8 @@ 'name': 'clang_coverage', 'pattern': '.', 'condition': 'checkout_clang_coverage_tools', - 'action': ['python', 'src/tools/code_coverage/update_clang_coverage_tools.py'], + 'action': ['python', 'src/tools/clang/scripts/update.py', + '--package=coverage_tools'], }, { # Mac doesn't use lld so it's not included in the default clang bundle @@ -3301,7 +3302,8 @@ 'name': 'lld/mac', 'pattern': '.', 'condition': 'host_os == "mac" and (checkout_win or checkout_fuchsia)', - 'action': ['python', 'src/tools/clang/scripts/download_lld_mac.py'], + 'action': ['python', 'src/tools/clang/scripts/update.py', + '--package=lld_mac'], }, { # Update LASTCHANGE.
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.h b/android_webview/browser/metrics/aw_metrics_service_client.h index d75c8d30..fafb2aa 100644 --- a/android_webview/browser/metrics/aw_metrics_service_client.h +++ b/android_webview/browser/metrics/aw_metrics_service_client.h
@@ -127,6 +127,9 @@ override; base::TimeDelta GetStandardUploadInterval() override; bool ShouldStartUpFastForTesting() const override; + + // Gets the embedding app's package name if it's OK to log. Otherwise, this + // returns the empty string. std::string GetAppPackageName() override; protected:
diff --git a/android_webview/docs/contributing-tests.md b/android_webview/docs/contributing-tests.md new file mode 100644 index 0000000..846401c --- /dev/null +++ b/android_webview/docs/contributing-tests.md
@@ -0,0 +1,68 @@ +# Contributing to WebView Tests + +[TOC] + +## Instrumentation tests +These are on-device integration tests for android\_webview with rest of the +chromium code (covering both Java and native code). A large percentage of +Android applications use WebView, and could trigger WebView specific code paths +in the codebase, therefore it is important to have solid integration tests. + +#### Where to add tests? +The tests are located in the [javatests directory](/android_webview/javatests/src/org/chromium/android_webview/test/). +They are roughly organized by the +[Aw classes](/android_webview/java/src/org/chromium/android_webview/) (some +tests are organized by overall functionality instead). Put new tests into an +existing test class or create a new one if a suitable one isn't available. + +#### How to write intrumentation tests? +See the [instrumentation test doc](/testing/android/docs/instrumentation.md). + +#### How do tests interact with WebView? +Tests are written as JUnit4 tests. [AwActivityTestRule] is used to create and +obtain references to WebView objects such as [AwContents](internally it launches +the [WebView instrumentation shell](/android_webview/test/shell/src/org/chromium/android_webview/shell/) +application to hold [AwTestContainerViews](/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java) +which in turn contains [AwContents]). [AwContents] will allow the test to +trigger code paths such as loading urls, going forwards/backwards, etc... . +[AwActivityTestRule] has some helper methods to call the [AwContents] methods, +for example to ensure that they are called on the UI thread. Some AW +components, such as [AwCookieManager](/android_webview/java/src/org/chromium/android_webview/AwCookieManager.java), +can be directly created in tests. + +#### How do tests inject html/css/js content? +Tests can use the load\* methods in [AwActivityTestRule] to inject snippets +of content. This will however bypass the network layer. To have end-to-end +testing, use [EmbeddedTestServer](/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java), +which will allow simple loading of files from the [data directory](/android_webview/test/data/). +For loading data from arbitrary URIs and more advanced control, the +[TestWebServer](/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java) +can be used. + +## Java unittest (JUnit) +These are off-device tests using robolectric that only exercise android\_webview +Java code. + +#### Where do add tests? +The tests are located in the [junit directory](/android_webview/junit/src/org/chromium/android_webview/robolectric/). + +#### How to write junit tests? +See the [JUnit doc](/testing/android/docs/junit.md#junit-tests-with-robolectric). + +## Native unittests +These are on-device gtests that only exercise android\_webview native code. + +#### Where to add tests? +The tests are located alongside respective source code files under +[android\_webview directory](/android_webview/). + +#### How to write gtests? +See the [GTest doc](/testing/android/docs/gtest_implementation.md). + +## How to run tests? +Running tests is covered in [WebView Test Instructions](/android_webview/docs/test-instructions.md). + +[AwActivityTestRule]: +/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java +[AwContents]: +/android_webview/java/src/org/chromium/android_webview/AwContents.java
diff --git a/android_webview/java/src/org/chromium/android_webview/AwProxyController.java b/android_webview/java/src/org/chromium/android_webview/AwProxyController.java index a806e76f..979fc75 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwProxyController.java +++ b/android_webview/java/src/org/chromium/android_webview/AwProxyController.java
@@ -46,7 +46,7 @@ public AwProxyController() {} - public String setProxyOverride( + public void setProxyOverride( String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) { int length = (proxyRules == null ? 0 : proxyRules.length); String[] urlSchemes = new String[length]; @@ -63,7 +63,7 @@ // proxy URLs proxyUrls[i] = proxyRules[i][1]; if (proxyUrls[i] == null) { - return "Proxy rule " + i + " has a null url"; + throw new IllegalArgumentException("Proxy rule " + i + " has a null url"); } // Check schemes for UMA if (proxyRules[i][0].equals("http")) { @@ -86,40 +86,41 @@ length = (bypassRules == null ? 0 : bypassRules.length); for (int i = 0; i < length; i++) { if (bypassRules[i] == null) { - return "Bypass rule " + i + " is null"; + throw new IllegalArgumentException("Bypass rule " + i + " is null"); } } if (executor == null) { - return "Executor must not be null"; + throw new IllegalArgumentException("Executor must not be null"); } String result = AwProxyControllerJni.get().setProxyOverride( AwProxyController.this, urlSchemes, proxyUrls, bypassRules, listener, executor); - if (result.equals("")) { - // In case operation is successful, log UMA data on SetProxyOverride - // Proxy scheme filter - if (schemeHttp && schemeHttps) { - recordProxySchemeType(ProxySchemeType.ALL); - } else if (schemeHttp) { - recordProxySchemeType(ProxySchemeType.HTTP); - } else if (schemeHttps) { - recordProxySchemeType(ProxySchemeType.HTTPS); - } - // Proxy url type - if (urlHttp) { - recordProxyUrlType(ProxyUrlType.HTTP); - } - if (urlHttps) { - recordProxyUrlType(ProxyUrlType.HTTPS); - } - if (urlDirect) { - recordProxyUrlType(ProxyUrlType.DIRECT); - } - // Bypass rules - RecordHistogram.recordBooleanHistogram("Android.WebView.SetProxyOverride.BypassRules", - bypassRules == null || bypassRules.length == 0 ? false : true); + if (!result.isEmpty()) { + throw new IllegalArgumentException(result); } - return result; + + // In case operation is successful, log UMA data on SetProxyOverride + // Proxy scheme filter + if (schemeHttp && schemeHttps) { + recordProxySchemeType(ProxySchemeType.ALL); + } else if (schemeHttp) { + recordProxySchemeType(ProxySchemeType.HTTP); + } else if (schemeHttps) { + recordProxySchemeType(ProxySchemeType.HTTPS); + } + // Proxy url type + if (urlHttp) { + recordProxyUrlType(ProxyUrlType.HTTP); + } + if (urlHttps) { + recordProxyUrlType(ProxyUrlType.HTTPS); + } + if (urlDirect) { + recordProxyUrlType(ProxyUrlType.DIRECT); + } + // Bypass rules + RecordHistogram.recordBooleanHistogram("Android.WebView.SetProxyOverride.BypassRules", + bypassRules == null || bypassRules.length == 0 ? false : true); } private static void recordProxySchemeType(@ProxySchemeType int proxySchemeType) { @@ -133,15 +134,14 @@ proxyUrlType, ProxyUrlType.NUM_ENTRIES); } - public String clearProxyOverride(Runnable listener, Executor executor) { + public void clearProxyOverride(Runnable listener, Executor executor) { if (executor == null) { - return "Executor must not be null"; + throw new IllegalArgumentException("Executor must not be null"); } AwProxyControllerJni.get().clearProxyOverride(AwProxyController.this, listener, executor); // Log UMA data on ClearProxyOverride RecordHistogram.recordBooleanHistogram("Android.WebView.ClearProxyOverride", true); - return ""; } @CalledByNativeUnchecked
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 f1747ce..1895881 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
@@ -21,6 +21,7 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; /** @@ -212,37 +213,42 @@ throws Exception { CallbackHelper ch = new CallbackHelper(); int callCount = ch.getCallCount(); - String result = TestThreadUtils.runOnUiThreadBlocking(() -> { - return mAwProxyController.setProxyOverride(proxyRules, bypassRules, new Runnable() { + runOnUiThreadBlocking(() -> { + mAwProxyController.setProxyOverride(proxyRules, bypassRules, new Runnable() { @Override public void run() { ch.notifyCalled(); } }, new SynchronousExecutor()); }); - if (!result.isEmpty()) { - throw new IllegalArgumentException(result); - } ch.waitForCallback(callCount); } private void clearProxyOverrideSync() throws Exception { CallbackHelper ch = new CallbackHelper(); int callCount = ch.getCallCount(); - String result = TestThreadUtils.runOnUiThreadBlocking(() -> { - return mAwProxyController.clearProxyOverride(new Runnable() { + runOnUiThreadBlocking(() -> { + mAwProxyController.clearProxyOverride(new Runnable() { @Override public void run() { ch.notifyCalled(); } }, new SynchronousExecutor()); }); - if (!result.isEmpty()) { - throw new IllegalArgumentException(result); - } ch.waitForCallback(callCount); } + private void runOnUiThreadBlocking(Runnable r) throws Exception { + try { + TestThreadUtils.runOnUiThreadBlocking(r); + } catch (RuntimeException e) { + Throwable cause = e.getCause(); + if (cause instanceof ExecutionException) cause = cause.getCause(); + if (cause instanceof IllegalArgumentException) throw (IllegalArgumentException) cause; + throw e; + } + } + static class SynchronousExecutor implements Executor { @Override public void execute(Runnable r) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java index c6b9662b..e64456f7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java
@@ -824,6 +824,13 @@ @Test @SmallTest @Feature({"AndroidWebView", "JsJavaInteraction"}) + public void testPostMessage_JsObjectName_Symbol() throws Throwable { + checkInjectAndAccessJsObjectNameAsWindowProperty("*"); + } + + @Test + @SmallTest + @Feature({"AndroidWebView", "JsJavaInteraction"}) public void testPostMessage_JsObjectName_Keyword() throws Throwable { checkInjectAndAccessJsObjectNameAsWindowProperty("var"); }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java index ebe0f6fc..1b77b99 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java
@@ -9,6 +9,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.support_lib_boundary.ProxyControllerBoundaryInterface; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; /** @@ -27,31 +28,44 @@ @Override public void setProxyOverride( String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) { - String result; if (checkNeedsPost()) { - result = mRunQueue.runOnUiThreadBlocking(() -> { - return mProxyController.setProxyOverride( - proxyRules, bypassRules, listener, executor); + RuntimeException exception = mRunQueue.runOnUiThreadBlocking(() -> { + try { + mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor); + } catch (RuntimeException e) { + return e; + } + return null; }); + maybeThrowUnwrappedException(exception); } else { - result = mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor); - } - if (!result.isEmpty()) { - throw new IllegalArgumentException(result); + mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor); } } @Override public void clearProxyOverride(Runnable listener, Executor executor) { - String result; if (checkNeedsPost()) { - result = mRunQueue.runOnUiThreadBlocking( - () -> { return mProxyController.clearProxyOverride(listener, executor); }); + RuntimeException exception = mRunQueue.runOnUiThreadBlocking(() -> { + try { + mProxyController.clearProxyOverride(listener, executor); + } catch (RuntimeException e) { + return e; + } + return null; + }); + maybeThrowUnwrappedException(exception); } else { - result = mProxyController.clearProxyOverride(listener, executor); + mProxyController.clearProxyOverride(listener, executor); } - if (!result.isEmpty()) { - throw new IllegalArgumentException(result); + } + + private void maybeThrowUnwrappedException(RuntimeException exception) { + if (exception != null) { + Throwable cause = exception.getCause(); + if (cause instanceof ExecutionException) cause = cause.getCause(); + if (cause instanceof RuntimeException) throw (RuntimeException) cause; + throw exception; } }
diff --git a/ash/drag_drop/drag_drop_unittest.cc b/ash/drag_drop/drag_drop_unittest.cc index 140c3d82..da979501 100644 --- a/ash/drag_drop/drag_drop_unittest.cc +++ b/ash/drag_drop/drag_drop_unittest.cc
@@ -117,13 +117,7 @@ // Test if the mouse gets moved properly to another display // during drag & drop operation. -// Fails in debug builds, crbug.com/1006101. -#if !defined(NDEBUG) -#define MAYBE_DragDropAcrossMultiDisplay DISABLED_DragDropAcrossMultiDisplay -#else -#define MAYBE_DragDropAcrossMultiDisplay DragDropAcrossMultiDisplay -#endif -TEST_F(DragDropTest, MAYBE_DragDropAcrossMultiDisplay) { +TEST_F(DragDropTest, DragDropAcrossMultiDisplay) { ui_controls::InstallUIControlsAura(test::CreateAshUIControls()); UpdateDisplay("400x400,400x400");
diff --git a/ash/home_screen/drag_window_from_shelf_controller.cc b/ash/home_screen/drag_window_from_shelf_controller.cc index b792451..06aae4ea 100644 --- a/ash/home_screen/drag_window_from_shelf_controller.cc +++ b/ash/home_screen/drag_window_from_shelf_controller.cc
@@ -496,8 +496,10 @@ for (auto* window : GetTransientTreeIterator(window_)) { // self-destructed when window transform animation is done. new WindowTransformToHomeScreenAnimation( - window, window == window_ ? base::make_optional(original_backdrop_mode_) - : base::nullopt); + window, + window == window_ ? base::make_optional(original_backdrop_mode_) + : base::nullopt, + base::NullCallback()); } }
diff --git a/ash/home_screen/home_screen_controller.cc b/ash/home_screen/home_screen_controller.cc index 8b681ff..a9ca31b9 100644 --- a/ash/home_screen/home_screen_controller.cc +++ b/ash/home_screen/home_screen_controller.cc
@@ -22,6 +22,7 @@ #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_state.h" #include "ash/wm/window_transient_descendant_iterator.h" +#include "base/barrier_closure.h" #include "base/logging.h" #include "base/stl_util.h" #include "ui/aura/window.h" @@ -156,6 +157,9 @@ return true; } + delegate_->OnHomeLauncherTargetPositionChanged(true /* showing */, + display_id); + // First minimize all inactive windows. const bool window_minimized = MinimizeAllWindows(windows, active_windows /*windows_to_ignore*/); @@ -163,24 +167,46 @@ // Animate currently active windows into the home screen - they will be // minimized by WindowTransformToHomeScreenAnimation when the transition // finishes. - for (auto* active_window : active_windows) { - BackdropWindowMode original_backdrop_mode = - active_window->GetProperty(kBackdropWindowMode); - active_window->SetProperty(kBackdropWindowMode, - BackdropWindowMode::kDisabled); - // Do the scale-down transform for the entire transient tree. - for (auto* window : GetTransientTreeIterator(active_window)) { - // Self-destructed when window transform animation is done. - new WindowTransformToHomeScreenAnimation( - window, window == active_window - ? base::make_optional(original_backdrop_mode) - : base::nullopt); + if (!active_windows.empty()) { + base::RepeatingClosure window_transforms_callback = base::BarrierClosure( + active_windows.size(), + base::BindOnce(&HomeScreenController::NotifyHomeLauncherTransitionEnded, + weak_ptr_factory_.GetWeakPtr(), true /*shown*/, + display_id)); + + for (auto* active_window : active_windows) { + BackdropWindowMode original_backdrop_mode = + active_window->GetProperty(kBackdropWindowMode); + active_window->SetProperty(kBackdropWindowMode, + BackdropWindowMode::kDisabled); + + // Do the scale-down transform for the entire transient tree. + for (auto* window : GetTransientTreeIterator(active_window)) { + // Self-destructed when window transform animation is done. + new WindowTransformToHomeScreenAnimation( + window, + window == active_window + ? base::make_optional(original_backdrop_mode) + : base::nullopt, + window == active_window ? window_transforms_callback + : base::NullCallback()); + } } + } else { + delegate_->OnHomeLauncherAnimationComplete(true /*shown*/, display_id); } + return window_minimized || !active_windows.empty(); } +void HomeScreenController::NotifyHomeLauncherTransitionEnded( + bool shown, + int64_t display_id) { + if (delegate_) + delegate_->OnHomeLauncherAnimationComplete(shown, display_id); +} + void HomeScreenController::SetDelegate(HomeScreenDelegate* delegate) { delegate_ = delegate; }
diff --git a/ash/home_screen/home_screen_controller.h b/ash/home_screen/home_screen_controller.h index a002692..fe7e235f 100644 --- a/ash/home_screen/home_screen_controller.h +++ b/ash/home_screen/home_screen_controller.h
@@ -13,6 +13,7 @@ #include "ash/wm/overview/overview_observer.h" #include "ash/wm/overview/overview_session.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/optional.h" namespace ash { @@ -68,6 +69,11 @@ // in overview mode. void UpdateVisibility(); + // Notifies home screen delegate that a home launcher transition has ended. + // |shown| - whether the final home state was shown. + // |display_id| - the home screen display ID. + void NotifyHomeLauncherTransitionEnded(bool shown, int64_t display_id); + // Whether the wallpaper is being previewed. The home screen should be hidden // during wallpaper preview. bool in_wallpaper_preview_ = false; @@ -91,6 +97,8 @@ // available). base::Optional<OverviewSession::EnterExitOverviewType> overview_exit_type_; + base::WeakPtrFactory<HomeScreenController> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(HomeScreenController); };
diff --git a/ash/home_screen/window_transform_to_home_screen_animation.cc b/ash/home_screen/window_transform_to_home_screen_animation.cc index 5d65be0..c7b36f5 100644 --- a/ash/home_screen/window_transform_to_home_screen_animation.cc +++ b/ash/home_screen/window_transform_to_home_screen_animation.cc
@@ -39,8 +39,11 @@ WindowTransformToHomeScreenAnimation::WindowTransformToHomeScreenAnimation( aura::Window* window, - base::Optional<BackdropWindowMode> original_backdrop_mode) - : window_(window), original_backdrop_mode_(original_backdrop_mode) { + base::Optional<BackdropWindowMode> original_backdrop_mode, + base::OnceClosure opt_callback) + : window_(window), + original_backdrop_mode_(original_backdrop_mode), + opt_callback_(std::move(opt_callback)) { window_observer_.Add(window); ui::ScopedLayerAnimationSettings settings(window_->layer()->GetAnimator()); @@ -55,8 +58,10 @@ window_->layer()->SetOpacity(0.f); } -WindowTransformToHomeScreenAnimation::~WindowTransformToHomeScreenAnimation() = - default; +WindowTransformToHomeScreenAnimation::~WindowTransformToHomeScreenAnimation() { + if (!opt_callback_.is_null()) + std::move(opt_callback_).Run(); +} void WindowTransformToHomeScreenAnimation::OnImplicitAnimationsCompleted() { // Minimize the dragged window after transform animation is completed.
diff --git a/ash/home_screen/window_transform_to_home_screen_animation.h b/ash/home_screen/window_transform_to_home_screen_animation.h index e242da29..ee80477 100644 --- a/ash/home_screen/window_transform_to_home_screen_animation.h +++ b/ash/home_screen/window_transform_to_home_screen_animation.h
@@ -5,6 +5,7 @@ #ifndef ASH_HOME_SCREEN_WINDOW_TRANSFORM_TO_HOME_SCREEN_ANIMATION_H_ #define ASH_HOME_SCREEN_WINDOW_TRANSFORM_TO_HOME_SCREEN_ANIMATION_H_ +#include "base/callback.h" #include "base/macros.h" #include "base/optional.h" #include "base/scoped_observer.h" @@ -28,7 +29,8 @@ public: WindowTransformToHomeScreenAnimation( aura::Window* window, - base::Optional<BackdropWindowMode> original_backdrop_mode); + base::Optional<BackdropWindowMode> original_backdrop_mode, + base::OnceClosure opt_callback); ~WindowTransformToHomeScreenAnimation() override; // ui::ImplicitAnimationObserver: @@ -44,6 +46,8 @@ aura::Window* window_; base::Optional<BackdropWindowMode> original_backdrop_mode_; + base::OnceClosure opt_callback_; + ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this}; DISALLOW_COPY_AND_ASSIGN(WindowTransformToHomeScreenAnimation);
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc index c10bfa14..f3b4dde 100644 --- a/ash/host/ash_window_tree_host_platform.cc +++ b/ash/host/ash_window_tree_host_platform.cc
@@ -43,8 +43,7 @@ transformer_helper_(this) { CreateCompositor(viz::FrameSinkId(), /* force_software_compositor */ false, - /* use_external_begin_frame_control */ false, - /* are_events_in_pixels */ true); + /* use_external_begin_frame_control */ false); CommonInit(); }
diff --git a/ash/magnifier/docked_magnifier_controller_impl_unittest.cc b/ash/magnifier/docked_magnifier_controller_impl_unittest.cc index b3d9775..e0bb5adb 100644 --- a/ash/magnifier/docked_magnifier_controller_impl_unittest.cc +++ b/ash/magnifier/docked_magnifier_controller_impl_unittest.cc
@@ -25,6 +25,7 @@ #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_test_util.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc index f414352..2f6bd04c 100644 --- a/ash/public/cpp/ash_switches.cc +++ b/ash/public/cpp/ash_switches.cc
@@ -134,7 +134,7 @@ } bool IsUsingShelfAutoDim() { - return !base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableDimShelf); + return base::CommandLine::ForCurrentProcess()->HasSwitch(kEnableDimShelf); } } // namespace switches
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index 6c921393a..c8ca357 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -251,6 +251,12 @@ const gfx::Rect local_bounds = GetLocalBounds(); gfx::Rect shelf_view_bounds = local_bounds.Contains(ideal_bounds) ? local_bounds : ideal_bounds; + + if (shelf_view_->shelf()->IsHorizontalAlignment()) + shelf_view_bounds.set_x(GetAppIconEndPadding()); + else + shelf_view_bounds.set_y(GetAppIconEndPadding()); + shelf_view_->SetBoundsRect(shelf_view_bounds); } @@ -640,9 +646,9 @@ } // Paddings are within the shelf view. It makes sure that |shelf_view_|'s - // bounds are never changed. - shelf_view_->set_app_icons_layout_offset(before_padding + - GetAppIconEndPadding()); + // bounds are not changed by adding/removing the shelf icon under the same + // layout strategy. + shelf_view_->set_app_icons_layout_offset(before_padding); // Adjust the bounds when not showing in the horizontal // alignment.tShelf()->IsHorizontalAlignment()) {
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc index 9f769e1..7522846 100644 --- a/ash/shelf/scrollable_shelf_view_unittest.cc +++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/shelf/shelf_view_test_api.h" #include "ash/shelf/shelf_widget.h" #include "ash/test/ash_test_base.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/test/scoped_feature_list.h" #include "chromeos/constants/chromeos_features.h" #include "ui/display/manager/display_manager.h" @@ -412,4 +413,58 @@ EXPECT_EQ(0, view_model->GetIndexOfView(dragged_view)); } +// Verifies that the scrollable shelf in oveflow mode has the correct layout +// after switching to tablet mode (https://crbug.com/1017979). +TEST_F(ScrollableShelfViewTest, CorrectUIAfterSwitchingToTablet) { + // Add enough app shortcuts to ensure that at least three pages of icons show. + for (int i = 0; i < 25; i++) + AddAppShortcut(); + ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + GetEventGenerator()->GestureTapAt( + scrollable_shelf_view_->right_arrow()->GetBoundsInScreen().CenterPoint()); + ASSERT_EQ(ScrollableShelfView::kShowButtons, + scrollable_shelf_view_->layout_strategy_for_test()); + + Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); + base::RunLoop().RunUntilIdle(); + + views::ViewModel* view_model = shelf_view_->view_model(); + views::View* first_tappable_view = + view_model->view_at(scrollable_shelf_view_->first_tappable_app_index()); + + // Verifies that the gap between the left arrow button and the first tappable + // icon is expected. + const gfx::Rect left_arrow_bounds = + scrollable_shelf_view_->left_arrow()->GetBoundsInScreen(); + EXPECT_EQ(left_arrow_bounds.right() + 2, + first_tappable_view->GetBoundsInScreen().x()); +} + +// Verifies that the scrollable shelf without overflow has the correct layout in +// tablet mode. +TEST_F(ScrollableShelfViewTest, CorrectUIInTabletWithoutOverflow) { + Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); + + for (int i = 0; i < 3; i++) + AddAppShortcut(); + ASSERT_EQ(ScrollableShelfView::kNotShowArrowButtons, + scrollable_shelf_view_->layout_strategy_for_test()); + + gfx::Rect hotseat_background = + scrollable_shelf_view_->GetHotseatBackgroundBounds(); + views::View::ConvertRectToScreen(scrollable_shelf_view_, &hotseat_background); + + views::ViewModel* view_model = shelf_view_->view_model(); + const gfx::Rect first_tappable_view_bounds = + view_model->view_at(scrollable_shelf_view_->first_tappable_app_index()) + ->GetBoundsInScreen(); + const gfx::Rect last_tappable_view_bounds = + view_model->view_at(scrollable_shelf_view_->last_tappable_app_index()) + ->GetBoundsInScreen(); + + EXPECT_EQ(hotseat_background.x() + 4, first_tappable_view_bounds.x()); + EXPECT_EQ(hotseat_background.right() - 4, last_tappable_view_bounds.right()); +} + } // namespace ash
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 87e8243..6e42e49 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -34,6 +34,7 @@ #include "ash/wm/overview/overview_grid_event_handler.h" #include "ash/wm/overview/overview_highlight_controller.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_window_drag_controller.h"
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc index 5a7cc23..9b3c9e3 100644 --- a/ash/wm/overview/overview_highlight_controller.cc +++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -18,6 +18,7 @@ #include "ash/wm/overview/overview_delegate.h" #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/scoped_overview_animation_settings.h"
diff --git a/ash/wm/overview/overview_highlight_controller_unittest.cc b/ash/wm/overview/overview_highlight_controller_unittest.cc index d07bfc11..d217f649 100644 --- a/ash/wm/overview/overview_highlight_controller_unittest.cc +++ b/ash/wm/overview/overview_highlight_controller_unittest.cc
@@ -16,6 +16,7 @@ #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_test_util.h" #include "ash/wm/overview/scoped_overview_transform_window.h" #include "ash/wm/window_util.h"
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index c3c4489..3c99339 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -11,7 +11,6 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_state_type.h" -#include "ash/resources/vector_icons/vector_icons.h" #include "ash/scoped_animation_disabler.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" @@ -24,6 +23,7 @@ #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_grid_event_handler.h" #include "ash/wm/overview/overview_highlight_controller.h" +#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/rounded_label_widget.h" @@ -47,12 +47,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor_extra/shadow.h" #include "ui/gfx/geometry/safe_integer_conversions.h" -#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/transform_util.h" -#include "ui/strings/grit/ui_strings.h" -#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/controls/button/image_button.h" #include "ui/views/layout/layout_provider.h" #include "ui/views/widget/widget.h" @@ -83,16 +78,6 @@ // change in the size of the item along that dimension. constexpr float kDragWindowScale = 0.05f; -constexpr int kCloseButtonInkDropInsetDp = 2; - -constexpr SkColor kCloseButtonColor = SK_ColorWHITE; - -// The colors of the close button ripple. -constexpr SkColor kCloseButtonInkDropRippleColor = - SkColorSetA(kCloseButtonColor, 0x0F); -constexpr SkColor kCloseButtonInkDropRippleHighlightColor = - SkColorSetA(kCloseButtonColor, 0x14); - // A self-deleting animation observer that runs the given callback when its // associated animation completes. Optionally takes a callback that is run when // the animation starts. @@ -187,62 +172,6 @@ } // namespace -// The close button for the overview item. It has a custom ink drop. -class OverviewItem::OverviewCloseButton : public views::ImageButton { - public: - explicit OverviewCloseButton(views::ButtonListener* listener) - : views::ImageButton(listener) { - SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); - SetImage( - views::Button::STATE_NORMAL, - gfx::CreateVectorIcon(kOverviewWindowCloseIcon, kCloseButtonColor)); - SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER); - SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE); - SetMinimumImageSize(gfx::Size(kHeaderHeightDp, kHeaderHeightDp)); - SetAccessibleName(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); - SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); - } - - ~OverviewCloseButton() override = default; - - // Resets the listener so that the listener can go out of scope. - void ResetListener() { listener_ = nullptr; } - - protected: - // views::Button: - std::unique_ptr<views::InkDrop> CreateInkDrop() override { - auto ink_drop = std::make_unique<views::InkDropImpl>(this, size()); - ink_drop->SetAutoHighlightMode( - views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE); - ink_drop->SetShowHighlightOnHover(true); - return ink_drop; - } - std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override { - return std::make_unique<views::FloodFillInkDropRipple>( - size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(), - kCloseButtonInkDropRippleColor, /*visible_opacity=*/1.f); - } - std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() - const override { - return std::make_unique<views::InkDropHighlight>( - gfx::PointF(GetLocalBounds().CenterPoint()), - std::make_unique<views::CircleLayerDelegate>( - kCloseButtonInkDropRippleHighlightColor, GetInkDropRadius())); - } - std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override { - return std::make_unique<views::CircleInkDropMask>( - size(), GetLocalBounds().CenterPoint(), GetInkDropRadius()); - } - - private: - int GetInkDropRadius() const { - return std::min(size().width(), size().height()) / 2 - - kCloseButtonInkDropInsetDp; - } - - DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); -}; - OverviewItem::OverviewItem(aura::Window* window, OverviewSession* overview_session, OverviewGrid* overview_grid) @@ -286,8 +215,7 @@ MaximizeIfSnapped(GetWindow()); } - overview_item_view_->ResetEventDelegate(); - close_button_->ResetListener(); + overview_item_view_->OnOverviewItemWindowRestoring(); transform_window_.RestoreWindow(reset_transform); if (transform_window_.IsMinimized()) { @@ -523,8 +451,7 @@ animating_to_close_ = true; overview_session_->PositionWindows(/*animate=*/true); - overview_item_view_->ResetEventDelegate(); - close_button_->ResetListener(); + overview_item_view_->OnOverviewItemWindowRestoring(); int translation_y = kSwipeToCloseCloseTranslationDp * (up ? -1 : 1); gfx::Transform transform; @@ -991,7 +918,7 @@ void OverviewItem::ButtonPressed(views::Button* sender, const ui::Event& event) { - DCHECK_EQ(sender, close_button_); + DCHECK_EQ(sender, overview_item_view_->close_button()); if (IsSlidingOutOverviewFromShelf()) return; @@ -1074,13 +1001,6 @@ /*reposition=*/!animating_to_close_); } -void OverviewItem::OnWindowTitleChanged(aura::Window* window) { - if (window != GetWindow()) - return; - - overview_item_view_->SetTitle(window->GetTitle()); -} - void OverviewItem::OnPostWindowStateTypeChange(WindowState* window_state, WindowStateType old_type) { // During preparation, window state can change, e.g. updating shelf @@ -1109,11 +1029,11 @@ } views::ImageButton* OverviewItem::GetCloseButtonForTesting() { - return static_cast<views::ImageButton*>(close_button_); + return overview_item_view_->close_button(); } -float OverviewItem::GetCloseButtonVisibilityForTesting() const { - return close_button_->layer()->opacity(); +float OverviewItem::GetCloseButtonOpacityForTesting() const { + return overview_item_view_->close_button()->layer()->opacity(); } float OverviewItem::GetTitlebarOpacityForTesting() const { @@ -1283,9 +1203,8 @@ shadow_->Init(kShadowElevation); item_widget_->GetLayer()->Add(shadow_->layer()); - close_button_ = new OverviewCloseButton(this); - overview_item_view_ = new OverviewItemView( - this, GetWindow(), transform_window_.IsMinimized(), close_button_); + overview_item_view_ = + new OverviewItemView(this, GetWindow(), transform_window_.IsMinimized()); item_widget_->SetContentsView(overview_item_view_); item_widget_->Show(); item_widget_->SetOpacity(0.f);
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h index bbe31432..32fce2f 100644 --- a/ash/wm/overview/overview_item.h +++ b/ash/wm/overview/overview_item.h
@@ -8,7 +8,6 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/wm/overview/overview_item_view.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/scoped_overview_transform_window.h" #include "ash/wm/window_state_observer.h" @@ -26,17 +25,18 @@ } // namespace ui namespace views { +class ImageButton; class Widget; } // namespace views namespace ash { class DragWindowController; class OverviewGrid; +class OverviewItemView; class RoundedLabelWidget; // This class represents an item in overview mode. -class ASH_EXPORT OverviewItem : public OverviewItemView::EventDelegate, - public views::ButtonListener, +class ASH_EXPORT OverviewItem : public views::ButtonListener, public aura::WindowObserver, public WindowStateObserver { public: @@ -194,12 +194,12 @@ // If kNewOverviewLayout is on, use this function for handling events. void HandleGestureEventForTabletModeLayout(ui::GestureEvent* event); - // OverviewItemView::EventDelegate: - void HandleMouseEvent(const ui::MouseEvent& event) override; - void HandleGestureEvent(ui::GestureEvent* event) override; - bool ShouldIgnoreGestureEvents() override; - void OnHighlightedViewActivated() override; - void OnHighlightedViewClosed() override; + // Handles events forwarded from |overview_item_view_|. + void HandleMouseEvent(const ui::MouseEvent& event); + void HandleGestureEvent(ui::GestureEvent* event); + bool ShouldIgnoreGestureEvents(); + void OnHighlightedViewActivated(); + void OnHighlightedViewClosed(); // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; @@ -213,7 +213,6 @@ const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) override; void OnWindowDestroying(aura::Window* window) override; - void OnWindowTitleChanged(aura::Window* window) override; // WindowStateObserver: void OnPostWindowStateTypeChange(WindowState* window_state, @@ -262,7 +261,7 @@ } views::ImageButton* GetCloseButtonForTesting(); - float GetCloseButtonVisibilityForTesting() const; + float GetCloseButtonOpacityForTesting() const; float GetTitlebarOpacityForTesting() const; gfx::Rect GetShadowBoundsForTesting(); RoundedLabelWidget* cannot_snap_widget_for_testing() { @@ -275,7 +274,6 @@ private: friend class OverviewSessionRoundedCornerTest; friend class OverviewSessionTest; - class OverviewCloseButton; FRIEND_TEST_ALL_PREFIXES(SplitViewOverviewSessionTest, OverviewUnsnappableIndicatorVisibility); @@ -368,8 +366,6 @@ // maybe a backdrop. Forwards certain events to |this|. OverviewItemView* overview_item_view_ = nullptr; - OverviewCloseButton* close_button_ = nullptr; - // A widget with text that may show up on top of |transform_window_| to notify // users this window cannot be snapped. std::unique_ptr<RoundedLabelWidget> cannot_snap_widget_;
diff --git a/ash/wm/overview/overview_item_view.cc b/ash/wm/overview/overview_item_view.cc index c18c8fb..f3f2ce1 100644 --- a/ash/wm/overview/overview_item_view.cc +++ b/ash/wm/overview/overview_item_view.cc
@@ -4,8 +4,10 @@ #include "ash/wm/overview/overview_item_view.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" #include "ash/wm/overview/overview_constants.h" +#include "ash/wm/overview/overview_item.h" #include "ash/wm/overview/rounded_rect_view.h" #include "ash/wm/window_preview_view.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -14,6 +16,11 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/strings/grit/ui_strings.h" +#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/controls/button/image_button.h" #include "ui/views/controls/label.h" #include "ui/views/widget/widget.h" @@ -38,11 +45,19 @@ constexpr base::TimeDelta kCloseButtonSlowFadeInDelay = base::TimeDelta::FromMilliseconds(750); -void AddChildWithLayer(views::View* parent, views::View* child) { - child->SetPaintToLayer(); - child->layer()->SetFillsBoundsOpaquely(false); - parent->AddChildView(child); -} +constexpr int kCloseButtonInkDropInsetDp = 2; + +constexpr SkColor kCloseButtonColor = SK_ColorWHITE; + +// Value should match the one in +// ash/resources/vector_icons/overview_window_close.icon. +constexpr int kCloseButtonIconMarginDp = 5; + +// The colors of the close button ripple. +constexpr SkColor kCloseButtonInkDropRippleColor = + SkColorSetA(kCloseButtonColor, 0x0F); +constexpr SkColor kCloseButtonInkDropRippleHighlightColor = + SkColorSetA(kCloseButtonColor, 0x14); // Animates |layer| from 0 -> 1 opacity if |visible| and 1 -> 0 opacity // otherwise. The tween type differs for |visible| and if |visible| is true @@ -67,21 +82,81 @@ layer->SetOpacity(target_opacity); } +// The close button for the overview item. It has a custom ink drop. +class OverviewCloseButton : public views::ImageButton { + public: + explicit OverviewCloseButton(views::ButtonListener* listener) + : views::ImageButton(listener) { + SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); + SetImage( + views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(kOverviewWindowCloseIcon, kCloseButtonColor)); + SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER); + SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE); + SetMinimumImageSize(gfx::Size(kHeaderHeightDp, kHeaderHeightDp)); + SetAccessibleName(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); + SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE)); + } + + ~OverviewCloseButton() override = default; + + // Resets the listener so that the listener can go out of scope. + void ResetListener() { listener_ = nullptr; } + + protected: + // views::Button: + std::unique_ptr<views::InkDrop> CreateInkDrop() override { + auto ink_drop = std::make_unique<views::InkDropImpl>(this, size()); + ink_drop->SetAutoHighlightMode( + views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE); + ink_drop->SetShowHighlightOnHover(true); + return ink_drop; + } + + std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override { + return std::make_unique<views::FloodFillInkDropRipple>( + size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(), + kCloseButtonInkDropRippleColor, /*visible_opacity=*/1.f); + } + + std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() + const override { + return std::make_unique<views::InkDropHighlight>( + gfx::PointF(GetLocalBounds().CenterPoint()), + std::make_unique<views::CircleLayerDelegate>( + kCloseButtonInkDropRippleHighlightColor, GetInkDropRadius())); + } + + std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override { + return std::make_unique<views::CircleInkDropMask>( + size(), GetLocalBounds().CenterPoint(), GetInkDropRadius()); + } + + private: + int GetInkDropRadius() const { + return std::min(size().width(), size().height()) / 2 - + kCloseButtonInkDropInsetDp; + } + + DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); +}; + } // namespace -OverviewItemView::OverviewItemView(EventDelegate* event_delegate, +OverviewItemView::OverviewItemView(OverviewItem* overview_item, aura::Window* window, - bool show_preview, - views::ImageButton* close_button) - : WindowMiniView(window), - event_delegate_(event_delegate), - close_button_(close_button) { + bool show_preview) + : WindowMiniView(window, /*views_should_paint_to_layers=*/true), + overview_item_(overview_item) { + DCHECK(overview_item_); // This should not be focusable. It's also to avoid accessibility error when // |window->GetTitle()| is empty. SetFocusBehavior(FocusBehavior::NEVER); - if (close_button) - AddChildWithLayer(header_view(), close_button); + close_button_ = new OverviewCloseButton(overview_item_); + close_button_->SetPaintToLayer(); + close_button_->layer()->SetFillsBoundsOpaquely(false); + AddChildViewOf(header_view(), close_button_); // Call this last as it calls |Layout()| which relies on the some of the other // elements existing. @@ -137,8 +212,9 @@ layer->SetOpacity(1.f); } -void OverviewItemView::ResetEventDelegate() { - event_delegate_ = nullptr; +void OverviewItemView::OnOverviewItemWindowRestoring() { + overview_item_ = nullptr; + static_cast<OverviewCloseButton*>(close_button_)->ResetListener(); } void OverviewItemView::RefreshPreviewView() { @@ -149,6 +225,51 @@ Layout(); } +void OverviewItemView::UpdatePreviewRoundedCorners(bool show, float rounding) { + if (!preview_view()) + return; + + DCHECK(preview_view()->layer()); + const float scale = preview_view()->layer()->transform().Scale2d().x(); + const gfx::RoundedCornersF radii(show ? rounding / scale : 0.0f); + preview_view()->layer()->SetRoundedCornerRadius(radii); + preview_view()->layer()->SetIsFastRoundedCorner(true); +} + +int OverviewItemView::GetMargin() const { + return kOverviewMargin; +} + +gfx::Rect OverviewItemView::GetHeaderBounds() const { + // The size of the close button resource, |image_width| is scaled up to + // |close_button_width| when laid out. The resource itself contains some + // padding, which is the distance from the edges of the image to the edges of + // the vector icon. We want to align the edges of the image as shown below in + // the diagram. The resource padding, like the rest of the resource is scaled + // up, so calculate the scaled up resource padding. + const int image_width = + close_button_->GetImage(views::ImageButton::STATE_NORMAL).width(); + const int close_button_width = close_button_->width(); + const int right_padding = gfx::ToRoundedInt( + kCloseButtonIconMarginDp * float{close_button_width} / image_width); + const int margin = GetMargin(); + + // Positions the header in a way so that the right aligned close button is + // aligned so that the edge of its icon, not the button lines up with the + // margins. In the diagram below, a represents the the right edge of the + // provided icon (which contains some padding), b represents the right edge of + // |close_button_| and c represents the right edge of the local bounds. + // ---------------------------+---------+ + // | +---+ | + // |title_label_| | | a b + // | +---+ | + // ---------------------------+---------+ + // c + // | + return gfx::Rect(margin, margin, GetLocalBounds().width() - right_padding, + kHeaderHeightDp); +} + views::View* OverviewItemView::GetView() { return this; } @@ -167,13 +288,13 @@ } void OverviewItemView::MaybeActivateHighlightedView() { - if (event_delegate_) - event_delegate_->OnHighlightedViewActivated(); + if (overview_item_) + overview_item_->OnHighlightedViewActivated(); } void OverviewItemView::MaybeCloseHighlightedView() { - if (event_delegate_) - event_delegate_->OnHighlightedViewClosed(); + if (overview_item_) + overview_item_->OnHighlightedViewClosed(); } gfx::Point OverviewItemView::GetMagnifierFocusPointInScreen() { @@ -189,37 +310,37 @@ } bool OverviewItemView::OnMousePressed(const ui::MouseEvent& event) { - if (!event_delegate_) - return Button::OnMousePressed(event); - event_delegate_->HandleMouseEvent(event); + if (!overview_item_) + return views::View::OnMousePressed(event); + overview_item_->HandleMouseEvent(event); return true; } bool OverviewItemView::OnMouseDragged(const ui::MouseEvent& event) { - if (!event_delegate_) - return Button::OnMouseDragged(event); - event_delegate_->HandleMouseEvent(event); + if (!overview_item_) + return views::View::OnMouseDragged(event); + overview_item_->HandleMouseEvent(event); return true; } void OverviewItemView::OnMouseReleased(const ui::MouseEvent& event) { - if (!event_delegate_) { - Button::OnMouseReleased(event); + if (!overview_item_) { + views::View::OnMouseReleased(event); return; } - event_delegate_->HandleMouseEvent(event); + overview_item_->HandleMouseEvent(event); } void OverviewItemView::OnGestureEvent(ui::GestureEvent* event) { - if (!event_delegate_) + if (!overview_item_) return; - if (event_delegate_->ShouldIgnoreGestureEvents()) { + if (overview_item_->ShouldIgnoreGestureEvents()) { event->SetHandled(); return; } - event_delegate_->HandleGestureEvent(event); + overview_item_->HandleGestureEvent(event); event->SetHandled(); } @@ -235,11 +356,11 @@ accept_events = false; } - return accept_events && Button::CanAcceptEvent(event); + return accept_events && views::View::CanAcceptEvent(event); } void OverviewItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) { - views::Button::GetAccessibleNodeData(node_data); + WindowMiniView::GetAccessibleNodeData(node_data); node_data->AddStringAttribute( ax::mojom::StringAttribute::kDescription, l10n_util::GetStringUTF8(
diff --git a/ash/wm/overview/overview_item_view.h b/ash/wm/overview/overview_item_view.h index 98342885..a1b16a70 100644 --- a/ash/wm/overview/overview_item_view.h +++ b/ash/wm/overview/overview_item_view.h
@@ -19,6 +19,7 @@ } // namespace views namespace ash { +class OverviewItem; // OverviewItemView covers the overview window and listens for events. class ASH_EXPORT OverviewItemView @@ -33,24 +34,11 @@ kVisible, }; - class EventDelegate { - public: - virtual void HandleMouseEvent(const ui::MouseEvent& event) = 0; - virtual void HandleGestureEvent(ui::GestureEvent* event) = 0; - virtual bool ShouldIgnoreGestureEvents() = 0; - virtual void OnHighlightedViewActivated() = 0; - virtual void OnHighlightedViewClosed() = 0; - - protected: - virtual ~EventDelegate() {} - }; - // If |show_preview| is true, this class will contain a child view which // mirrors |window|. - OverviewItemView(EventDelegate* event_delegate, + OverviewItemView(OverviewItem* overview_item, aura::Window* window, - bool show_preview, - views::ImageButton* close_button); + bool show_preview); ~OverviewItemView() override; // Fades the app icon and title out if |visibility| is kInvisible, in @@ -65,12 +53,21 @@ // not kInvisible. void HideCloseInstantlyAndThenShowItSlowly(); - void ResetEventDelegate(); + // Called when |overview_item_| is about to be restored to its original state + // outside of overview. + void OnOverviewItemWindowRestoring(); // Refreshes |preview_view_| so that its content is up-to-date. Used by tab // dragging. void RefreshPreviewView(); + // Sets or hides rounded corners on |preview_view_|, if it exists. + void UpdatePreviewRoundedCorners(bool show, float rounding); + + // WindowMiniView: + int GetMargin() const override; + gfx::Rect GetHeaderBounds() const override; + // OverviewHighlightController::OverviewHighlightableView: views::View* GetView() override; gfx::Rect GetHighlightBoundsInScreen() override; @@ -78,6 +75,8 @@ void MaybeCloseHighlightedView() override; gfx::Point GetMagnifierFocusPointInScreen() override; + views::ImageButton* close_button() { return close_button_; } + protected: // views::View: const char* GetClassName() const override; @@ -89,8 +88,9 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; private: - // The delegate which all the events get forwarded to. - EventDelegate* event_delegate_; + // The OverviewItem which owns the widget which houses this view. Non-null + // until |OnOverviewItemWindowRestoring| is called. + OverviewItem* overview_item_; views::ImageButton* close_button_;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index af823e1e..1db5922 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -2261,9 +2261,9 @@ generator->PressLeftButton(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0.f, item1->GetTitlebarOpacityForTesting()); - EXPECT_EQ(1.f, item1->GetCloseButtonVisibilityForTesting()); + EXPECT_EQ(1.f, item1->GetCloseButtonOpacityForTesting()); EXPECT_EQ(1.f, item2->GetTitlebarOpacityForTesting()); - EXPECT_EQ(0.f, item2->GetCloseButtonVisibilityForTesting()); + EXPECT_EQ(0.f, item2->GetCloseButtonOpacityForTesting()); // Drag |item1| in a way so that |window1| does not get activated (drags // within a certain threshold count as clicks). Verify the close button and @@ -2277,9 +2277,9 @@ generator->ReleaseLeftButton(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1.f, item1->GetTitlebarOpacityForTesting()); - EXPECT_EQ(1.f, item1->GetCloseButtonVisibilityForTesting()); + EXPECT_EQ(1.f, item1->GetCloseButtonOpacityForTesting()); EXPECT_EQ(1.f, item2->GetTitlebarOpacityForTesting()); - EXPECT_EQ(1.f, item2->GetCloseButtonVisibilityForTesting()); + EXPECT_EQ(1.f, item2->GetCloseButtonOpacityForTesting()); histogram_tester.ExpectTotalCount( "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1); histogram_tester.ExpectTotalCount(
diff --git a/ash/wm/overview/overview_test_util.cc b/ash/wm/overview/overview_test_util.cc index d802fd5..52f9e6f0 100644 --- a/ash/wm/overview/overview_test_util.cc +++ b/ash/wm/overview/overview_test_util.cc
@@ -7,6 +7,7 @@ #include "ash/shell.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" +#include "ash/wm/overview/overview_highlight_controller.h" #include "ash/wm/overview/overview_item.h" #include "ui/events/test/event_generator.h"
diff --git a/ash/wm/window_cycle_list.cc b/ash/wm/window_cycle_list.cc index 31f206b3..b31bfe0 100644 --- a/ash/wm/window_cycle_list.cc +++ b/ash/wm/window_cycle_list.cc
@@ -4,7 +4,6 @@ #include "ash/wm/window_cycle_list.h" -#include <list> #include <map> #include <memory> @@ -12,6 +11,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/window_mini_view.h" #include "ash/wm/window_preview_view.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" @@ -47,33 +47,20 @@ // at 14% opacity. constexpr SkColor kHighlightAndBackdropColor = SkColorSetA(SK_ColorWHITE, 0x24); -// The color of the window title. -constexpr SkColor kTitleColor = SkColorSetRGB(241, 243, 244); - // Used for the shield (black background). constexpr float kBackgroundCornerRadius = 4.f; // Corner radius applied to the alt-tab selector border. constexpr gfx::RoundedCornersF kWindowSelectionCornerRadii{9}; -// Horizontal spacing between header child views. -constexpr int kHeaderChildPaddingDp = 12; - -// Vertical padding for the label views. -constexpr int kVerticalLabelPaddingDp = 12; - -// The size in dp of the window icon shown on the alt tab window next to the -// title. -constexpr gfx::Size kIconSize{24, 24}; - -// The font delta of the window title. The base font is 12pt (for English) so -// this comes out to 14pt. -constexpr int kLabelFontDelta = 2; - // All previews are the same height (this is achieved via a combination of // scaling and padding). constexpr int kFixedPreviewHeightDp = 256; +// The min and max width for preview size are in relation to the fixed height. +constexpr int kMinPreviewWidthDp = kFixedPreviewHeightDp / 2; +constexpr int kMaxPreviewWidthDp = kFixedPreviewHeightDp * 2; + // Padding between the alt-tab bandshield and the window previews. constexpr int kInsideBorderHorizontalPaddingDp = 64; constexpr int kInsideBorderVerticalPaddingDp = 60; @@ -81,138 +68,64 @@ // Padding between the window previews within the alt-tab bandshield. constexpr int kBetweenChildPaddingDp = 10; -// The min and max width for preview size are in relation to the fixed height. -constexpr int kMinPreviewWidthDp = kFixedPreviewHeightDp / 2; -constexpr int kMaxPreviewWidthDp = kFixedPreviewHeightDp * 2; - } // namespace // This view represents a single aura::Window by displaying a title and a // thumbnail of the window's contents. -class WindowCycleItemView : public views::View, public aura::WindowObserver { +class WindowCycleItemView : public WindowMiniView { public: explicit WindowCycleItemView(aura::Window* window) - : window_title_(new views::Label), - window_thumbnail_backdrop_(new views::View), - preview_view_( - new WindowPreviewView(window, - /*trilinear_filtering_on_init=*/ - features::IsTrilinearFilteringEnabled())) { - header_view_ = new views::View(); - views::BoxLayout* layout = - header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), - kHeaderChildPaddingDp)); - AddChildView(header_view_); - - gfx::ImageSkia* icon = window->GetProperty(aura::client::kAppIconKey); - if (!icon || icon->size().IsEmpty()) - icon = window->GetProperty(aura::client::kWindowIconKey); - if (icon && !icon->size().IsEmpty()) { - image_view_ = new views::ImageView(); - image_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage( - *icon, skia::ImageOperations::RESIZE_BEST, kIconSize)); - image_view_->SetSize(kIconSize); - header_view_->AddChildView(image_view_); - } - - window_observer_.Add(window); - window_title_->SetText(window->GetTitle()); - window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - window_title_->SetEnabledColor(kTitleColor); - window_title_->SetAutoColorReadabilityEnabled(false); - // Background is not fully opaque, so subpixel rendering won't look good. - window_title_->SetSubpixelRenderingEnabled(false); - window_title_->SetFontList(gfx::FontList().Derive( - kLabelFontDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); - window_title_->SetBorder(views::CreateEmptyBorder( - kVerticalLabelPaddingDp, 0, kVerticalLabelPaddingDp, - kHeaderChildPaddingDp)); - header_view_->AddChildView(window_title_); - layout->SetFlexForView(window_title_, 1); - - window_thumbnail_backdrop_->SetBackground( - views::CreateSolidBackground(kHighlightAndBackdropColor)); - AddChildView(window_thumbnail_backdrop_); - - AddChildView(preview_view_); - + : WindowMiniView(window, /*views_should_paint_to_layers=*/false) { + SetShowPreview(/*show=*/true); SetFocusBehavior(FocusBehavior::ALWAYS); } ~WindowCycleItemView() override = default; + private: + // WindowMiniView: + // Returns the size for the preview view, scaled to fit within the max bounds. + // Scaling is always 1:1 and we only scale down, never up. + gfx::Size GetPreviewViewSize() const override { + gfx::Size preview_pref_size = preview_view()->GetPreferredSize(); + if (preview_pref_size.width() > kMaxPreviewWidthDp || + preview_pref_size.height() > kFixedPreviewHeightDp) { + const float scale = + std::min(kMaxPreviewWidthDp / float{preview_pref_size.width()}, + kFixedPreviewHeightDp / float{preview_pref_size.height()}); + preview_pref_size = + gfx::ScaleToFlooredSize(preview_pref_size, scale, scale); + } + + return preview_pref_size; + } + // views::View: + void Layout() override { + WindowMiniView::Layout(); + + // Show the backdrop if the preview view does not take up all the bounds + // allocated for it. + gfx::Rect preview_max_bounds = GetLocalBounds(); + preview_max_bounds.Subtract(GetHeaderBounds()); + const gfx::Rect preview_area_bounds = preview_view()->bounds(); + SetBackdropVisibility(preview_max_bounds.size() != + preview_area_bounds.size()); + } + gfx::Size CalculatePreferredSize() const override { gfx::Size size = GetSizeForPreviewArea(); - size.Enlarge(0, window_title_->GetPreferredSize().height()); + const int header_height = title_label()->GetPreferredSize().height(); + size.Enlarge(0, header_height); return size; } - void Layout() override { - const gfx::Size preview_area_size = GetSizeForPreviewArea(); - // The header view is positioned above the preview area. - header_view_->SetBounds(0, 0, width(), - height() - preview_area_size.height()); - - gfx::Rect preview_area_bounds(preview_area_size); - preview_area_bounds.set_y(height() - preview_area_size.height()); - preview_view_->SetSize(GetMirrorViewScaledSize()); - if (preview_view_->size() == preview_area_size) { - // Padding is not needed, hide the background and set the mirror view - // to take up the entire preview area. - preview_view_->SetPosition(preview_area_bounds.origin()); - window_thumbnail_backdrop_->SetVisible(false); - return; - } - - // Padding is needed, so show the background and set the mirror view to be - // centered within it. - window_thumbnail_backdrop_->SetBoundsRect(preview_area_bounds); - window_thumbnail_backdrop_->SetVisible(true); - preview_area_bounds.ClampToCenteredSize(preview_view_->size()); - preview_view_->SetPosition(preview_area_bounds.origin()); - } - - void GetAccessibleNodeData(ui::AXNodeData* node_data) override { - node_data->role = ax::mojom::Role::kWindow; - node_data->SetName(window_title_->GetText()); - } - - // aura::WindowObserver: - void OnWindowDestroying(aura::Window* window) override { - window_observer_.Remove(window); - } - - void OnWindowTitleChanged(aura::Window* window) override { - window_title_->SetText(window->GetTitle()); - } - - private: - // Returns the size for the mirror view, scaled to fit within the max bounds. - // Scaling is always 1:1 and we only scale down, never up. - gfx::Size GetMirrorViewScaledSize() const { - gfx::Size mirror_pref_size = preview_view_->GetPreferredSize(); - - if (mirror_pref_size.width() > kMaxPreviewWidthDp || - mirror_pref_size.height() > kFixedPreviewHeightDp) { - const float scale = std::min( - kMaxPreviewWidthDp / static_cast<float>(mirror_pref_size.width()), - kFixedPreviewHeightDp / - static_cast<float>(mirror_pref_size.height())); - mirror_pref_size = - gfx::ScaleToFlooredSize(mirror_pref_size, scale, scale); - } - - return mirror_pref_size; - } - - // Returns the size for the entire preview area (mirror view and additional - // padding). All previews will be the same height, so if the mirror view isn't - // tall enough we will add top and bottom padding. Previews can range in width - // from half to double of kFixedPreviewHeightDp. Again, padding will be added - // to the sides to achieve this if the preview is too narrow. + // Returns the size for the entire preview area (preview view and additional + // padding). All previews will be the same height, so if the preview view + // isn't tall enough we will add top and bottom padding. Previews can range + // in width from half to double of |kFixedPreviewHeightDp|. Again, padding + // will be added to the sides to achieve this if the preview is too narrow. gfx::Size GetSizeForPreviewArea() const { - gfx::Size preview_size = GetMirrorViewScaledSize(); + gfx::Size preview_size = GetPreviewViewSize(); // All previews are the same height (this may add padding on top and // bottom). @@ -226,19 +139,6 @@ return preview_size; } - // Views which contains the icon, title. - views::View* header_view_ = nullptr; - views::ImageView* image_view_ = nullptr; - // Displays the title of the window above the preview. - views::Label* window_title_; - // When visible, shows a darkened backdrop area behind |preview_view_| - // (effectively padding the preview to fit the desired bounds). - views::View* window_thumbnail_backdrop_; - // The view that actually renders a thumbnail version of the window. - WindowPreviewView* preview_view_; - - ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this}; - DISALLOW_COPY_AND_ASSIGN(WindowCycleItemView); }; @@ -273,8 +173,8 @@ mirror_container_->layer()->SetFillsBoundsOpaquely(false); for (auto* window : windows) { - // |mirror_container_| owns |view|. The |preview_view_| in |view| will use - // trilinear filtering in InitLayerOwner(). + // |mirror_container_| owns |view|. The |preview_view_| in |view| will + // use trilinear filtering in InitLayerOwner(). views::View* view = new WindowCycleItemView(window); window_view_map_[window] = view; mirror_container_->AddChildView(view); @@ -309,9 +209,10 @@ DCHECK_EQ(mirror_container_, parent); window_view_map_.erase(view_iter); delete preview; - // With one of its children now gone, we must re-layout |mirror_container_|. - // This must happen before SetTargetWindow() to make sure our own Layout() - // works correctly when it's calculating highlight bounds. + // With one of its children now gone, we must re-layout + // |mirror_container_|. This must happen before SetTargetWindow() to make + // sure our own Layout() works correctly when it's calculating highlight + // bounds. parent->Layout(); SetTargetWindow(new_target); } @@ -332,9 +233,9 @@ return; bool first_layout = mirror_container_->bounds().IsEmpty(); - // If |mirror_container_| has not yet been laid out, we must lay it and its - // descendants out so that the calculations based on |target_view| work - // properly. + // If |mirror_container_| has not yet been laid out, we must lay it and + // its descendants out so that the calculations based on |target_view| + // work properly. if (first_layout) mirror_container_->SizeToPreferredSize(); @@ -348,8 +249,8 @@ int x_offset = (width() - container_bounds.width()) / 2; if (x_offset < 0) { // Case two: the container is wider than the screen. Center the target - // view by moving the list just enough to ensure the target view is in the - // center. + // view by moving the list just enough to ensure the target view is in + // the center. x_offset = width() / 2 - mirror_container_->GetMirroredXInView( target_bounds.CenterPoint().x()); @@ -458,8 +359,8 @@ if (windows_.empty()) return; - // When there is only one window, we should give feedback to the user. If the - // window is minimized, we should also show it. + // When there is only one window, we should give feedback to the user. If + // the window is minimized, we should also show it. if (windows_.size() == 1) { ::wm::AnimateWindow(windows_[0], ::wm::WINDOW_ANIMATION_TYPE_BOUNCE); SelectWindow(windows_[0]); @@ -469,9 +370,9 @@ DCHECK(static_cast<size_t>(current_index_) < windows_.size()); if (!cycle_view_ && current_index_ == 0) { - // Special case the situation where we're cycling forward but the MRU window - // is not active. This occurs when all windows are minimized. The starting - // window should be the first one rather than the second. + // Special case the situation where we're cycling forward but the MRU + // window is not active. This occurs when all windows are minimized. The + // starting window should be the first one rather than the second. if (direction == WindowCycleController::FORWARD && !wm::IsActiveWindow(windows_[0])) current_index_ = -1;
diff --git a/ash/wm/window_mini_view.cc b/ash/wm/window_mini_view.cc index 97dc2727..5161987 100644 --- a/ash/wm/window_mini_view.cc +++ b/ash/wm/window_mini_view.cc
@@ -4,14 +4,12 @@ #include "ash/wm/window_mini_view.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/wm/overview/overview_constants.h" #include "ash/wm/overview/rounded_rect_view.h" #include "ash/wm/window_preview_view.h" +#include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/ax_node_data.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/compositor/layer.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" @@ -33,16 +31,13 @@ // The font delta of the window title. constexpr int kLabelFontDelta = 2; +// TODO(sammiequon): Combine this with the duplicate in overview. +constexpr int kHeaderHeightDp = 40; + // Values of the backdrop. constexpr int kBackdropRoundingDp = 4; constexpr SkColor kBackdropColor = SkColorSetA(SK_ColorWHITE, 0x24); -void AddChildWithLayer(views::View* parent, views::View* child) { - child->SetPaintToLayer(); - child->layer()->SetFillsBoundsOpaquely(false); - parent->AddChildView(child); -} - } // namespace WindowMiniView::~WindowMiniView() = default; @@ -54,17 +49,12 @@ if (!backdrop_view_) { backdrop_view_ = new RoundedRectView(kBackdropRoundingDp, kBackdropColor); backdrop_view_->set_can_process_events_within_subtree(false); - AddChildWithLayer(this, backdrop_view_); + AddChildViewOf(this, backdrop_view_); Layout(); } backdrop_view_->SetVisible(visible); } -void WindowMiniView::SetTitle(const base::string16& title) { - title_label_->SetText(title); - SetAccessibleName(title); -} - void WindowMiniView::SetShowPreview(bool show) { if (show == !!preview_view_) return; @@ -80,32 +70,35 @@ preview_view_ = new WindowPreviewView(source_window_, /*trilinear_filtering_on_init=*/false); - AddChildWithLayer(this, preview_view_); + AddChildViewOf(this, preview_view_); Layout(); } -void WindowMiniView::UpdatePreviewRoundedCorners(bool show, float rounding) { - if (!preview_view_) - return; - - const float scale = preview_view_->layer()->transform().Scale2d().x(); - const gfx::RoundedCornersF radii(show ? rounding / scale : 0.0f); - preview_view_->layer()->SetRoundedCornerRadius(radii); - preview_view_->layer()->SetIsFastRoundedCorner(true); +int WindowMiniView::GetMargin() const { + return 0; } -WindowMiniView::WindowMiniView(aura::Window* source_window) - : views::Button(nullptr), source_window_(source_window) { - window_observer_.Add(source_window); +gfx::Rect WindowMiniView::GetHeaderBounds() const { + return gfx::Rect(GetLocalBounds().width(), kHeaderHeightDp); +} - SetAccessibleName(source_window->GetTitle()); +gfx::Size WindowMiniView::GetPreviewViewSize() const { + DCHECK(preview_view_); + return preview_view_->GetPreferredSize(); +} + +WindowMiniView::WindowMiniView(aura::Window* source_window, + bool views_should_paint_to_layers) + : source_window_(source_window), + views_should_paint_to_layers_(views_should_paint_to_layers) { + window_observer_.Add(source_window); header_view_ = new views::View(); views::BoxLayout* layout = header_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), kHorizontalLabelPaddingDp)); - AddChildWithLayer(this, header_view_); + AddChildViewOf(this, header_view_); // Prefer kAppIconKey over kWindowIconKey as the app icon is typically larger. gfx::ImageSkia* icon = source_window->GetProperty(aura::client::kAppIconKey); @@ -116,7 +109,7 @@ image_view_->SetImage(gfx::ImageSkiaOperations::CreateResizedImage( *icon, skia::ImageOperations::RESIZE_BEST, kIconSize)); image_view_->SetSize(kIconSize); - header_view_->AddChildView(image_view_); + AddChildViewOf(header_view_, image_view_); } title_label_ = new views::Label(source_window->GetTitle()); @@ -126,13 +119,22 @@ title_label_->SetSubpixelRenderingEnabled(false); title_label_->SetFontList(gfx::FontList().Derive( kLabelFontDelta, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); - header_view_->AddChildView(title_label_); + AddChildViewOf(header_view_, title_label_); layout->SetFlexForView(title_label_, 1); } +void WindowMiniView::AddChildViewOf(views::View* parent, views::View* child) { + parent->AddChildView(child); + if (views_should_paint_to_layers_) { + child->SetPaintToLayer(); + child->layer()->SetFillsBoundsOpaquely(false); + } +} + void WindowMiniView::Layout() { + const int margin = GetMargin(); gfx::Rect bounds(GetLocalBounds()); - bounds.Inset(kOverviewMargin, kOverviewMargin); + bounds.Inset(margin, margin); if (backdrop_view_) { gfx::Rect backdrop_bounds = bounds; @@ -143,16 +145,16 @@ if (preview_view_) { gfx::Rect preview_bounds = bounds; preview_bounds.Inset(0, kHeaderHeightDp, 0, 0); - preview_bounds.ClampToCenteredSize(preview_view_->CalculatePreferredSize()); + preview_bounds.ClampToCenteredSize(GetPreviewViewSize()); preview_view_->SetBoundsRect(preview_bounds); } - // Position the header at the top. The close button should be right aligned so - // that the edge of its icon, not the button itself lines up with the margins. - const gfx::Rect header_bounds(kOverviewMargin, kOverviewMargin, - GetLocalBounds().width() - kWindowMargin, - kHeaderHeightDp); - header_view_->SetBoundsRect(header_bounds); + header_view_->SetBoundsRect(GetHeaderBounds()); +} + +void WindowMiniView::GetAccessibleNodeData(ui::AXNodeData* node_data) { + node_data->role = ax::mojom::Role::kWindow; + node_data->SetName(title_label_->GetText()); } void WindowMiniView::OnWindowDestroying(aura::Window* window) { @@ -164,4 +166,8 @@ SetShowPreview(false); } +void WindowMiniView::OnWindowTitleChanged(aura::Window* window) { + title_label_->SetText(window->GetTitle()); +} + } // namespace ash
diff --git a/ash/wm/window_mini_view.h b/ash/wm/window_mini_view.h index 54140d4..d1130487 100644 --- a/ash/wm/window_mini_view.h +++ b/ash/wm/window_mini_view.h
@@ -25,7 +25,7 @@ // WindowMiniView is a view which contains a header and optionally a mirror of // the given window. Displaying the mirror is chosen by the subclass by calling // |SetShowPreview| in their constructors (or later on if they like). -class ASH_EXPORT WindowMiniView : public views::Button, +class ASH_EXPORT WindowMiniView : public views::View, public aura::WindowObserver { public: ~WindowMiniView() override; @@ -33,27 +33,35 @@ // Sets the visiblity of |backdrop_view_|. Creates it if it is null. void SetBackdropVisibility(bool visible); - // Set the title of the view, and also updates the accessibility name. - void SetTitle(const base::string16& title); - // Creates or deletes |preview_view_| as needed. void SetShowPreview(bool show); - void UpdatePreviewRoundedCorners(bool show, float rounding); - views::View* header_view() { return header_view_; } - views::Label* title_label() { return title_label_; } + views::Label* title_label() const { return title_label_; } RoundedRectView* backdrop_view() { return backdrop_view_; } - WindowPreviewView* preview_view() { return preview_view_; } + WindowPreviewView* preview_view() const { return preview_view_; } protected: - explicit WindowMiniView(aura::Window* source_window); + WindowMiniView(aura::Window* source_window, + bool views_should_paint_to_layers); + + // Adds |child| as a child of |parent|. May set child view to have a layer if + // |views_should_paint_to_layers_| is true. + void AddChildViewOf(views::View* parent, views::View* child); + + // Subclasses can override these functions to provide customization for + // margins and layouts of certain elements. + virtual int GetMargin() const; + virtual gfx::Rect GetHeaderBounds() const; + virtual gfx::Size GetPreviewViewSize() const; // views::View: void Layout() override; + void GetAccessibleNodeData(ui::AXNodeData* node_data) override; // aura::WindowObserver: void OnWindowDestroying(aura::Window* window) override; + void OnWindowTitleChanged(aura::Window* window) override; private: // The window this class is meant to be a header for. This class also may @@ -72,6 +80,9 @@ // Optionally shows a preview of |window_|. WindowPreviewView* preview_view_ = nullptr; + // If true, views added to this view subtree have layers. + const bool views_should_paint_to_layers_; + ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this}; DISALLOW_COPY_AND_ASSIGN(WindowMiniView);
diff --git a/base/BUILD.gn b/base/BUILD.gn index 7ce56fe..7ef497de4 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -194,7 +194,6 @@ "containers/adapters.h", "containers/buffer_iterator.h", "containers/checked_iterators.h", - "containers/checked_range.h", "containers/circular_deque.h", "containers/flat_map.h", "containers/flat_set.h", @@ -2530,7 +2529,6 @@ "component_export_unittest.cc", "containers/adapters_unittest.cc", "containers/buffer_iterator_unittest.cc", - "containers/checked_range_unittest.cc", "containers/circular_deque_unittest.cc", "containers/flat_map_unittest.cc", "containers/flat_set_unittest.cc",
diff --git a/base/android/bundle_utils.cc b/base/android/bundle_utils.cc index bc02afe..b3939a61 100644 --- a/base/android/bundle_utils.cc +++ b/base/android/bundle_utils.cc
@@ -51,7 +51,10 @@ JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jstring> java_path = Java_BundleUtils_getNativeLibraryPath( env, base::android::ConvertUTF8ToJavaString(env, library_name)); - DCHECK(java_path); + // TODO(https://crbug.com/1019853): Remove this tolerance. + if (!java_path) { + return std::string(); + } return base::android::ConvertJavaStringToUTF8(env, java_path); } @@ -63,10 +66,13 @@ } // static -void* BundleUtils::DlOpenModuleLibraryPartition( - const std::string& library_name) { +void* BundleUtils::DlOpenModuleLibraryPartition(const std::string& library_name, + const std::string& partition) { + // TODO(https://crbug.com/1019853): Remove this tolerance. std::string library_path = ResolveLibraryPath(library_name); - std::string partition = base::FilePath(library_path).BaseName().value(); + if (library_path.empty()) { + return nullptr; + } // Linear search is required here because the partition descriptors are not // ordered. If a large number of partitions come into existence, lld could be
diff --git a/base/android/bundle_utils.h b/base/android/bundle_utils.h index e74b2a6d..6741dd72 100644 --- a/base/android/bundle_utils.h +++ b/base/android/bundle_utils.h
@@ -21,8 +21,14 @@ // dlopen wrapper that works for partitioned native libraries in dynamic // feature modules. This routine looks up the partition's address space in a // table of main library symbols, and uses it when loading the feature - // library. - static void* DlOpenModuleLibraryPartition(const std::string& library_name); + // library. It requires |library_name| (eg. chrome_foo) to resolve the file + // path (which may be in an interesting location due to SplitCompat) and + // |partition_name| to look up the load parameters in the main library. These + // two values may be identical, but since the partition name is set at compile + // time, and the code is linked into multiple libraries (eg. Chrome vs + // Monochrome), they may not be. + static void* DlOpenModuleLibraryPartition(const std::string& library_name, + const std::string& partition); }; } // namespace android
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java index 1228c52..c902a1d 100644 --- a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java +++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
@@ -12,6 +12,7 @@ import android.util.Log; import org.chromium.base.annotations.NativeMethods; +import org.chromium.base.metrics.RecordHistogram; /** * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring @@ -72,7 +73,7 @@ * successful. */ public void endRecording() { - if (mRecorder.endRecording()) { + if (mRecorder.endRecording() && RecordHistogram.sDisabledBy == null) { AnimationFrameTimeHistogramJni.get().saveHistogram( mHistogramName, mRecorder.getFrameTimesMs(), mRecorder.getFrameTimesCount()); }
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java index 7b1f28b..9778e202 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -29,7 +29,13 @@ @JNINamespace("base::android") @MainDex public class RecordHistogram { - private static Throwable sDisabledBy; + /** + * Whether recording histograms is currently disabled for testing. Exposed for use in peer + * classes {e.g. AnimationFrameTimeHistogram}. + * Use {@link #setDisabledForTests(boolean)} to set this value. + */ + @VisibleForTesting + public static Throwable sDisabledBy; private static Map<String, Long> sCache = Collections.synchronizedMap(new HashMap<String, Long>());
diff --git a/base/android/java/src/org/chromium/base/process_launcher/OWNERS b/base/android/java/src/org/chromium/base/process_launcher/OWNERS index c2edc66a..7c9ae35 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/OWNERS +++ b/base/android/java/src/org/chromium/base/process_launcher/OWNERS
@@ -1,5 +1,4 @@ boliu@chromium.org -jcivelli@chromium.org per-file *.aidl=set noparent per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h index cdfd290..bf3d6949 100644 --- a/base/containers/checked_iterators.h +++ b/base/containers/checked_iterators.h
@@ -38,9 +38,9 @@ constexpr CheckedContiguousIterator(const CheckedContiguousIterator& other) = default; - // Converting constructor allowing conversions like CCI<T> to CCI<const T>, - // but disallowing CCI<const T> to CCI<T> or CCI<Derived> to CCI<Base>, which - // are unsafe. Furthermore, this is the same condition as used by the + // Converting constructor allowing conversions like CRAI<T> to CRAI<const T>, + // but disallowing CRAI<const T> to CRAI<T> or CRAI<Derived> to CRAI<Base>, + // which are unsafe. Furthermore, this is the same condition as used by the // converting constructors of std::span<T> and std::unique_ptr<T[]>. // See https://wg21.link/n4042 for details. template < @@ -108,7 +108,7 @@ return *this; } - constexpr CheckedContiguousIterator operator--(int) { + constexpr CheckedContiguousIterator& operator--(int) { CheckedContiguousIterator old = *this; --*this; return old; @@ -132,9 +132,9 @@ constexpr CheckedContiguousIterator& operator-=(difference_type rhs) { if (rhs < 0) { - CHECK_LE(-rhs, end_ - current_); + CHECK_LE(rhs, end_ - current_); } else { - CHECK_LE(rhs, current_ - start_); + CHECK_LE(-rhs, current_ - start_); } current_ -= rhs; return *this;
diff --git a/base/containers/checked_range.h b/base/containers/checked_range.h deleted file mode 100644 index 281ffa4..0000000 --- a/base/containers/checked_range.h +++ /dev/null
@@ -1,162 +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_CONTAINERS_CHECKED_RANGE_H_ -#define BASE_CONTAINERS_CHECKED_RANGE_H_ - -#include <stddef.h> - -#include <iterator> -#include <type_traits> - -#include "base/containers/checked_iterators.h" -#include "base/stl_util.h" - -namespace base { - -// CheckedContiguousRange is a light-weight wrapper around a container modeling -// the ContiguousContainer requirement [1, 2]. Effectively this means that the -// container stores its elements contiguous in memory. Furthermore, it is -// expected that base::data(container) and base::size(container) are valid -// expressions, and that data() + idx is dereferencable for all idx in the -// range[0, size()). In the standard library this includes the containers -// std::string, std::vector and std::array, but other containers like -// std::initializer_list and C arrays are supported as well. -// -// In general this class is in nature quite similar to base::span, and its API -// is inspired by it. However, one important difference is that this class -// stores a pointer to the underlying container (as opposed to just storing its -// data() and size()), and thus is able to deal with changes to the container, -// such as removing or adding elements. -// -// Note however that this class still does not extend the life time of the -// underlying container, and thus callers need to make sure that the container -// outlives the view to avoid dangling pointers and references. -// -// Lastly, this class leverages base::CheckedContiguousIterator to perform -// bounds CHECKs, causing program termination when e.g. dereferencing the end -// iterator. -// -// [1] https://en.cppreference.com/w/cpp/named_req/ContiguousContainer -// [2] -// https://eel.is/c++draft/container.requirements.general#def:contiguous_container -template <typename ContiguousContainer> -class CheckedContiguousRange { - public: - using element_type = std::remove_pointer_t<decltype( - base::data(std::declval<ContiguousContainer&>()))>; - using value_type = std::remove_cv_t<element_type>; - using reference = element_type&; - using const_reference = const element_type&; - using pointer = element_type*; - using const_pointer = const element_type*; - using iterator = CheckedContiguousIterator<element_type>; - using const_iterator = CheckedContiguousConstIterator<element_type>; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using difference_type = typename iterator::difference_type; - using size_type = size_t; - - static_assert(!std::is_reference<ContiguousContainer>::value, - "Error: ContiguousContainer can not be a reference."); - - // Required for converting constructor below. - template <typename Container> - friend class CheckedContiguousRange; - - constexpr CheckedContiguousRange() noexcept = default; - - // Templated constructor restricted to possibly rvref qualified versions of - // ContiguousContainer. This makes sure it does not shadow the auto generated - // copy and move constructors. - template <int&... ExplicitArgumentBarrier, - typename Container, - typename = std::enable_if_t<std::is_same< - std::remove_cv_t<std::remove_reference_t<ContiguousContainer>>, - std::remove_cv_t<std::remove_reference_t<Container>>>::value>> - constexpr CheckedContiguousRange(Container&& container) noexcept - : container_(&container) {} - - // Converting constructor allowing conversions like CCR<C> to CCR<const C>, - // but disallowing CCR<const C> to CCR<C> or CCR<Derived[]> to CCR<Base[]>, - // which are unsafe. Furthermore, this is the same condition as used by the - // converting constructors of std::span<T> and std::unique_ptr<T[]>. - // See https://wg21.link/n4042 for details. - template <int&... ExplicitArgumentBarrier, - typename Container, - typename = std::enable_if_t<std::is_convertible< - typename CheckedContiguousRange<Container>::element_type (*)[], - element_type (*)[]>::value>> - constexpr CheckedContiguousRange( - CheckedContiguousRange<Container> range) noexcept - : container_(range.container_) {} - - constexpr iterator begin() const noexcept { - return iterator(data(), data(), data() + size()); - } - - constexpr iterator end() const noexcept { - return iterator(data(), data() + size(), data() + size()); - } - - constexpr const_iterator cbegin() const noexcept { return begin(); } - - constexpr const_iterator cend() const noexcept { return end(); } - - constexpr reverse_iterator rbegin() const noexcept { - return reverse_iterator(end()); - } - - constexpr reverse_iterator rend() const noexcept { - return reverse_iterator(begin()); - } - - constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } - - constexpr const_reverse_iterator crend() const noexcept { return rend(); } - - constexpr reference front() const noexcept { return *begin(); } - - constexpr reference back() const noexcept { return *(end() - 1); } - - constexpr reference operator[](size_type idx) const noexcept { - return *(begin() + idx); - } - - constexpr pointer data() const noexcept { return base::data(*container_); } - - constexpr const_pointer cdata() const noexcept { return data(); } - - constexpr size_type size() const noexcept { return base::size(*container_); } - - constexpr bool empty() const noexcept { return base::empty(*container_); } - - private: - ContiguousContainer* container_ = nullptr; -}; - -// Utility functions helping to create const ranges and performing automatic -// type deduction. -template <typename ContiguousContainer> -using CheckedContiguousConstRange = - CheckedContiguousRange<const ContiguousContainer>; - -template <int&... ExplicitArgumentBarrier, typename ContiguousContainer> -constexpr auto MakeCheckedContiguousRange( - ContiguousContainer&& container) noexcept { - return CheckedContiguousRange<std::remove_reference_t<ContiguousContainer>>( - std::forward<ContiguousContainer>(container)); -} - -template <int&... ExplicitArgumentBarrier, typename ContiguousContainer> -constexpr auto MakeCheckedContiguousConstRange( - ContiguousContainer&& container) noexcept { - return CheckedContiguousConstRange< - std::remove_reference_t<ContiguousContainer>>( - std::forward<ContiguousContainer>(container)); -} - -} // namespace base - -#endif // BASE_CONTAINERS_CHECKED_RANGE_H_
diff --git a/base/containers/checked_range_unittest.cc b/base/containers/checked_range_unittest.cc deleted file mode 100644 index 3ac1a5f..0000000 --- a/base/containers/checked_range_unittest.cc +++ /dev/null
@@ -1,248 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/containers/checked_range.h" -#include <algorithm> -#include <array> -#include <initializer_list> -#include <type_traits> - -#include "base/strings/string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { - -TEST(CheckedContiguousRange, Constructor_Vector) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - EXPECT_EQ(vector.data(), range.data()); - EXPECT_EQ(vector.size(), range.size()); -} - -TEST(CheckedContiguousRange, Constructor_String) { - std::string str = "Hello World"; - CheckedContiguousRange<std::string> range(str); - EXPECT_EQ(str.data(), range.data()); - EXPECT_EQ(str.size(), range.size()); -} - -TEST(CheckedContiguousRange, Constructor_Array) { - static constexpr int array[] = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const int[5]> range(array); - static_assert(data(array) == range.data(), ""); - static_assert(size(array) == range.size(), ""); -} - -TEST(CheckedContiguousRange, Constructor_StdArray) { - static constexpr std::array<int, 5> array = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const std::array<int, 5>> range(array); - static_assert(data(array) == range.data(), ""); - static_assert(size(array) == range.size(), ""); -} - -TEST(CheckedContiguousRange, Constructor_StringPiece) { - static constexpr base::StringPiece str = "Hello World"; - constexpr CheckedContiguousRange<const base::StringPiece> range(str); - static_assert(str.data() == range.data(), ""); - static_assert(str.size() == range.size(), ""); -} - -TEST(CheckedContiguousRange, Constructor_InitializerList) { - static constexpr std::initializer_list<int> il = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const std::initializer_list<int>> range(il); - static_assert(data(il) == range.data(), ""); - static_assert(size(il) == range.size(), ""); -} - -TEST(CheckedContiguousRange, Constructor_Copy) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - CheckedContiguousRange<std::vector<int>> copy(range); - EXPECT_EQ(vector.data(), copy.data()); - EXPECT_EQ(vector.size(), copy.size()); -} - -TEST(CheckedContiguousRange, Constructor_Move) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - CheckedContiguousRange<std::vector<int>> move(std::move(range)); - EXPECT_EQ(vector.data(), move.data()); - EXPECT_EQ(vector.size(), move.size()); -} - -TEST(CheckedContiguousRange, Copy_Assign) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - CheckedContiguousRange<std::vector<int>> copy; - copy = range; - EXPECT_EQ(vector.data(), copy.data()); - EXPECT_EQ(vector.size(), copy.size()); -} - -TEST(CheckedContiguousRange, Move_Assign) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - CheckedContiguousRange<std::vector<int>> move; - move = std::move(range); - EXPECT_EQ(vector.data(), move.data()); - EXPECT_EQ(vector.size(), move.size()); -} - -TEST(CheckedContiguousRange, Iterators) { - std::vector<int> vector; - CheckedContiguousRange<const std::vector<int>> range(vector); - - // Check that all ranges by the iterators compare equal, even when elements - // are added. - for (size_t i = 0; i < 5; ++i) { - vector.push_back(i); - EXPECT_TRUE( - std::equal(vector.begin(), vector.end(), range.begin(), range.end())); - EXPECT_TRUE(std::equal(vector.cbegin(), vector.cend(), range.cbegin(), - range.cend())); - EXPECT_TRUE(std::equal(vector.rbegin(), vector.rend(), range.rbegin(), - range.rend())); - EXPECT_TRUE(std::equal(vector.crbegin(), vector.crend(), range.crbegin(), - range.crend())); - } -} - -TEST(CheckedContiguousRange, Front) { - static constexpr std::array<int, 5> array = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const std::array<int, 5>> range(array); - static_assert(array.front() == range.front(), ""); -} - -TEST(CheckedContiguousRange, Back) { - static constexpr std::array<int, 5> array = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const std::array<int, 5>> range(array); - static_assert(array.back() == range.back(), ""); -} - -TEST(CheckedContiguousRange, OperatorAt_Constexpr) { - static constexpr std::array<int, 5> array = {1, 2, 3, 4, 5}; - constexpr CheckedContiguousRange<const std::array<int, 5>> range(array); - static_assert(array[0] == range[0], ""); - static_assert(array[1] == range[1], ""); - static_assert(array[2] == range[2], ""); - static_assert(array[3] == range[3], ""); - static_assert(array[4] == range[4], ""); -} - -TEST(CheckedContiguousRange, Mutable_OperatorAt) { - std::vector<int> vector = {1, 2, 3, 4, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - - EXPECT_EQ(vector[0], range[0]); - range[0] = 2; - EXPECT_EQ(vector[0], 2); -} - -TEST(CheckedContiguousRange, Mutable_Data) { - std::vector<int> vector = {3, 1, 4, 2, 5}; - CheckedContiguousRange<std::vector<int>> range(vector); - - EXPECT_FALSE(std::is_sorted(vector.begin(), vector.end())); - std::sort(range.data(), range.data() + range.size()); - EXPECT_TRUE(std::is_sorted(vector.begin(), vector.end())); -} - -TEST(CheckedContiguousRange, DataSizeEmpty_Constexpr) { - static constexpr std::array<int, 0> array = {}; - constexpr CheckedContiguousRange<const std::array<int, 0>> range(array); - static_assert(data(array) == range.data(), ""); - static_assert(data(array) == range.cdata(), ""); - static_assert(size(array) == range.size(), ""); - static_assert(range.empty(), ""); -} - -TEST(CheckedContiguousRange, MakeCheckedContiguousRange) { - using Vec = std::vector<int>; - - static_assert(std::is_same<CheckedContiguousRange<Vec>, - decltype(MakeCheckedContiguousRange( - std::declval<Vec&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousRange( - std::declval<const Vec&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<Vec>, - decltype(MakeCheckedContiguousRange( - std::declval<Vec&&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousRange( - std::declval<const Vec&&>()))>::value, - ""); -} - -TEST(CheckedContiguousRange, MakeCheckedContiguousConstRange) { - using Vec = std::vector<int>; - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousConstRange( - std::declval<Vec&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousConstRange( - std::declval<const Vec&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousConstRange( - std::declval<Vec&&>()))>::value, - ""); - - static_assert(std::is_same<CheckedContiguousRange<const Vec>, - decltype(MakeCheckedContiguousConstRange( - std::declval<const Vec&&>()))>::value, - ""); -} - -TEST(CheckedContiguousRange, Conversions) { - using T = std::vector<int>; - // Check that adding const is allowed, but removing const is not. - static_assert(std::is_convertible<CheckedContiguousRange<T>, - CheckedContiguousRange<const T>>::value, - ""); - static_assert(!std::is_constructible<CheckedContiguousRange<T>, - CheckedContiguousRange<const T>>::value, - ""); - - struct Base {}; - struct Derived : Base {}; - // Check that trying to assign arrays from a derived class fails. - static_assert( - !std::is_constructible<CheckedContiguousRange<Base[5]>, - CheckedContiguousRange<Derived[5]>>::value, - ""); -} - -// Death checks can be very slow. Thus only enable them in release builds. -#ifdef NDEBUG -TEST(CheckedContiguousRange, OutOfBoundsDeath) { - std::vector<int> empty_vector; - CheckedContiguousRange<std::vector<int>> empty_range(empty_vector); - ASSERT_DEATH_IF_SUPPORTED(empty_range[0], ""); - ASSERT_DEATH_IF_SUPPORTED(empty_range.begin()[0], ""); - ASSERT_DEATH_IF_SUPPORTED(empty_range.end()[0], ""); - ASSERT_DEATH_IF_SUPPORTED(*empty_range.begin(), ""); - ASSERT_DEATH_IF_SUPPORTED(*empty_range.end(), ""); - ASSERT_DEATH_IF_SUPPORTED(empty_range.front(), ""); - ASSERT_DEATH_IF_SUPPORTED(empty_range.back(), ""); - - static constexpr int array[] = {0, 1, 2}; - constexpr CheckedContiguousRange<const int[3]> range(array); - ASSERT_DEATH_IF_SUPPORTED(range[3], ""); - ASSERT_DEATH_IF_SUPPORTED(range.begin()[-1], ""); - ASSERT_DEATH_IF_SUPPORTED(range.begin()[3], ""); -} -#endif // NDEBUG - -} // namespace base
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc index 9f85875..de05bdb 100644 --- a/base/containers/span_unittest.cc +++ b/base/containers/span_unittest.cc
@@ -1299,26 +1299,11 @@ EXPECT_EQ(kArray[size], item); } -// Death checks can be very slow. Thus only enable them in release builds. -#ifdef NDEBUG TEST(SpanTest, OutOfBoundsDeath) { constexpr span<int, 0> kEmptySpan; ASSERT_DEATH_IF_SUPPORTED(kEmptySpan[0], ""); ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin()[0], ""); ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end()[0], ""); - ASSERT_DEATH_IF_SUPPORTED(--kEmptySpan.begin(), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin()--, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin() -= 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin() - 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin() += (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.begin() + (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(++kEmptySpan.end(), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end()++, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end() += 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end() + 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end() -= (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.end() - (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(*kEmptySpan.end(), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.first(1), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.last(1), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptySpan.subspan(1), ""); @@ -1327,19 +1312,6 @@ ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan[0], ""); ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin()[0], ""); ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end()[0], ""); - ASSERT_DEATH_IF_SUPPORTED(--kEmptyDynamicSpan.begin(), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin()--, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin() -= 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin() - 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin() += (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.begin() + (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(++kEmptyDynamicSpan.end(), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end()++, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end() += 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end() + 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end() -= (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.end() - (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(*kEmptyDynamicSpan.end(), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.front(), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.first(1), ""); ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.last(1), ""); @@ -1352,23 +1324,9 @@ ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan[4], ""); ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin()[-1], ""); ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin()[3], ""); - ASSERT_DEATH_IF_SUPPORTED(--kNonEmptyDynamicSpan.begin(), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin()--, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin() -= 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin() - 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin() += (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.begin() + (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(++kNonEmptyDynamicSpan.end(), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.end()++, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.end() += 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.end() + 1, ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.end() -= (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.end() - (-1), ""); - ASSERT_DEATH_IF_SUPPORTED(*kNonEmptyDynamicSpan.end(), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.subspan(10), ""); - ASSERT_DEATH_IF_SUPPORTED(kNonEmptyDynamicSpan.subspan(1, 7), ""); + ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.subspan(10), ""); + ASSERT_DEATH_IF_SUPPORTED(kEmptyDynamicSpan.subspan(1, 7), ""); } -#endif // NDEBUG TEST(SpanTest, IteratorIsRangeMoveSafe) { static constexpr int kArray[] = {1, 6, 1, 8, 0};
diff --git a/base/memory/OWNERS b/base/memory/OWNERS index 9b7cbb1..51481fe 100644 --- a/base/memory/OWNERS +++ b/base/memory/OWNERS
@@ -2,3 +2,6 @@ per-file *chromeos*=oshima@chromium.org per-file *shared_memory*=set noparent per-file *shared_memory*=file://ipc/SECURITY_OWNERS +per-file madv_free*=lizeb@chromium.org +per-file madv_free*=pasko@chromium.org +per-file madv_free*=mthiesse@chromium.org
diff --git a/base/stl_util.h b/base/stl_util.h index 4edd1fb..e22b029 100644 --- a/base/stl_util.h +++ b/base/stl_util.h
@@ -144,20 +144,6 @@ return il.begin(); } -// std::array::data() was not constexpr prior to C++17 [1]. -// Hence these overloads are provided. -// -// [1] https://en.cppreference.com/w/cpp/container/array/data -template <typename T, size_t N> -constexpr T* data(std::array<T, N>& array) noexcept { - return !array.empty() ? &array[0] : nullptr; -} - -template <typename T, size_t N> -constexpr const T* data(const std::array<T, N>& array) noexcept { - return !array.empty() ? &array[0] : nullptr; -} - // Returns a const reference to the underlying container of a container adapter. // Works for std::priority_queue, std::queue, and std::stack. template <class A>
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc index 2889b25..8c4f68c 100644 --- a/base/threading/platform_thread_win.cc +++ b/base/threading/platform_thread_win.cc
@@ -33,6 +33,10 @@ // thread mode is enabled on Windows 7. constexpr int kWin7BackgroundThreadModePriority = 4; +// Value sometimes returned by ::GetThreadPriority() after thread priority is +// set to normal on Windows 7. +constexpr int kWin7NormalPriority = 3; + // The information on how to set the thread name comes from // a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx const DWORD kVCThreadNameException = 0x406D1388; @@ -441,6 +445,9 @@ case kWin7BackgroundThreadModePriority: DCHECK_EQ(win::GetVersion(), win::Version::WIN7); return ThreadPriority::BACKGROUND; + case kWin7NormalPriority: + DCHECK_EQ(win::GetVersion(), win::Version::WIN7); + FALLTHROUGH; case THREAD_PRIORITY_NORMAL: return ThreadPriority::NORMAL; case THREAD_PRIORITY_ABOVE_NORMAL:
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc index 7164771..fe35a3af 100644 --- a/base/trace_event/memory_infra_background_whitelist.cc +++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -348,7 +348,6 @@ "sync/0x?/model_type/MANAGED_USER_SETTING", "sync/0x?/model_type/MANAGED_USER_SHARED_SETTING", "sync/0x?/model_type/MANAGED_USER_WHITELIST", - "sync/0x?/model_type/MOUNTAIN_SHARE", "sync/0x?/model_type/NIGORI", "sync/0x?/model_type/OS_PREFERENCE", "sync/0x?/model_type/OS_PRIORITY_PREFERENCE",
diff --git a/build/android/docs/java_toolchain.md b/build/android/docs/java_toolchain.md index fed7654..6a432d3 100644 --- a/build/android/docs/java_toolchain.md +++ b/build/android/docs/java_toolchain.md
@@ -1,4 +1,4 @@ -# Building Dex +# Chromium's Java Toolchain This doc aims to describe the Chrome build process that takes a set of `.java` files and turns them into a `classes.dex` file. @@ -20,7 +20,9 @@ All targets names must end with "_java" so that the build system can distinguish them from non-java targets (or [other variations](https://cs.chromium.org/chromium/src/build/config/android/internal_rules.gni?rcl=ec2c17d7b4e424e060c3c7972842af87343526a1&l=20)). -## Step 1a: Compile with javac +## From Source to Final Dex + +### Step 1a: Compile with javac This step is the only step that does not apply to prebuilt targets. @@ -39,7 +41,7 @@ recompiled. * Prefer smaller targets to avoid slow compiles. -## Step 1b: Compile with ErrorProne +### Step 1b: Compile with ErrorProne This step can be disabled via GN arg: `use_errorprone_java_compiler = false` @@ -51,7 +53,7 @@ [ErrorProne]: https://errorprone.info/ [ep_plugins]: /tools/android/errorprone_plugin/ -## Step 2: Creating an .interface.jar +### Step 2: Creating an .interface.jar This step happens in parallel with subsequent steps. @@ -59,14 +61,19 @@ copy of the input with all non-public symbols and function bodies removed. * Dependant targets use `.interface.jar` files to skip having to be rebuilt when only private implementation details change. + * To accomplish this behavior, library targets list only their + `.interface.jar` as outputs. Ninja's `restat=1` feature then causes + dependent targets to be rebuilt only when the `.interface.jar` changes. + Final dex targets are always rebuilt because they depend on the + non-`.interface.jar` through a `depfile`. -## Step 3: Bytecode Processing +### Step 3: Bytecode Processing * `//build/android/bytecode` runs on the compiled `.jar` in order to: * Enable Java assertions (when dcheck is enabled). * Assert that libraries have properly declared `deps`. -## Step 4: Desugaring +### Step 4: Desugaring This step happens only when targets have `supports_android = true`. @@ -74,7 +81,7 @@ lambdas and default interface methods, into constructs that are compatible with Java 7. -## Step 5: Filtering +### Step 5: Filtering This step happens only when targets that have `jar_excluded_patterns` or `jar_included_patterns` set (e.g. all `android_` targets). @@ -91,7 +98,7 @@ [Android Resources]: life_of_a_resource.md [apphooks]: /chrome/android/java/src/org/chromium/chrome/browser/AppHooksImpl.java -## Step 6: Instrumentation +### Step 6: Instrumentation This step happens only when this GN arg is set: `use_jacoco_coverage = true` @@ -99,14 +106,14 @@ [Jacoco]: https://www.eclemma.org/jacoco/ -## Step 7: Copy to lib.java +### Step 7: Copy to lib.java * The `.jar` is copied into `$root_build_dir/lib.java` (under target-specific subdirectories) so that it will be included by bot archive steps. * These `.jar` files are the ones used when running `java_binary` and `junit_binary` targets. -## Step 8: Per-Library Dexing +### Step 8: Per-Library Dexing This step happens only when targets have `supports_android = true`. @@ -122,16 +129,20 @@ [d8]: https://developer.android.com/studio/command-line/d8 [incremental install]: /build/android/incremental_install/README.md -## Step 9: Apk / Bundle Module Compile +### Step 9: Apk / Bundle Module Compile * Each `android_apk` and `android_bundle_module` template has a nested `java_library` target. The nested library includes final copies of files stripped out by prior filtering steps. These files include: * Final `R.java` files, created by `compile_resources.py`. - * Final `GEN_JNI.java` for JNI glue. + * Final `GEN_JNI.java` for [JNI glue]. * `BuildConfig.java` and `NativeLibraries.java` (//base dependencies). -## Step 10: Final Dexing +[JNI glue]: /base/android/jni_generator/README.md + +### Step 10: Final Dexing + +This step is skipped when building using [Incremental Install]. When `is_java_debug = true`: * [d8] merges all library `.dex.jar` files into a final `.dex.zip`. @@ -142,11 +153,142 @@ * For App Bundles, R8 creates a single `.dex.zip` with the code from all modules. +[Incremental Install]: /build/android/incremental_install/README.md [R8]: https://r8.googlesource.com/r8 -## Step 11: Bundle Module Dex Splitting +### Step 11: Bundle Module Dex Splitting This step happens only when `is_java_debug = false`. * [dexsplitter.py] splits the single `.dex.zip` into per-module `.dex.zip` files. + +## Test APKs with apk_under_test + +Test APKs are normal APKs that contain an `<instrumentation>` tag within their +`AndroidManifest.xml`. If this tag specifies an `android:targetPackage` +different from itself, then Android will add that package's `classes.dex` to the +test APK's Java classpath when run. In GN, you can enable this behavior using +the `apk_under_test` parameter on `instrumentation_test_apk` targets. Using it +is discouraged if APKs have `proguard_enabled=true`. + +### Difference in Final Dex + +When `enable_proguard=false`: +* Any library depended on by the test APK that is also depended on by the + apk-under-test is excluded from the test APK's final dex step. + +When `enable_proguard=true`: +* Test APKs cannot make use of the apk-under-test's dex because only symbols + explicitly kept by `-keep` directives are guaranteed to exist after + ProGuarding. As a work-around, test APKs include all of the apk-under-test's + libraries directly in its own final dex such that the under-test apk's Java + code is never used (because it is entirely shadowed by the test apk's dex). + * We've found this configuration to be fragile, and are trying to [move away + from it](https://bugs.chromium.org/p/chromium/issues/detail?id=890452). + +### Difference in GEN_JNI.java +* Calling native methods using [JNI glue] requires that a `GEN_JNI.java` class + be generated that contains all native methods for an APK. There cannot be + conflicting `GEN_JNI` classes in both the test apk and the apk-under-test, so + only the apk-under-test has one generated for it. As a result this, + instrumentation test APKs that use apk-under-test cannot use native methods + that aren't already part of the apk-under-test. + +## How to Generate Java Source Code +There are two ways to go about generating source files: Annotation Processors +and custom build steps. + +### Annotation Processors +* These are run by `javac` as part of the compile step. +* They **cannot** modify the source files that they apply to. They can only + generate new sources. +* Use these when: + * an existing Annotation Processor does what you want + (E.g. Dagger, AutoService, etc.), or + * you need to understand Java types to do generation. + +### Custom Build Steps +* These use discrete build actions to generate source files. + * Some generate `.java` directly, but most generate a zip file of sources + (called a `.srcjar`) to simplify the number of inputs / outputs. +* Examples of existing templates: + * `jinja_template`: Generates source files using [Jinja]. + * `java_cpp_template`: Generates source files using the C preprocessor. + * `java_cpp_enum`: Generates `@IntDef`s based on enums within `.h` files. + * `java_cpp_strings`: Generates String constants based on strings defined in + `.cc` files. +* Custom build steps are preferred over Annotation Processors because they are + generally easier to understand, and can run in parallel with other steps + (rather than being tied to compiles). + +[Jinja]: https://palletsprojects.com/p/jinja/ + +## Static Analysis & Code Checks + +We use several tools for static analysis. + +### [ErrorProne](https://errorprone.info/) +* Runs as part of normal compilation. Controlled by GN arg: `use_errorprone_java_compiler`. +* Most useful check: + * Enforcement of `@GuardedBy` annotations. +* List of enabled / disabled checks exists [within javac.py](https://cs.chromium.org/chromium/src/build/android/gyp/javac.py?l=30) + * Many checks are currently disabled because there is work involved in fixing + violations they introduce. Please help! +* Custom checks for Chrome: + * [//tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/](/tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/) +* Use ErrorProne checks when you need something more sophisticated than pattern + matching. +* Checks run on the entire codebase, not only on changed lines. +* Does not run when `chromium_code = false` (e.g. for //third_party). + +### [Android Lint](https://developer.android.com/studio/write/lint) +* Runs as part of normal compilation. Controlled by GN arg: `disable_android_lint` +* Most useful check: + * Enforcing `@TargetApi` annotations (ensure you don't call a function that + does not exist on all versions of Android unless guarded by an version + check). +* List of disabled checks: + * [//build/android/lint/suppressions.xml](/build/android/lint/suppressions.xml) +* Custom lint checks [are possible](lint_plugins), but we don't have any. +* Checks run on the entire codebase, not only on changed lines. +* Does not run when `chromium_code = false` (e.g. for //third_party). + +[lint_plugins]: http://tools.android.com/tips/lint-custom-rules + +### [Bytecode Rewriter](/build/android/bytecode/) +* Runs as part of normal compilation. +* Performs a single check: + * That target `deps` are not missing any entries. + * In other words: Enforces that targets do not rely on indirect dependencies + to populate their classpath. +* Checks run on the entire codebase, not only on changed lines. + +### [PRESUBMIT.py](/PRESUBMIT.py): +* Checks for banned patterns via `_BANNED_JAVA_FUNCTIONS`. + * (These should likely be moved to checkstyle). +* Checks for a random set of things in `_AndroidSpecificOnUploadChecks()`. + * Including running Checkstyle. + * (Some of these other checks should likely also be moved to checkstyle). +* Checks run only on changed lines. + +### [Checkstyle](https://checkstyle.sourceforge.io/) +* Checks Java style rules that are not covered by clang-format. + * E.g.: Unused imports and naming conventions. +* Allows custom checks to be added via XML. Here [is ours]. +* Preferred over adding checks directly in PRESUBMIT.py because the tool + understands `@SuppressWarnings` annotations. +* Checks run only on changed lines. + +[is ours]: /tools/android/checkstyle/chromium-style-5.0.xml + +### [clang-format](https://clang.llvm.org/docs/ClangFormat.html) +* Formats `.java` files via `git cl format`. +* Can be toggle on/off with code comments. + ```java + // clang-format off + ... non-formated code here ... + // clang-format on + ``` +* Does not work great for multiple annotations or on some lambda expressions, + but is generally agreed it is better than not having it at all.
diff --git a/build/android/gyp/desugar.py b/build/android/gyp/desugar.py index 407b8f2c..1e1c1567 100755 --- a/build/android/gyp/desugar.py +++ b/build/android/gyp/desugar.py
@@ -38,6 +38,7 @@ options.input_jar, '--output', options.output_jar, + '--generate_base_classes_for_default_methods', # Don't include try-with-resources files in every .jar. Instead, they # are included via //third_party/bazel/desugar:desugar_runtime_java. '--desugar_try_with_resources_omit_runtime_classes',
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index 0de46928..5a33e43 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -402,14 +402,7 @@ parser.add_option( '--java-version', help='Java language version to use in -source and -target args to javac.') - parser.add_option( - '--full-classpath', - action='append', - help='Classpath to use when annotation processors are present.') - parser.add_option( - '--interface-classpath', - action='append', - help='Classpath to use when no annotation processors are present.') + parser.add_option('--classpath', action='append', help='Classpath to use.') parser.add_option( '--processors', action='append', @@ -462,9 +455,7 @@ build_utils.CheckOptions(options, parser, required=('jar_path',)) options.bootclasspath = build_utils.ParseGnList(options.bootclasspath) - options.full_classpath = build_utils.ParseGnList(options.full_classpath) - options.interface_classpath = build_utils.ParseGnList( - options.interface_classpath) + options.classpath = build_utils.ParseGnList(options.classpath) options.processorpath = build_utils.ParseGnList(options.processorpath) options.processors = build_utils.ParseGnList(options.processors) options.java_srcjars = build_utils.ParseGnList(options.java_srcjars) @@ -558,14 +549,6 @@ if options.bootclasspath: javac_cmd.extend(['-bootclasspath', ':'.join(options.bootclasspath)]) - # Annotation processors crash when given interface jars. - active_classpath = ( - options.full_classpath - if options.processors else options.interface_classpath) - classpath = [] - if active_classpath: - classpath.extend(active_classpath) - if options.processorpath: javac_cmd.extend(['-processorpath', ':'.join(options.processorpath)]) if options.processor_args: @@ -574,8 +557,8 @@ javac_cmd.extend(options.javac_arg) - classpath_inputs = (options.bootclasspath + options.interface_classpath + - options.processorpath) + classpath_inputs = ( + options.bootclasspath + options.classpath + options.processorpath) # GN already knows of java_files, so listing them just make things worse when # they change. @@ -588,11 +571,11 @@ options.jar_path + '.info', ] - input_strings = javac_cmd + classpath + java_files + input_strings = javac_cmd + options.classpath + java_files if options.jar_info_exclude_globs: input_strings.append(options.jar_info_exclude_globs) build_utils.CallAndWriteDepfileIfStale( - lambda: _OnStaleMd5(options, javac_cmd, java_files, classpath), + lambda: _OnStaleMd5(options, javac_cmd, java_files, options.classpath), options, depfile_deps=depfile_deps, input_paths=input_paths,
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index f61c73d..350a92b8 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2820,8 +2820,7 @@ "--jar-path=$_rebased_javac_jar_path", "--java-srcjars=$_rebased_java_srcjars", "--java-version=1.8", - "--full-classpath=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", - "--interface-classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", "--processorpath=@FileArg($_rebased_build_config:javac:processor_classpath)", "--processors=@FileArg($_rebased_build_config:javac:processor_classes)", ]
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 7b1c2d43a..4dd518b 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1526,7 +1526,7 @@ # TODO(https://crbug.com/999871): Decide if we want to clean up the # codebase or just disable this. Doesn't seem super useful, but - # also fires in only 4 files. + # also fires in only 2 files. "-Wno-c99-designator", # TODO(https://crbug.com/999886): Clean up, enable. @@ -2217,10 +2217,10 @@ cflags = [] if (clang_emit_debug_info_for_profiling) { # Add the following flags to generate debug info for profiling. - cflags += [ - "-fdebug-info-for-profiling", - "-gline-tables-only", - ] + cflags += [ "-gline-tables-only" ] + if (!is_nacl) { + cflags += [ "-fdebug-info-for-profiling" ] + } } if (_clang_sample_profile != "") { rebased_clang_sample_profile =
diff --git a/build/download_libclang.py b/build/download_libclang.py index e9f232b..e6905ec 100755 --- a/build/download_libclang.py +++ b/build/download_libclang.py
@@ -5,50 +5,16 @@ """Script to download libclang binaries from google storage.""" -import find_depot_tools -import json import os -import shutil -import subprocess import sys -import tarfile -SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) -CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir)) +sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', + 'tools', 'clang', 'scripts')) +import update -DEPOT_PATH = find_depot_tools.add_depot_tools_to_path() -GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py') - -LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build', - 'Release+Asserts') -CLANG_UPDATE_PY = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts', - 'update.py') - -CLANG_BUCKET = 'gs://chromium-browser-clang' - - -def main(): - clang_revision = subprocess.check_output([sys.executable, CLANG_UPDATE_PY, - '--print-revision']).rstrip() - targz_name = 'libclang-%s.tgz' % clang_revision - - if sys.platform == 'win32' or sys.platform == 'cygwin': - cds_full_url = CLANG_BUCKET + '/Win/' + targz_name - elif sys.platform == 'darwin': - cds_full_url = CLANG_BUCKET + '/Mac/' + targz_name - else: - assert sys.platform.startswith('linux') - cds_full_url = CLANG_BUCKET + '/Linux_x64/' + targz_name - - os.chdir(LLVM_BUILD_PATH) - - subprocess.check_call([sys.executable, GSUTIL_PATH, - 'cp', cds_full_url, targz_name]) - tarfile.open(name=targz_name, mode='r:gz').extractall(path=LLVM_BUILD_PATH) - - os.remove(targz_name) - return 0 - +# TODO(hans): Remove this forwarding hack after all callers of this script have +# been updated to call update.py instead. if __name__ == '__main__': - sys.exit(main()) + sys.argv = [sys.argv[0], '--package=libclang'] + sys.exit(update.main())
diff --git a/build/download_translation_unit_tool.py b/build/download_translation_unit_tool.py index b60d33a1..576ec284 100755 --- a/build/download_translation_unit_tool.py +++ b/build/download_translation_unit_tool.py
@@ -3,52 +3,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Script to download Clang translation_unit tool from google storage.""" - -import find_depot_tools -import json import os -import shutil -import subprocess import sys -import tarfile -SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) -CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir)) +sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', + 'tools', 'clang', 'scripts')) +import update -DEPOT_PATH = find_depot_tools.add_depot_tools_to_path() -GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py') - -LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build', - 'Release+Asserts') -CLANG_UPDATE_PY = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts', - 'update.py') - -CLANG_BUCKET = 'gs://chromium-browser-clang' - - -def main(): - clang_revision = subprocess.check_output([sys.executable, CLANG_UPDATE_PY, - '--print-revision']).rstrip() - targz_name = 'translation_unit-%s.tgz' % clang_revision - - if sys.platform == 'win32' or sys.platform == 'cygwin': - cds_full_url = CLANG_BUCKET + '/Win/' + targz_name - elif sys.platform == 'darwin': - cds_full_url = CLANG_BUCKET + '/Mac/' + targz_name - else: - assert sys.platform.startswith('linux') - cds_full_url = CLANG_BUCKET + '/Linux_x64/' + targz_name - - os.chdir(LLVM_BUILD_PATH) - - subprocess.check_call([sys.executable, GSUTIL_PATH, - 'cp', cds_full_url, targz_name]) - tarfile.open(name=targz_name, mode='r:gz').extractall(path=LLVM_BUILD_PATH) - - os.remove(targz_name) - return 0 - +# TODO(hans): Remove this forwarding hack after all callers of this script have +# been updated to call update.py instead. if __name__ == '__main__': - sys.exit(main()) + sys.argv = [sys.argv[0], '--package=translation_unit'] + sys.exit(update.main())
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 966449e..8723f319 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8897644882069353280 \ No newline at end of file +8897614418061955120 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 81a3204fe..574032dd 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8897644931840249616 \ No newline at end of file +8897616019253100944 \ No newline at end of file
diff --git a/build/partitioned_shared_library.gni b/build/partitioned_shared_library.gni index 1e4873d..ca8a3c61 100644 --- a/build/partitioned_shared_library.gni +++ b/build/partitioned_shared_library.gni
@@ -1,4 +1,5 @@ # 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. @@ -17,7 +18,7 @@ # segment. After linking, the segments are split apart using objcopy into # separate libraries. The main library is then packaged with the application # as usual, while feature libraries may be packaged, delivered and loaded -# separately. +# separately (via an Android Dynamic Feature Module). # # When loading a feature library, the intended address of the library must be # supplied to the loader, so that it can be mapped to the memory location. The @@ -27,18 +28,15 @@ # The template instantiates targets for the base library, as well as each # specified partition, based on the root target name. Example: # -# - monochrome (base library) -# - monochrome_foo (partition library for feature 'foo') -# - monochrome_bar (partition library for feature 'bar') +# - libmonochrome (base library) +# - libmonochrome_foo (partition library for feature 'foo') +# - libmonochrome_bar (partition library for feature 'bar') # -# The base library is placed in the root output directory, but additional -# feature libraries are placed in a subdirectory named according to the base -# library. This avoids name collisions, since feature library names are not -# sensitive to the base library to which they are paired. Example: -# -# - out/libmonochrome.so -# - out/monochrome_partitions/libfoo.so -# - out/monochrome_partitions/libbar.so +# Note that the feature library filenames are chosen based on the main +# library's name (eg. libmonochrome_foo.so), but the soname of the feature +# library is based on the feature name (eg. "foo"). This should generally be +# okay, with the caveat that loading the library multiple times *might* cause +# problems in Android. # # This template uses shared_library's default configurations. # @@ -101,7 +99,7 @@ if (defined(invoker.partition) && invoker.partition != "") { args += [ "--partition", - "lib${invoker.partition}.so", + "${invoker.partition}", ] } args += [ rebase_path(sources[0], root_build_dir) ] @@ -129,10 +127,10 @@ # same directory. foreach(_partition, invoker.partitions) { partition_action("${target_name}_${_partition}") { - partition = _partition - _partition_dir = "$root_out_dir/${invoker.target_name}_partitions" - unstripped_output = "$_partition_dir/lib.unstripped/lib${partition}.so" - stripped_output = "$_partition_dir/lib${partition}.so" + partition = "${_partition}_partition" + stripped_output = "$root_out_dir/lib${_output_name}_${partition}.so" + unstripped_output = + "$root_out_dir/lib.unstripped/lib${_output_name}_${partition}.so" } } }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 27f8d4c..e1b5bda7 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -823,6 +823,7 @@ "//chrome/browser/ui/android/widget:java", "//chrome/browser/ui/android/widget:test_support_java", "//chrome/browser/util:java", + "//chrome/lib/lifecycle/public/android:java", "//chrome/test/android:chrome_java_test_support", "//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java", "//components/autofill/android:autofill_java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 7df0589..760f01a2 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -47,7 +47,12 @@ "javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java", "javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java", + "javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterRenderTest.java", + "javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java", + "javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuDelegate.java", + "javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuPropertiesDelegate.java", + "javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuObserver.java", "javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java", @@ -92,6 +97,7 @@ "javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java", "javatests/src/org/chromium/chrome/browser/directactions/FakeDirectActionReporter.java", "javatests/src/org/chromium/chrome/browser/directactions/MenuDirectActionHandlerTest.java", + "javatests/src/org/chromium/chrome/browser/contacts_picker/ContactDetailsTest.java", "javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index e0df1c9..8133889 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -415,7 +415,10 @@ mSecondaryTasksSurfacePropertyModel.set(IS_INCOGNITO, mIsIncognito); } - notifyStateChange(); + // TODO(crbug.com/1021399): This looks not needed since there is no way to change incognito + // mode when focusing on the omnibox and incognito mode change won't affect the visibility + // of the tab switcher toolbar. + if (mPropertyModel.get(IS_SHOWING_OVERVIEW)) notifyStateChange(); } private void setSecondaryTasksSurfaceVisibility(boolean isVisible) { @@ -436,6 +439,7 @@ private void notifyStateChange() { assert mSurfaceMode != SurfaceMode.NO_START_SURFACE; + assert mPropertyModel.get(IS_SHOWING_OVERVIEW); if (mStateObserver != null) { mStateObserver.onStateChanged(shouldShowTabSwitcherToolbar());
diff --git a/chrome/android/java/res/color/checkbox_tint.xml b/chrome/android/java/res/color/checkbox_tint.xml index e21a830..26def180 100644 --- a/chrome/android/java/res/color/checkbox_tint.xml +++ b/chrome/android/java/res/color/checkbox_tint.xml
@@ -3,6 +3,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> +<!-- TODO(twellington): Add an item for disabled state. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:color="@color/light_active_color" /> <item android:color="@color/control_normal_color"/>
diff --git a/chrome/android/java/res/layout/contacts_list_item_view.xml b/chrome/android/java/res/layout/contacts_list_item_view.xml index 00c8976..c613b059 100644 --- a/chrome/android/java/res/layout/contacts_list_item_view.xml +++ b/chrome/android/java/res/layout/contacts_list_item_view.xml
@@ -74,4 +74,11 @@ </LinearLayout> </LinearLayout> + <ImageView + android:id="@+id/star" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_marginEnd="20dp" + android:src="@drawable/btn_star_filled" + android:visibility="gone" /> </merge>
diff --git a/chrome/android/java/res/layout/title_button_menu_item.xml b/chrome/android/java/res/layout/title_button_menu_item.xml index d2c2fb4..ffe6588 100644 --- a/chrome/android/java/res/layout/title_button_menu_item.xml +++ b/chrome/android/java/res/layout/title_button_menu_item.xml
@@ -40,6 +40,9 @@ android:src="?android:attr/listChoiceIndicatorMultiple" /> <!-- Displays an icon. --> + <!-- TODO(twellington): Consider setting a default tint that adjusts when the item is disabled. + currently there are no menu items with icons that are visible but disabled so this behavior + is currently unused. --> <org.chromium.ui.widget.ChromeImageButton android:id="@+id/button" android:layout_width="56dp"
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index a0d9010e..63383521 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -509,6 +509,9 @@ <dimen name="circular_monogram_size">20dp</dimen> <dimen name="circular_monogram_text_size">14dp</dimen> + <!-- Contact Picker dimensions --> + <dimen name="contact_picker_icon_size">36dp</dimen> + <!-- Photo Picker dimensions --> <dimen name="photo_picker_selected_padding">12dp</dimen> <dimen name="photo_picker_label_gap">10dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java index a8f68ac5..6c07bbe4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
@@ -37,6 +37,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.base.SysUtils; +import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ui.widget.highlight.ViewHighlighter; @@ -297,14 +298,6 @@ } } - /** - * @return The footer view for the menu or null if one has not been set. - */ - @Nullable - public View getFooterView() { - return mFooterView; - } - private int[] getPopupPosition(int screenRotation, Rect appRect, Rect padding, View anchorView, int popupWidth, int popupHeight, boolean isAnchorAtBottom) { anchorView.getLocationInWindow(mTempLocation); @@ -568,4 +561,9 @@ return headerView.getMeasuredHeight(); } + + @VisibleForTesting + void finishAnimationsForTests() { + if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.end(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java index a7b00eb..d0e39c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -245,6 +245,7 @@ holder.title.setEnabled(titleItem.isEnabled()); holder.title.setFocusable(titleItem.isEnabled()); holder.title.setOnClickListener(v -> mOnClickHandler.onItemClick(titleItem)); + if (TextUtils.isEmpty(titleItem.getTitleCondensed())) { holder.title.setContentDescription(null); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorFactory.java index b76b874a..2489404 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorFactory.java
@@ -25,11 +25,14 @@ * @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity. * @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing * activity. + * @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is + * displayed using a hardware butt */ public static AppMenuCoordinator createAppMenuCoordinator(Context context, ActivityLifecycleDispatcher activityLifecycleDispatcher, - MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView) { - return new AppMenuCoordinatorImpl( - context, activityLifecycleDispatcher, buttonDelegate, appMenuDelegate, decorView); + MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView, + View hardwareButtonAnchorView) { + return new AppMenuCoordinatorImpl(context, activityLifecycleDispatcher, buttonDelegate, + appMenuDelegate, decorView, hardwareButtonAnchorView); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java index 981827b3..d7166162 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuCoordinatorImpl.java
@@ -8,7 +8,6 @@ import android.view.View; import android.view.ViewConfiguration; - import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -51,10 +50,13 @@ * @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity. * @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing * activity. + * @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is + * displayed using a hardware button. */ public AppMenuCoordinatorImpl(Context context, ActivityLifecycleDispatcher activityLifecycleDispatcher, - MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView) { + MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView, + View hardwareButtonAnchorView) { mContext = context; mButtonDelegate = buttonDelegate; mAppMenuDelegate = appMenuDelegate; @@ -62,7 +64,7 @@ mAppMenuHandler = new AppMenuHandlerImpl(mAppMenuPropertiesDelegate, mAppMenuDelegate, mAppMenuPropertiesDelegate.getAppMenuLayoutId(), decorView, - activityLifecycleDispatcher); + activityLifecycleDispatcher, hardwareButtonAnchorView); } @Override @@ -106,7 +108,7 @@ // Testing methods @VisibleForTesting - public AppMenuHandlerImpl getAppMenuHandlerImplForTesting() { + AppMenuHandlerImpl getAppMenuHandlerImplForTesting() { return mAppMenuHandler; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java index 4416470..771e804 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuHandlerImpl.java
@@ -73,17 +73,20 @@ * activity. * @param activityLifecycleDispatcher The {@link ActivityLifecycleDispatcher} for the containing * activity. + * @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is + * displayed using a hardware button. */ public AppMenuHandlerImpl(AppMenuPropertiesDelegate delegate, AppMenuDelegate appMenuDelegate, int menuResourceId, View decorView, - ActivityLifecycleDispatcher activityLifecycleDispatcher) { + ActivityLifecycleDispatcher activityLifecycleDispatcher, + View hardwareButtonAnchorView) { mAppMenuDelegate = appMenuDelegate; mDelegate = delegate; mDecorView = decorView; mBlockers = new ArrayList<>(); mObservers = new ArrayList<>(); mMenuResourceId = menuResourceId; - mHardwareButtonMenuAnchor = mDecorView.findViewById(R.id.menu_anchor_stub); + mHardwareButtonMenuAnchor = hardwareButtonAnchorView; mActivityLifecycleDispatcher = activityLifecycleDispatcher; mActivityLifecycleDispatcher.register(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java index 2471828f..eea641d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorder.java
@@ -9,7 +9,7 @@ import org.chromium.base.StrictModeContext; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import javax.inject.Inject; @@ -19,13 +19,12 @@ * Record the results of showing a clear data dialog on TWA client uninstall or data clear. */ public class ClearDataDialogResultRecorder { - private final Lazy<ChromePreferenceManager> mPrefsManager; + private final Lazy<SharedPreferencesManager> mPrefsManager; private final ChromeBrowserInitializer mBrowserInitializer; private final TrustedWebActivityUmaRecorder mUmaRecorder; @Inject - public ClearDataDialogResultRecorder( - Lazy<ChromePreferenceManager> manager, + public ClearDataDialogResultRecorder(Lazy<SharedPreferencesManager> manager, ChromeBrowserInitializer browserInitializer, TrustedWebActivityUmaRecorder umaRecorder) { mPrefsManager = manager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactDetails.java index b2938c6..edad68f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactDetails.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactDetails.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.contacts_picker; import android.content.res.Resources; +import android.graphics.drawable.Drawable; import androidx.annotation.Nullable; @@ -19,6 +20,10 @@ * A class to keep track of the metadata associated with a contact. */ public class ContactDetails implements Comparable<ContactDetails> { + // The identifier for the information from the signed in user. Must not be a valid id in the + // context of the Android Contacts list. + public static final String SELF_CONTACT_ID = "-1"; + /** * A container class for delivering contact details in abbreviated form * (where only the first email and phone numbers are returned and the rest @@ -46,6 +51,14 @@ // The list of addresses registered for this contact. private final List<PaymentAddress> mAddresses; + // Keeps track of whether this is the contact detail for the owner of the device. + private boolean mIsSelf; + + // The avatar icon for the owner of the device. Non-null only if the ContactDetails representing + // the owner were synthesized (not when a pre-existing contact tile was moved to the top). + @Nullable + private Drawable mSelfIcon; + /** * The ContactDetails constructor. * @param id The unique identifier of this contact. @@ -89,6 +102,37 @@ } /** + * Marks whether object is representing the owner of the device. + * @param value True if this is the contact details for the owner. False otherwise. + */ + public void setIsSelf(boolean value) { + mIsSelf = value; + } + + /** + * Returns true if this contact detail is representing the owner of the device. + */ + public boolean isSelf() { + return mIsSelf; + } + + /** + * Sets the icon representing the owner of the device. + */ + public void setSelfIcon(Drawable icon) { + mSelfIcon = icon; + } + + /** + * Fetch the cached icon for this contact. Returns null if this is not the 'self' contact, all + * other contact avatars should be retrieved through the {@link FetchIconWorkerTask}. + */ + @Nullable + public Drawable getSelfIcon() { + return mSelfIcon; + } + + /** * Accessor for the abbreviated display name (first letter of first name and first letter of * last name). * @return The display name, abbreviated to two characters.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactView.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactView.java index 9a95eafb..b901f393 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactView.java
@@ -13,6 +13,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import android.widget.ImageView; import android.widget.TextView; import org.chromium.chrome.R; @@ -49,6 +50,9 @@ private TextView mPhoneNumber; private TextView mPhoneNumberOverflowCount; + // The UI that indicates this is the owner of the device. + private ImageView mStar; + // The dialog manager to use to show contact details. private ModalDialogManager mManager; @@ -74,6 +78,7 @@ mEmailOverflowCount = findViewById(R.id.email_overflow_count); mPhoneNumber = findViewById(R.id.telephone_number); mPhoneNumberOverflowCount = findViewById(R.id.telephone_number_overflow_count); + mStar = findViewById(R.id.star); mEmailOverflowCount.setOnClickListener(this); mPhoneNumberOverflowCount.setOnClickListener(this); @@ -181,6 +186,8 @@ updateTextViewVisibilityAndContent( mPhoneNumberOverflowCount, details.overflowTelephoneNumberCount); + if (contactDetails.isSelf()) mStar.setVisibility(View.VISIBLE); + if (icon == null) { icon = mCategoryView.getIconGenerator().generateIconForText( contactDetails.getDisplayNameAbbreviation()); @@ -212,5 +219,6 @@ mEmailOverflowCount.setText(""); mPhoneNumber.setText(""); mPhoneNumberOverflowCount.setText(""); + mStar.setVisibility(View.GONE); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactViewHolder.java index dab7e2c..11058d95 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactViewHolder.java
@@ -6,6 +6,8 @@ import android.content.ContentResolver; import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.support.v7.widget.RecyclerView.ViewHolder; import org.chromium.base.VisibleForTesting; @@ -61,12 +63,19 @@ return; } - Bitmap icon = mCategoryView.getIconCache().getBitmap(mContact.getId()); - if (icon == null) { - mWorkerTask = new FetchIconWorkerTask(mContact.getId(), mContentResolver, this); - mWorkerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + Drawable drawable = contact.getSelfIcon(); + if (drawable != null) { + assert drawable instanceof BitmapDrawable; + Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); + mItemView.initialize(contact, bitmap); + } else { + Bitmap icon = mCategoryView.getIconCache().getBitmap(mContact.getId()); + if (icon == null) { + mWorkerTask = new FetchIconWorkerTask(mContact.getId(), mContentResolver, this); + mWorkerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + mItemView.initialize(contact, icon); } - mItemView.initialize(contact, icon); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactsFetcherWorkerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactsFetcherWorkerTask.java index 4c659e99..e6f6ff0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactsFetcherWorkerTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/ContactsFetcherWorkerTask.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.contacts_picker; import android.content.ContentResolver; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; @@ -38,6 +39,9 @@ void contactsRetrieved(ArrayList<ContactDetails> contacts); } + // The current context to use. + private Context mContext; + // The content resolver to use for looking up contacts. private ContentResolver mContentResolver; @@ -58,17 +62,18 @@ /** * A ContactsFetcherWorkerTask constructor. - * @param contentResolver The ContentResolver to use to fetch the contacts data. + * @param context The Context to use. * @param callback The callback to use to communicate back the results. * @param includeNames Whether names were requested by the website. * @param includeEmails Whether to include emails in the data fetched. * @param includeTel Whether to include telephones in the data fetched. * @param includeAddresses Whether to include telephones in the data fetched. */ - public ContactsFetcherWorkerTask(ContentResolver contentResolver, - ContactsRetrievedCallback callback, boolean includeNames, boolean includeEmails, - boolean includeTel, boolean includeAddresses) { - mContentResolver = contentResolver; + public ContactsFetcherWorkerTask(Context context, ContactsRetrievedCallback callback, + boolean includeNames, boolean includeEmails, boolean includeTel, + boolean includeAddresses) { + mContext = context; + mContentResolver = context.getContentResolver(); mCallback = callback; mIncludeNames = includeNames; mIncludeEmails = includeEmails;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/FetchIconWorkerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/FetchIconWorkerTask.java index 6137892..7e31c68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/FetchIconWorkerTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/FetchIconWorkerTask.java
@@ -51,6 +51,8 @@ public FetchIconWorkerTask( String id, ContentResolver contentResolver, IconRetrievedCallback callback) { mContactId = id; + // Avatar icon for own info should not be obtained through the contacts list. + assert !id.equals(ContactDetails.SELF_CONTACT_ID); mContentResolver = contentResolver; mCallback = callback; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java index c53d65ac..fdfabbf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
@@ -4,30 +4,42 @@ package org.chromium.chrome.browser.contacts_picker; +import android.accounts.Account; +import android.annotation.SuppressLint; import android.content.ContentResolver; +import android.content.Context; +import android.graphics.drawable.Drawable; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.Adapter; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import org.chromium.base.VisibleForTesting; import org.chromium.base.task.AsyncTask; import org.chromium.chrome.R; +import org.chromium.chrome.browser.signin.DisplayableProfileData; +import org.chromium.chrome.browser.signin.ProfileDataCache; +import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.ChromeSigninController; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Locale; /** * A data adapter for the Contacts Picker. */ public class PickerAdapter extends Adapter<RecyclerView.ViewHolder> - implements ContactsFetcherWorkerTask.ContactsRetrievedCallback, - TopView.ChipToggledCallback { + implements ContactsFetcherWorkerTask.ContactsRetrievedCallback, TopView.ChipToggledCallback, + ProfileDataCache.Observer { /** * A ViewHolder for the top-most view in the RecyclerView. The view it contains has a * checkbox and some multi-line text that goes with it, so clicks on either text line @@ -70,6 +82,9 @@ int CONTACT_DETAILS = 1; } + // The current context to use. + private Context mContext; + // The category view to use to show the contacts. private PickerCategoryView mCategoryView; @@ -85,9 +100,22 @@ // The full list of all registered contacts on the device. private ArrayList<ContactDetails> mContactDetails; + // The email address of the owner of the device. + @Nullable + private String mOwnerEmail; + // The async worker task to use for fetching the contact details. private ContactsFetcherWorkerTask mWorkerTask; + // The profile data cache to consult when figuring out the signed in user. + private ProfileDataCache mProfileDataCache; + + // Whether an observer for ProfileDataCache has been registered. + private boolean mObserving; + + // Whether owner info is being fetched asynchronously. + private boolean mWaitingOnOwnerInfo; + // Whether the user has switched to search mode. private boolean mSearchMode; @@ -106,29 +134,33 @@ // A list of contacts to use for testing (instead of querying Android). private static ArrayList<ContactDetails> sTestContacts; + // An owner email to use when testing. + private static String sTestOwnerEmail; + /** * The PickerAdapter constructor. * @param categoryView The category view to use to show the contacts. - * @param contentResolver The content resolver to use to fetch the data. + * @param context The current context. * @param formattedOrigin The origin the data will be shared with. */ - public PickerAdapter(PickerCategoryView categoryView, ContentResolver contentResolver, - String formattedOrigin) { + public PickerAdapter(PickerCategoryView categoryView, Context context, String formattedOrigin) { + mContext = context; mCategoryView = categoryView; - mContentResolver = contentResolver; + mContentResolver = context.getContentResolver(); mFormattedOrigin = formattedOrigin; sIncludeNames = true; sIncludeEmails = true; sIncludeTelephones = true; + mProfileDataCache = new ProfileDataCache(context, + mContext.getResources().getDimensionPixelSize(R.dimen.contact_picker_icon_size)); if (getAllContacts() == null && sTestContacts == null) { - mWorkerTask = new ContactsFetcherWorkerTask(mContentResolver, this, - mCategoryView.includeNames, mCategoryView.includeEmails, - mCategoryView.includeTel, mCategoryView.includeAddresses); + mWorkerTask = new ContactsFetcherWorkerTask(context, this, mCategoryView.includeNames, + mCategoryView.includeEmails, mCategoryView.includeTel, + mCategoryView.includeAddresses); mWorkerTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { - mContactDetails = sTestContacts; - notifyDataSetChanged(); + contactsRetrieved(sTestContacts); } } @@ -175,13 +207,55 @@ return mContactDetails; } + // Adapter: + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + addProfileDataObserver(); + } + + @Override + public void onDetachedFromRecyclerView(RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + removeProfileDataObserver(); + } + // ContactsFetcherWorkerTask.ContactsRetrievedCallback: @Override public void contactsRetrieved(ArrayList<ContactDetails> contacts) { mContactDetails = contacts; - if (mTopView != null) mTopView.updateContactCount(mContactDetails.size()); - notifyDataSetChanged(); + mOwnerEmail = getOwnerEmail(); + if (!processOwnerInfo(contacts) && mOwnerEmail != null) { + // Processing was not complete, finish the rest asynchronously. Flow continues in + // onProfileDataUpdated. + mWaitingOnOwnerInfo = true; + addProfileDataObserver(); + mProfileDataCache.update(Collections.singletonList(mOwnerEmail)); + mContactDetails.add(0, constructOwnerInfo(mOwnerEmail)); + } + update(); + } + + // ProfileDataCache.Observer + + @Override + public void onProfileDataUpdated(String accountId) { + if (!mWaitingOnOwnerInfo || !TextUtils.equals(accountId, mOwnerEmail)) { + return; + } + + // Now that we've received an update for the right accountId, we can stop listening and + // update our records. + mWaitingOnOwnerInfo = false; + removeProfileDataObserver(); + // TODO(finnur): crbug.com/1021477 - Maintain an member instance of this. + DisplayableProfileData profileData = mProfileDataCache.getProfileDataOrDefault(mOwnerEmail); + ContactDetails contact = mContactDetails.get(0); + Drawable icon = profileData.getImage(); + contact.setSelfIcon(icon); + update(); } // RecyclerView.Adapter: @@ -294,9 +368,120 @@ return sIncludeTelephones; } - /** Sets a list of contacts to use as data for the dialog. For testing use only. */ + /** + * Sets a list of contacts to use as data for the dialog, and the owner email. For testing use + * only. + */ @VisibleForTesting - public static void setTestContacts(ArrayList<ContactDetails> contacts) { + public static void setTestContactsAndOwner( + ArrayList<ContactDetails> contacts, String ownerEmail) { sTestContacts = contacts; + sTestOwnerEmail = ownerEmail; + } + + private void addProfileDataObserver() { + if (!mObserving) { + mObserving = true; + mProfileDataCache.addObserver(this); + } + } + + private void removeProfileDataObserver() { + if (mObserving) { + mObserving = false; + mProfileDataCache.removeObserver(this); + } + } + + private void update() { + if (mTopView != null) mTopView.updateContactCount(mContactDetails.size()); + notifyDataSetChanged(); + } + + /** + * Returns the email for the currently signed-in user. If that is not available, return the + * first Google account associated with this phone instead. + */ + private String getOwnerEmail() { + if (sTestOwnerEmail != null) return sTestOwnerEmail; + + ChromeSigninController controller = ChromeSigninController.get(); + Account account = controller.getSignedInUser(); + if (account != null) { + return account.name; + } + + AccountManagerFacade manager = AccountManagerFacade.get(); + List<Account> accounts = manager.tryGetGoogleAccounts(); + if (accounts.size() > 0) { + return accounts.get(0).name; + } + + return null; + } + + /** + * Attempts to figure out if the owner of the device is listed in the available contact details. + * If so move it to the top of the list. If not found, returns false. + * @return Returns true if processing is complete, false if waiting on asynchronous fetching of + * missing data for the owner info. + */ + private boolean processOwnerInfo(ArrayList<ContactDetails> contacts) { + if (mOwnerEmail == null) { + return true; + } + + ArrayList<Integer> matches = new ArrayList<Integer>(); + for (int i = 0; i < contacts.size(); ++i) { + List<String> emails = contacts.get(i).getEmails(); + for (int y = 0; y < emails.size(); ++y) { + if (TextUtils.equals(emails.get(y), mOwnerEmail)) { + matches.add(i); + break; + } + } + } + + if (matches.size() == 0) { + // No match was found, return false so that a record can be synthesized. + return false; + } + + // Move the contacts that match owner email to the top of the list. + for (int i = 0; i < matches.size(); ++i) { + int match = matches.get(i); + ContactDetails contact = contacts.get(match); + contact.setIsSelf(true); + contacts.remove(match); + contacts.add(i, contact); + } + return true; + } + + /** + * Constructs a {@link ContactDetails} record for the currently signed in user. Name is obtained + * via the {@link DisplayableProfileData}, if available, or (alternatively) using the signed in + * information. Telephone number is obtained via the telephony service, if that permission has + * already been granted, otherwise left blank. + * @param ownerEmail The email for the currently signed in user. + * @return The contact info for the currently signed in user. + */ + @SuppressLint("HardwareIds") + private ContactDetails constructOwnerInfo(String ownerEmail) { + DisplayableProfileData profileData = mProfileDataCache.getProfileDataOrDefault(ownerEmail); + String name = profileData.getFullNameOrEmail(); + if (TextUtils.isEmpty(name) || TextUtils.equals(name, ownerEmail)) { + ChromeSigninController controller = ChromeSigninController.get(); + name = controller.getSignedInAccountName(); + } + + ArrayList<String> telephones = new ArrayList<>(); + + ContactDetails contact = new ContactDetails(ContactDetails.SELF_CONTACT_ID, name, + Collections.singletonList(ownerEmail), telephones, /*addresses=*/null); + Drawable icon = profileData.getImage(); + contact.setIsSelf(true); + contact.setSelfIcon(icon); + return contact; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java index 7b48fc6..eaf54f49 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerCategoryView.java
@@ -151,7 +151,7 @@ R.string.contacts_picker_no_contacts_found, R.string.contacts_picker_no_contacts_found); - mPickerAdapter = new PickerAdapter(this, context.getContentResolver(), formattedOrigin); + mPickerAdapter = new PickerAdapter(this, context, formattedOrigin); mRecyclerView = mSelectableListLayout.initializeRecyclerView(mPickerAdapter); int titleId = multiSelectionAllowed ? R.string.contacts_picker_select_contacts : R.string.contacts_picker_select_contact;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index 024e2cb..a72e321a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.PrefServiceBridge; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.util.UrlConstants; import java.net.URL; @@ -43,7 +44,7 @@ private static final HashSet<String> PREDOMINENTLY_ENGLISH_SPEAKING_COUNTRIES = CollectionUtil.newHashSet("GB", "US"); - private final ChromePreferenceManager mPreferenceManager; + private final SharedPreferencesManager mPreferencesManager; private final ContextualSearchSelectionController mSelectionController; private ContextualSearchNetworkCommunicator mNetworkCommunicator; private ContextualSearchPanel mSearchPanel; @@ -58,7 +59,7 @@ */ public ContextualSearchPolicy(ContextualSearchSelectionController selectionController, ContextualSearchNetworkCommunicator networkCommunicator) { - mPreferenceManager = ChromePreferenceManager.getInstance(); + mPreferencesManager = SharedPreferencesManager.getInstance(); mSelectionController = selectionController; mNetworkCommunicator = networkCommunicator; @@ -104,7 +105,7 @@ * @return the {@link DisableablePromoTapCounter}. */ DisableablePromoTapCounter getPromoTapCounter() { - return DisableablePromoTapCounter.getInstance(mPreferenceManager); + return DisableablePromoTapCounter.getInstance(mPreferencesManager); } /** @@ -195,14 +196,14 @@ // Bump the counter only when it is still enabled. if (promoTapCounter.isEnabled()) promoTapCounter.increment(); } - int tapsSinceOpen = mPreferenceManager.incrementInt( + int tapsSinceOpen = mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_COUNT); if (isUserUndecided()) { ContextualSearchUma.logTapsSinceOpenForUndecided(tapsSinceOpen); } else { ContextualSearchUma.logTapsSinceOpenForDecided(tapsSinceOpen); } - mPreferenceManager.incrementInt( + mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_ALL_TIME_TAP_COUNT); } @@ -211,9 +212,9 @@ */ void updateCountersForOpen() { // Always completely reset the tap counters that accumulate only since the last open. - mPreferenceManager.writeInt( + mPreferencesManager.writeInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_COUNT, 0); - mPreferenceManager.writeInt( + mPreferencesManager.writeInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_QUICK_ANSWER_COUNT, 0); // Disable the "promo tap" counter, but only if we're using the Opt-out onboarding. @@ -222,11 +223,11 @@ getPromoTapCounter().disable(); // Bump the total-promo-opens counter. - int count = mPreferenceManager.incrementInt( + int count = mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_PROMO_OPEN_COUNT); ContextualSearchUma.logPromoOpenCount(count); } - mPreferenceManager.incrementInt( + mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_ALL_TIME_OPEN_COUNT); } @@ -238,9 +239,9 @@ */ void updateCountersForQuickAnswer(boolean wasActivatedByTap, boolean doesAnswer) { if (wasActivatedByTap && doesAnswer) { - mPreferenceManager.incrementInt( + mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_QUICK_ANSWER_COUNT); - mPreferenceManager.incrementInt( + mPreferencesManager.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_ALL_TIME_TAP_QUICK_ANSWER_COUNT); } } @@ -341,10 +342,12 @@ int selectionType = mSelectionController.getSelectionType(); if (selectionType == SelectionType.TAP) { long currentTimeMillis = System.currentTimeMillis(); - long lastAnimatedTimeMillis = - mPreferenceManager.getContextualSearchLastAnimationTime(); + long lastAnimatedTimeMillis = mPreferencesManager.readLong( + ChromePreferenceManager.CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME); if (Math.abs(currentTimeMillis - lastAnimatedTimeMillis) > DateUtils.DAY_IN_MILLIS) { - mPreferenceManager.setContextualSearchLastAnimationTime(currentTimeMillis); + mPreferencesManager.writeLong( + ChromePreferenceManager.CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME, + currentTimeMillis); return true; } else { return false; @@ -388,7 +391,7 @@ */ @VisibleForTesting int getPromoOpenCount() { - return mPreferenceManager.readInt( + return mPreferencesManager.readInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_PROMO_OPEN_COUNT); } @@ -397,7 +400,7 @@ */ @VisibleForTesting int getTapCount() { - return mPreferenceManager.readInt( + return mPreferencesManager.readInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_SINCE_OPEN_COUNT); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java index 4abe168..b866b4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/CtrSuppression.java
@@ -7,6 +7,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; /** * Provides a ContextualSearchHeuristic for CTR Recording, logging, and eventually suppression. @@ -23,14 +24,14 @@ private static Integer sCurrentWeekNumberCache; - private final ChromePreferenceManager mPreferenceManager; + private final SharedPreferencesManager mPreferenceManager; /** * Constructs an object that tracks impressions and clicks per user to produce CTR and * impression metrics. */ CtrSuppression() { - mPreferenceManager = ChromePreferenceManager.getInstance(); + mPreferenceManager = SharedPreferencesManager.getInstance(); // This needs to be done last in this constructor because the native code may call // into this object. @@ -148,10 +149,14 @@ * or we have never checked. */ private boolean didWeekChange(int currentWeekNumber) { - if (mPreferenceManager.getContextualSearchCurrentWeekNumber() == currentWeekNumber) { + if (mPreferenceManager.readInt( + ChromePreferenceManager.CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER) + == currentWeekNumber) { return false; } else { - mPreferenceManager.setContextualSearchCurrentWeekNumber(currentWeekNumber); + mPreferenceManager.writeInt( + ChromePreferenceManager.CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER, + currentWeekNumber); return true; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java index dc91d6e..bcb7c45 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java
@@ -6,6 +6,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; /** * Manages the Contextual Search disable-able promo tap counter. @@ -29,7 +30,7 @@ private static DisableablePromoTapCounter sInstance; - private final ChromePreferenceManager mPrefsManager; + private final SharedPreferencesManager mPrefsManager; private int mCounter; /** @@ -37,8 +38,7 @@ * @param prefsManager The ChromePreferenceManager to get prefs from. * @return the counter. */ - static DisableablePromoTapCounter getInstance( - ChromePreferenceManager prefsManager) { + static DisableablePromoTapCounter getInstance(SharedPreferencesManager prefsManager) { if (sInstance == null) { sInstance = new DisableablePromoTapCounter(prefsManager); } @@ -49,9 +49,10 @@ * Private constructor -- use {@link #getInstance} to get the singleton instance. * @param prefsManager The preferences manager to use. */ - private DisableablePromoTapCounter(ChromePreferenceManager prefsManager) { + private DisableablePromoTapCounter(SharedPreferencesManager prefsManager) { mPrefsManager = prefsManager; - setRawCounter(prefsManager.getContextualSearchTapTriggeredPromoCount()); + setRawCounter(prefsManager.readInt( + ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT)); } /** @@ -106,7 +107,8 @@ * Writes the current counter's raw value to persistent storage. */ private void writeRawCounter() { - mPrefsManager.setContextualSearchTapTriggeredPromoCount(mCounter); + mPrefsManager.writeInt( + ChromePreferenceManager.CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT, mCounter); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java index 5f03a106..297c2e62 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java
@@ -6,12 +6,13 @@ import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; /** * Provides a ContextualSearchHeuristic for Engagement with the feature. */ public class EngagementSuppression extends ContextualSearchHeuristic { - private final ChromePreferenceManager mPreferenceManager; + private final SharedPreferencesManager mPreferenceManager; private final boolean mIsConditionSatisfied; private final boolean mIsEnabled; @@ -19,7 +20,7 @@ * Constructs an object that tracks panel opens and other measures of engagement. */ EngagementSuppression() { - mPreferenceManager = ChromePreferenceManager.getInstance(); + mPreferenceManager = SharedPreferencesManager.getInstance(); mIsEnabled = ContextualSearchFieldTrial.getSwitch( ContextualSearchSwitch.IS_ENGAGEMENT_SUPPRESSION_ENABLED); // Used for manual testing; suppress when we've had an entity impression but no open, @@ -56,7 +57,7 @@ */ public static void registerQuickActionImpression( boolean wasPanelOpened, boolean wasActionClicked) { - ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(); + SharedPreferencesManager prefs = SharedPreferencesManager.getInstance(); prefs.incrementInt( ChromePreferenceManager.CONTEXTUAL_SEARCH_QUICK_ACTION_IMPRESSIONS_COUNT); if (wasActionClicked) { @@ -73,7 +74,7 @@ * @param wasPanelOpened Whether the panel was opened. */ public static void registerContextualCardsImpression(boolean wasPanelOpened) { - ChromePreferenceManager prefs = ChromePreferenceManager.getInstance(); + SharedPreferencesManager prefs = SharedPreferencesManager.getInstance(); prefs.incrementInt(ChromePreferenceManager.CONTEXTUAL_SEARCH_ENTITY_IMPRESSIONS_COUNT); if (wasPanelOpened) { prefs.incrementInt(ChromePreferenceManager.CONTEXTUAL_SEARCH_ENTITY_OPENS_COUNT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java index ce38dd5c..a94c2bc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
@@ -25,7 +25,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.infobar.InfoBarContainer; -import org.chromium.chrome.browser.rappor.RapporServiceBridge; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabObserver; @@ -51,7 +50,6 @@ private static final String TAG = "VideoPersist"; // Metrics - private static final String METRICS_URL = "Media.VideoPersistence.TopFrame"; private static final String METRICS_DURATION = "Media.VideoPersistence.Duration"; private static final String METRICS_ATTEMPT_RESULT = "Media.VideoPersistence.AttemptResult"; @@ -211,8 +209,6 @@ // Setup observers to dismiss the Activity on events that should end PiP. final Tab activityTab = activity.getActivityTab(); - RapporServiceBridge.sampleDomainAndRegistryFromURL(METRICS_URL, activityTab.getUrl()); - final TabObserver tabObserver = new DismissActivityOnTabEventObserver(activity); final TabModelSelectorObserver tabModelSelectorObserver = new DismissActivityOnTabModelSelectorEventObserver(activity);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/RecordCastAction.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/RecordCastAction.java index 6787662..725eb47 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/RecordCastAction.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/RecordCastAction.java
@@ -10,7 +10,6 @@ import org.chromium.base.annotations.NativeMethods; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.browser.rappor.RapporServiceBridge; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -146,18 +145,6 @@ } /** - * Record the domain and registry of the URL of the frame where the user is casting the video - * from using Rappor. - * - * @param url The frame URL to record the domain and registry of. - */ - public static void castDomainAndRegistry(String url) { - if (LibraryLoader.getInstance().isInitialized()) { - RapporServiceBridge.sampleDomainAndRegistryFromURL("Cast.Sender.MediaFrameUrl", url); - } - } - - /** * Record the ratio of the time the media element was detached from the remote playback session * to the total duration of the session (as from when the element has been attached till when * the session stopped or disconnected), in percents.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java index 0b50706..efb7a631 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java
@@ -18,7 +18,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.ChromeBaseAppCompatActivity; import org.chromium.chrome.browser.flags.FeatureUtilities; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences; /** @@ -136,7 +136,7 @@ * @return The current theme setting. See {@link ThemePreferences.ThemeSetting}. */ public static @ThemePreferences.ThemeSetting int getThemeSetting() { - int userSetting = ChromePreferenceManager.getInstance().readInt(UI_THEME_SETTING_KEY, -1); + int userSetting = SharedPreferencesManager.getInstance().readInt(UI_THEME_SETTING_KEY, -1); if (userSetting == -1) { return FeatureUtilities.isNightModeDefaultToLight() ? ThemePreferences.ThemeSetting.LIGHT
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java index d02cae0e..7b1c4cb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -116,11 +116,12 @@ @Deprecated private static final String PREF_WEBSITE_SETTINGS_FILTER = "website_settings_filter"; - private static final String CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT = + + public static final String CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT = "contextual_search_tap_triggered_promo_count"; - private static final String CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME = + public static final String CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME = "contextual_search_last_animation_time"; - private static final String CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER = + public static final String CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER = "contextual_search_current_week_number"; /** @@ -392,54 +393,6 @@ } /** - * @return The last time the search provider icon was animated on tap. - */ - public long getContextualSearchLastAnimationTime() { - return mManager.readLong(CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME); - } - - /** - * Sets the last time the search provider icon was animated on tap. - * @param time The last time the search provider icon was animated on tap. - */ - public void setContextualSearchLastAnimationTime(long time) { - mManager.writeLong(CONTEXTUAL_SEARCH_LAST_ANIMATION_TIME, time); - } - - /** - * @return Number of times the promo was triggered to peek by a tap gesture, or a negative value - * if in the disabled state. - */ - public int getContextualSearchTapTriggeredPromoCount() { - return mManager.readInt(CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT); - } - - /** - * Sets the number of times the promo was triggered to peek by a tap gesture. - * Use a negative value to record that the counter has been disabled. - * @param count Number of times the promo was triggered by a tap gesture, or a negative value - * to record that the counter has been disabled. - */ - public void setContextualSearchTapTriggeredPromoCount(int count) { - mManager.writeInt(CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT, count); - } - - /** - * @return The current week number, persisted for weekly CTR recording. - */ - public int getContextualSearchCurrentWeekNumber() { - return mManager.readInt(CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER); - } - - /** - * Sets the current week number to persist. Used for weekly CTR recording. - * @param weekNumber The week number to store. - */ - public void setContextualSearchCurrentWeekNumber(int weekNumber) { - mManager.writeInt(CONTEXTUAL_SEARCH_CURRENT_WEEK_NUMBER, weekNumber); - } - - /** * Returns timestamp of the suppression period start if signin promos in the New Tab Page are * temporarily suppressed; zero otherwise. * @return the epoch time in milliseconds (see {@link System#currentTimeMillis()}). @@ -514,52 +467,6 @@ } /** - * Writes the given int value to the named shared preference. - * @param key The name of the preference to modify. - * @param value The new value for the preference. - * @deprecated Use {@link SharedPreferencesManager} instead. - */ - @Deprecated - public void writeInt(String key, int value) { - mManager.writeInt(key, value); - } - - /** - * Reads the given int value from the named shared preference, defaulting to 0 if not found. - * @param key The name of the preference to return. - * @return The value of the preference. - * @deprecated Use {@link SharedPreferencesManager} instead. - */ - @Deprecated - public int readInt(String key) { - return mManager.readInt(key); - } - - /** - * Reads the given int value from the named shared preference. - * @param key The name of the preference to return. - * @param defaultValue The default value to return if the preference is not set. - * @return The value of the preference. - * @deprecated Use {@link SharedPreferencesManager} instead. - */ - @Deprecated - public int readInt(String key, int defaultValue) { - return mManager.readInt(key, defaultValue); - } - - /** - * Increments the integer value specified by the given key. If no initial value is present then - * an initial value of 0 is assumed and incremented, so a new value of 1 is set. - * @param key The key specifying which integer value to increment. - * @return The newly incremented value. - * @deprecated Use {@link SharedPreferencesManager} instead. - */ - @Deprecated - public int incrementInt(String key) { - return mManager.incrementInt(key); - } - - /** * Writes the given boolean to the named shared preference. * * @param key The name of the preference to modify. @@ -583,15 +490,4 @@ public boolean readBoolean(String key, boolean defaultValue) { return mManager.readBoolean(key, defaultValue); } - - /** - * Removes the shared preference entry. - * - * @param key The key of the preference to remove. - * @deprecated Use {@link SharedPreferencesManager} instead. - */ - @Deprecated - public void removeKey(String key) { - mManager.removeKey(key); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java index c9612a2..21c1c60f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java
@@ -17,8 +17,8 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.night_mode.NightModeUtils; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.PreferenceUtils; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.ui.UiUtils; import java.lang.annotation.Retention; @@ -50,20 +50,20 @@ PreferenceUtils.addPreferencesFromResource(this, R.xml.theme_preferences); getActivity().setTitle(R.string.prefs_themes); - ChromePreferenceManager chromePreferenceManager = ChromePreferenceManager.getInstance(); + SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance(); RadioButtonGroupThemePreference radioButtonGroupThemePreference = (RadioButtonGroupThemePreference) findPreference(PREF_UI_THEME_PREF); radioButtonGroupThemePreference.initialize(NightModeUtils.getThemeSetting(), - chromePreferenceManager.readBoolean(DARKEN_WEBSITES_ENABLED_KEY, false)); + sharedPreferencesManager.readBoolean(DARKEN_WEBSITES_ENABLED_KEY, false)); radioButtonGroupThemePreference.setOnPreferenceChangeListener((preference, newValue) -> { if (ChromeFeatureList.isEnabled( ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING)) { - chromePreferenceManager.writeBoolean(DARKEN_WEBSITES_ENABLED_KEY, + sharedPreferencesManager.writeBoolean(DARKEN_WEBSITES_ENABLED_KEY, radioButtonGroupThemePreference.isDarkenWebsitesEnabled()); } int theme = (int) newValue; - chromePreferenceManager.writeInt(UI_THEME_SETTING_KEY, theme); + sharedPreferencesManager.writeInt(UI_THEME_SETTING_KEY, theme); return true; }); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinatorPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinatorPhone.java index 3c59e21..87331e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinatorPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinatorPhone.java
@@ -163,8 +163,9 @@ } void setTabSwitcherToolbarVisibility(boolean shouldShowTabSwitcherToolbar) { - if ((mTabSwitcherModeToolbar.getVisibility() == View.VISIBLE) - == shouldShowTabSwitcherToolbar) { + if (mTabSwitcherModeToolbar == null + || (mTabSwitcherModeToolbar.getVisibility() == View.VISIBLE) + == shouldShowTabSwitcherToolbar) { return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index 7a77ec1..47d714f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -279,7 +279,8 @@ if (mActivity.supportsAppMenu()) { mAppMenuCoordinator = AppMenuCoordinatorFactory.createAppMenuCoordinator(mActivity, mActivity.getLifecycleDispatcher(), mActivity.getToolbarManager(), mActivity, - mActivity.getWindow().getDecorView()); + mActivity.getWindow().getDecorView(), + mActivity.getWindow().getDecorView().findViewById(R.id.menu_anchor_stub)); mActivity.getToolbarManager().onAppMenuInitialized( mAppMenuCoordinator.getAppMenuHandler(), mAppMenuCoordinator.getAppMenuPropertiesDelegate());
diff --git a/chrome/android/javatests/DEPS b/chrome/android/javatests/DEPS index 8f9fe09..85ef730 100644 --- a/chrome/android/javatests/DEPS +++ b/chrome/android/javatests/DEPS
@@ -3,6 +3,7 @@ "+chrome/browser/ui/android/styles", "+chrome/browser/ui/android/widget", "+chrome/browser/util/android", + "+chrome/lib/lifecycle/public", "+components/autofill/android/java/src/org/chromium/components/autofill", "+components/background_task_scheduler/android/java", "+components/bookmarks/common/android/java/src/org/chromium/components/bookmarks",
diff --git a/chrome/android/javatests/res/drawable/test_ic_arrow_downward_black_24dp.xml b/chrome/android/javatests/res/drawable/test_ic_arrow_downward_black_24dp.xml new file mode 100644 index 0000000..598cee0 --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_arrow_downward_black_24dp.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z" + android:fillColor="#010101"/> +</vector>
diff --git a/chrome/android/javatests/res/drawable/test_ic_arrow_forward_black_24dp.xml b/chrome/android/javatests/res/drawable/test_ic_arrow_forward_black_24dp.xml new file mode 100644 index 0000000..8eb68b5a --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_arrow_forward_black_24dp.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/> +</vector>
diff --git a/chrome/android/javatests/res/drawable/test_ic_info_outline_black_24dp.xml b/chrome/android/javatests/res/drawable/test_ic_info_outline_black_24dp.xml new file mode 100644 index 0000000..434620e8 --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_info_outline_black_24dp.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/> +</vector>
diff --git a/chrome/android/javatests/res/drawable/test_ic_refresh_black_24dp.xml b/chrome/android/javatests/res/drawable/test_ic_refresh_black_24dp.xml new file mode 100644 index 0000000..e411381 --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_refresh_black_24dp.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/> +</vector>
diff --git a/chrome/android/javatests/res/drawable/test_ic_star_border_black_24dp.xml b/chrome/android/javatests/res/drawable/test_ic_star_border_black_24dp.xml new file mode 100644 index 0000000..a075fd16 --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_star_border_black_24dp.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/> +</vector>
diff --git a/chrome/android/javatests/res/drawable/test_ic_vintage_filter.xml b/chrome/android/javatests/res/drawable/test_ic_vintage_filter.xml new file mode 100644 index 0000000..b617083 --- /dev/null +++ b/chrome/android/javatests/res/drawable/test_ic_vintage_filter.xml
@@ -0,0 +1,15 @@ +<?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:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M18.7,12.4c-0.28,-0.16 -0.57,-0.29 -0.86,-0.4 0.29,-0.11 0.58,-0.24 0.86,-0.4 1.92,-1.11 2.99,-3.12 3,-5.19 -1.79,-1.03 -4.07,-1.11 -6,0 -0.28,0.16 -0.54,0.35 -0.78,0.54 0.05,-0.31 0.08,-0.63 0.08,-0.95 0,-2.22 -1.21,-4.15 -3,-5.19C10.21,1.85 9,3.78 9,6c0,0.32 0.03,0.64 0.08,0.95 -0.24,-0.2 -0.5,-0.39 -0.78,-0.55 -1.92,-1.11 -4.2,-1.03 -6,0 0,2.07 1.07,4.08 3,5.19 0.28,0.16 0.57,0.29 0.86,0.4 -0.29,0.11 -0.58,0.24 -0.86,0.4 -1.92,1.11 -2.99,3.12 -3,5.19 1.79,1.03 4.07,1.11 6,0 0.28,-0.16 0.54,-0.35 0.78,-0.54 -0.05,0.32 -0.08,0.64 -0.08,0.96 0,2.22 1.21,4.15 3,5.19 1.79,-1.04 3,-2.97 3,-5.19 0,-0.32 -0.03,-0.64 -0.08,-0.95 0.24,0.2 0.5,0.38 0.78,0.54 1.92,1.11 4.2,1.03 6,0 -0.01,-2.07 -1.08,-4.08 -3,-5.19zM12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"/> +</vector>
diff --git a/chrome/android/javatests/res/layout/test_menu_footer.xml b/chrome/android/javatests/res/layout/test_menu_footer.xml new file mode 100644 index 0000000..2cfd92ed2 --- /dev/null +++ b/chrome/android/javatests/res/layout/test_menu_footer.xml
@@ -0,0 +1,12 @@ +<?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. --> + +<TextView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:ignore="HardcodedText" + android:text="Menu Footer"/> \ No newline at end of file
diff --git a/chrome/android/javatests/res/layout/test_menu_header.xml b/chrome/android/javatests/res/layout/test_menu_header.xml new file mode 100644 index 0000000..25544dc --- /dev/null +++ b/chrome/android/javatests/res/layout/test_menu_header.xml
@@ -0,0 +1,12 @@ +<?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. --> + +<TextView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:ignore="HardcodedText" + android:text="Menu Header"/> \ No newline at end of file
diff --git a/chrome/android/javatests/res/menu/test_menu.xml b/chrome/android/javatests/res/menu/test_menu.xml new file mode 100644 index 0000000..8e98dd12 --- /dev/null +++ b/chrome/android/javatests/res/menu/test_menu.xml
@@ -0,0 +1,26 @@ +<?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. --> + +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:ignore="HardcodedText"> + <item android:id="@+id/menu_item_one" + android:title="Menu Item One" /> + <item android:id="@+id/menu_item_two" + android:title="Menu Item Two" /> + <item android:id="@+id/menu_item_three" + android:title="Menu Item Three" /> + <item android:id="@+id/icon_row_menu_id" + android:title="@null"> + <menu> + <item android:id="@+id/icon_one" + android:title="Icon One" /> + <item android:id="@+id/icon_two" + android:title="Icon Two" /> + <item android:id="@+id/icon_three" + android:title="Icon Three" /> + </menu> + </item> +</menu> \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterRenderTest.java new file mode 100644 index 0000000..2df071a --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterRenderTest.java
@@ -0,0 +1,214 @@ +// 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.appmenu; + +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_1; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_2; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_3; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_4; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_5; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildIconRow; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildMenuItem; +import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildTitleMenuItem; + +import android.graphics.drawable.Drawable; +import android.support.test.filters.MediumTest; +import android.support.v7.content.res.AppCompatResources; +import android.view.MenuItem; +import android.view.View; +import android.widget.FrameLayout; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; + +import org.chromium.base.test.params.ParameterAnnotations; +import org.chromium.base.test.params.ParameterProvider; +import org.chromium.base.test.params.ParameterSet; +import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.R; +import org.chromium.chrome.test.ui.DummyUiActivityTestCase; +import org.chromium.chrome.test.util.RenderTestRule; +import org.chromium.content_public.browser.test.util.TestThreadUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Render tests for {@link AppMenuAdapter}. + */ +@RunWith(ParameterizedRunner.class) +@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) +public class AppMenuAdapterRenderTest extends DummyUiActivityTestCase { + // TODO(twellington): Add night mode variant after NightModeTestUtils methods are modularized + // in https://crbug.com/1002287. + + /** + * Parameter set controlling whether the menu item being rendered is enabled. + */ + public static class EnabledParams implements ParameterProvider { + private static List<ParameterSet> sEnabledDisabledParams = + Arrays.asList(new ParameterSet().value(false).name("Enabled"), + new ParameterSet().value(true).name("Disabled")); + + @Override + public List<ParameterSet> getParameters() { + return sEnabledDisabledParams; + } + } + + @Rule + public RenderTestRule mRenderTestRule = + new RenderTestRule("chrome/test/data/android/render_tests"); + + @Override + public void setUpTest() throws Exception { + super.setUpTest(); + MockitoAnnotations.initMocks(this); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testStandardMenuItem(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + MenuItem item = buildMenuItem(1, TITLE_1, enabled); + mRenderTestRule.render(createView(item), "standard"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testStandardMenuItem_Icon(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + Drawable icon = + AppCompatResources.getDrawable(getActivity(), R.drawable.test_ic_vintage_filter); + MenuItem item = buildMenuItem(1, TITLE_1, enabled, icon); + mRenderTestRule.render(createView(item), "standard_with_icon"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testTitleButtonMenuItem_Icon(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + Drawable icon = + AppCompatResources.getDrawable(getActivity(), R.drawable.test_ic_vintage_filter); + MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, icon, false, false, enabled); + mRenderTestRule.render(createView(item), "title_button_icon"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testTitleButtonMenuItem_Checkbox_Checked(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, null, true, true, enabled); + mRenderTestRule.render(createView(item), "title_button_checkbox_checked"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testTitleButtonMenuItem_Checkbox_Unchecked(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, null, true, false, enabled); + mRenderTestRule.render(createView(item), "title_button_checkbox_unchecked"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(EnabledParams.class) + public void testIconRow_ThreeIcons(boolean enabled) throws IOException { + setRenderTestPrefix(enabled); + Drawable icon1 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_forward_black_24dp); + Drawable icon2 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_star_border_black_24dp); + Drawable icon3 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_downward_black_24dp); + MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 0, + "", null, 0, "", null, enabled); + + mRenderTestRule.render(createView(item), "iconrow_three_icons"); + } + + @Test + @MediumTest + @Feature("RenderTest") + public void testIconRow_FourIcons() throws IOException { + setRenderTestPrefix(true); + Drawable icon1 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_forward_black_24dp); + Drawable icon2 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_star_border_black_24dp); + Drawable icon3 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_downward_black_24dp); + Drawable icon4 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_info_outline_black_24dp); + MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 5, + TITLE_4, icon4, 0, "", null, true); + + mRenderTestRule.render(createView(item), "iconrow_four_icons"); + } + + @Test + @MediumTest + @Feature("RenderTest") + public void testIconRow_FiveIcons() throws IOException { + setRenderTestPrefix(true); + Drawable icon1 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_forward_black_24dp); + Drawable icon2 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_star_border_black_24dp); + Drawable icon3 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_arrow_downward_black_24dp); + Drawable icon4 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_info_outline_black_24dp); + Drawable icon5 = AppCompatResources.getDrawable( + getActivity(), R.drawable.test_ic_refresh_black_24dp); + MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 5, + TITLE_4, icon4, 6, TITLE_5, icon5, true); + + mRenderTestRule.render(createView(item), "iconrow_five_icons"); + } + + private void setRenderTestPrefix(boolean enabled) { + mRenderTestRule.setVariantPrefix(enabled ? "Enabled" : "Disabled"); + } + + private View createView(MenuItem item) { + List<MenuItem> items = new ArrayList<>(); + items.add(item); + AppMenuAdapter adapter = new AppMenuAdapter(new AppMenuAdapterTest.TestClickHandler(), + items, getActivity().getLayoutInflater(), 0, null); + + // Create a new FrameLayout to set as the main content view. + FrameLayout parentView = new FrameLayout(getActivity()); + parentView.setLayoutParams(new FrameLayout.LayoutParams( + getActivity().getResources().getDimensionPixelSize(R.dimen.menu_width), + FrameLayout.LayoutParams.WRAP_CONTENT)); + + // Create a view for the provided menu item and attach it to the content view. + TestThreadUtils.runOnUiThreadBlocking(() -> { + View view = adapter.getView(0, null, parentView); + parentView.addView(view); + getActivity().setContentView(parentView); + }); + + return parentView.getChildAt(0); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java index b53281b..c25f50b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java
@@ -4,8 +4,9 @@ package org.chromium.chrome.browser.appmenu; +import android.graphics.drawable.Drawable; import android.support.test.filters.MediumTest; -import android.support.test.rule.UiThreadTestRule; +import android.support.v7.content.res.AppCompatResources; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.SubMenu; @@ -16,7 +17,6 @@ import androidx.annotation.Nullable; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; @@ -26,17 +26,20 @@ import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ui.DummyUiActivityTestCase; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; /** * Tests for {@link AppMenuAdapter}. */ @RunWith(ChromeJUnit4ClassRunner.class) public class AppMenuAdapterTest extends DummyUiActivityTestCase { - private static class TestClickHandler implements AppMenuAdapter.OnClickHandler { + static class TestClickHandler implements AppMenuAdapter.OnClickHandler { public CallbackHelper onClickCallback = new CallbackHelper(); public MenuItem lastClickedItem; @@ -57,14 +60,11 @@ } } - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - private static final String TITLE_1 = "Menu Item One"; - private static final String TITLE_2 = "Menu Item Two"; - private static final String TITLE_3 = "Menu Item Three"; - private static final String TITLE_4 = "Menu Item Four"; - private static final String TITLE_5 = "Menu Item Five"; + static final String TITLE_1 = "Menu Item One"; + static final String TITLE_2 = "Menu Item Two"; + static final String TITLE_3 = "Menu Item Three"; + static final String TITLE_4 = "Menu Item Four"; + static final String TITLE_5 = "Menu Item Five"; private TestClickHandler mClickHandler; @@ -78,9 +78,10 @@ @Test @MediumTest - public void testStandardMenuItem() { + public void testStandardMenuItem() throws ExecutionException, TimeoutException { + int itemId = 1234; List<MenuItem> items = new ArrayList<>(); - items.add(buildMenuItem(0, TITLE_1)); + items.add(buildMenuItem(itemId, TITLE_1)); AppMenuAdapter adapter = new AppMenuAdapter( mClickHandler, items, getActivity().getLayoutInflater(), 0, null); @@ -92,14 +93,19 @@ TextView titleView1 = view1.findViewById(R.id.menu_item_text); Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView1.getText()); + + TestThreadUtils.runOnUiThreadBlocking(() -> view1.performClick()); + mClickHandler.onClickCallback.waitForCallback(0); + Assert.assertEquals( + "Incorrect clicked item id", itemId, mClickHandler.lastClickedItem.getItemId()); } @Test @MediumTest public void testConvertView_Reused_StandardMenuItem() { List<MenuItem> items = new ArrayList<>(); - items.add(buildMenuItem(0, TITLE_1)); - items.add(buildMenuItem(1, TITLE_2)); + items.add(buildMenuItem(1, TITLE_1)); + items.add(buildMenuItem(2, TITLE_2)); AppMenuAdapter adapter = new AppMenuAdapter( mClickHandler, items, getActivity().getLayoutInflater(), 0, null); @@ -111,16 +117,67 @@ Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText()); View view2 = adapter.getView(1, view1, parentView); - Assert.assertEquals("Convert view should have been re-used.", view1, view2); + Assert.assertEquals("Convert view should have been re-used", view1, view2); Assert.assertEquals("Title should have been updated", TITLE_2, titleView.getText()); } @Test @MediumTest + public void testConvertView_Reused_TitleMenuItem() { + List<MenuItem> items = new ArrayList<>(); + items.add(buildTitleMenuItem(1, 2, TITLE_1, 3, TITLE_2)); + items.add(buildTitleMenuItem(4, 5, TITLE_3, 6, TITLE_4)); + + AppMenuAdapter adapter = new AppMenuAdapter( + mClickHandler, items, getActivity().getLayoutInflater(), 0, null); + + Assert.assertEquals("Wrong item view type", AppMenuAdapter.MenuItemType.TITLE_BUTTON, + adapter.getItemViewType(0)); + + ViewGroup parentView = getActivity().findViewById(android.R.id.content); + View view1 = adapter.getView(0, null, parentView); + TextView titleView = view1.findViewById(R.id.title); + + Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText()); + + View view2 = adapter.getView(1, view1, parentView); + Assert.assertEquals("Convert view should have been re-used", view1, view2); + Assert.assertEquals("Title should have been updated", TITLE_3, titleView.getText()); + } + + @Test + @MediumTest + public void testConvertView_Reused_IconRow() { + Drawable icon = AppCompatResources.getDrawable( + getActivity(), org.chromium.chrome.test.R.drawable.test_ic_vintage_filter); + List<MenuItem> items = new ArrayList<>(); + items.add(buildIconRow(1, 2, TITLE_1, icon, 3, TITLE_2, icon, 4, "", icon, 0, null, null, 0, + null, null, true)); + items.add(buildIconRow(5, 6, TITLE_3, icon, 7, TITLE_4, icon, 8, "", icon, 0, null, null, 0, + null, null, true)); + + AppMenuAdapter adapter = new AppMenuAdapter( + mClickHandler, items, getActivity().getLayoutInflater(), 0, null); + + ViewGroup parentView = getActivity().findViewById(android.R.id.content); + View view1 = adapter.getView(0, null, parentView); + View buttonOne = view1.findViewById(R.id.button_one); + + Assert.assertEquals("Incorrect content description for item 1", TITLE_1, + buttonOne.getContentDescription()); + + View view2 = adapter.getView(1, view1, parentView); + Assert.assertEquals("Convert view should have been re-used", view1, view2); + Assert.assertEquals("Content description should have been updated", TITLE_3, + buttonOne.getContentDescription()); + } + + @Test + @MediumTest public void testConvertView_NotReused() { List<MenuItem> items = new ArrayList<>(); - items.add(buildMenuItem(0, TITLE_1)); - items.add(buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3)); + items.add(buildMenuItem(1, TITLE_1)); + items.add(buildTitleMenuItem(2, 3, TITLE_2, 4, TITLE_3)); AppMenuAdapter adapter = new AppMenuAdapter( mClickHandler, items, getActivity().getLayoutInflater(), 0, null); @@ -137,9 +194,32 @@ Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText()); View view2 = adapter.getView(1, view1, parentView); - Assert.assertNotEquals("Convert view should not have been re-used.", view1, view2); + Assert.assertNotEquals("Standard view should not have been re-used", view1, view2); Assert.assertEquals( "Title for view 1 should have not have been updated", TITLE_1, titleView.getText()); + + View view3 = adapter.getView(0, view2, parentView); + Assert.assertNotEquals("Title button view should not have been re-used", view2, view3); + } + + @Test + @MediumTest + public void testConvertView_NotReused_IconRow() { + Drawable icon = AppCompatResources.getDrawable( + getActivity(), org.chromium.chrome.test.R.drawable.test_ic_vintage_filter); + List<MenuItem> items = new ArrayList<>(); + items.add(buildIconRow(1, 2, TITLE_1, icon, 3, TITLE_2, icon, 4, "", icon, 0, null, null, 0, + null, null, true)); + items.add(buildIconRow(5, 6, TITLE_3, icon, 7, TITLE_4, icon, 8, "", icon, 9, TITLE_5, icon, + 0, null, null, true)); + + AppMenuAdapter adapter = new AppMenuAdapter( + mClickHandler, items, getActivity().getLayoutInflater(), 0, null); + + ViewGroup parentView = getActivity().findViewById(android.R.id.content); + View view1 = adapter.getView(0, null, parentView); + View view2 = adapter.getView(1, view1, parentView); + Assert.assertNotEquals("Convert view should not have been re-used", view1, view2); } @Test @@ -203,6 +283,8 @@ Assert.assertEquals("Binder2 incorrectly called", 0, customBinder2.getViewItemCallbackHelper.getCallCount()); Assert.assertNotEquals("Convert view should not have been re-used", view1, view2); + Assert.assertNotNull("Views created with binder1 should have an enter animation.", + view2.getTag(R.id.menu_item_enter_anim_id)); View view3 = adapter.getView(2, view2, parentView); Assert.assertEquals( @@ -224,17 +306,36 @@ Assert.assertEquals( "Binder2 not called", 1, customBinder2.getViewItemCallbackHelper.getCallCount()); Assert.assertNotEquals("Convert view should not have been re-used", view2, view5); + Assert.assertNull("Views created with binder2 should not have an enter animation", + view5.getTag(R.id.menu_item_enter_anim_id)); } - private static MenuItem buildMenuItem(int id, CharSequence title) { + static MenuItem buildMenuItem(int id, CharSequence title) { + return buildMenuItem(id, title, true); + } + + static MenuItem buildMenuItem(int id, CharSequence title, boolean enabled) { MenuItem item = Mockito.mock(MenuItem.class); Mockito.when(item.getItemId()).thenReturn(id); Mockito.when(item.getTitle()).thenReturn(title); + Mockito.when(item.isEnabled()).thenReturn(enabled); return item; } - private static MenuItem buildTitleMenuItem( + static MenuItem buildMenuItem(int id, CharSequence title, boolean enabled, Drawable icon) { + MenuItem item = buildMenuItem(id, title, enabled); + Mockito.when(item.getIcon()).thenReturn(icon); + return item; + } + + static MenuItem buildTitleMenuItem( int id, int subId1, CharSequence title1, int subId2, CharSequence title2) { + return buildTitleMenuItem(id, subId1, title1, subId2, title2, null, false, false, true); + } + + static MenuItem buildTitleMenuItem(int id, int subId1, CharSequence title1, int subId2, + CharSequence title2, @Nullable Drawable icon, boolean checkable, boolean checked, + boolean enabled) { MenuItem item = Mockito.mock(MenuItem.class); SubMenu subMenu = Mockito.mock(SubMenu.class); Mockito.when(item.getItemId()).thenReturn(id); @@ -242,12 +343,84 @@ Mockito.when(item.getSubMenu()).thenReturn(subMenu); Mockito.when(subMenu.size()).thenReturn(2); - MenuItem subMenuItem1 = buildMenuItem(subId1, title1); - MenuItem subMenuItem2 = buildMenuItem(subId2, title2); + MenuItem title = buildMenuItem(subId1, title1, enabled); + MenuItem subItem = buildMenuItem(subId2, title2, enabled); + Mockito.when(subMenu.getItem(0)).thenReturn(title); + Mockito.when(subMenu.getItem(1)).thenReturn(subItem); + + if (icon != null) { + assert !checkable : "Title button only supports icon or checkbox"; + Mockito.when(subItem.isCheckable()).thenReturn(false); + Mockito.when(subItem.getIcon()).thenReturn(icon); + Mockito.when(subItem.isChecked()).thenReturn(checked); + Mockito.when(subItem.isVisible()).thenReturn(true); + } + + if (checkable) { + assert icon == null : "Title button only supports icon or checkbox"; + Mockito.when(subItem.isCheckable()).thenReturn(true); + Mockito.when(subItem.isChecked()).thenReturn(checked); + Mockito.when(subItem.isVisible()).thenReturn(true); + } + + return item; + } + + static MenuItem buildIconMenuItem(int id, CharSequence titleCondensed, boolean enabled) { + MenuItem item = Mockito.mock(MenuItem.class); + Mockito.when(item.getItemId()).thenReturn(id); + Mockito.when(item.getTitleCondensed()).thenReturn(titleCondensed); + Mockito.when(item.isEnabled()).thenReturn(enabled); + return item; + } + + static MenuItem buildIconRow(int id, int subId1, CharSequence title1, Drawable icon1, + int subId2, CharSequence title2, Drawable icon2, int subId3, CharSequence title3, + Drawable icon3, int subId4, CharSequence title4, @Nullable Drawable icon4, int subId5, + CharSequence title5, @Nullable Drawable icon5, boolean enabled) { + MenuItem item = Mockito.mock(MenuItem.class); + SubMenu subMenu = Mockito.mock(SubMenu.class); + Mockito.when(item.getItemId()).thenReturn(id); + Mockito.when(item.hasSubMenu()).thenReturn(true); + Mockito.when(item.getSubMenu()).thenReturn(subMenu); + + int numSubMenus = 3; + if (subId4 != 0) { + numSubMenus++; + if (subId5 != 0) numSubMenus++; + } + Mockito.when(subMenu.size()).thenReturn(numSubMenus); + + MenuItem subMenuItem1 = buildIconMenuItem(subId1, title1, enabled); + Mockito.when(subMenuItem1.getIcon()).thenReturn(icon1); + Mockito.when(subMenuItem1.isVisible()).thenReturn(true); Mockito.when(subMenu.getItem(0)).thenReturn(subMenuItem1); + + MenuItem subMenuItem2 = buildIconMenuItem(subId2, title2, enabled); + Mockito.when(subMenuItem2.getIcon()).thenReturn(icon2); + Mockito.when(subMenuItem2.isVisible()).thenReturn(true); Mockito.when(subMenu.getItem(1)).thenReturn(subMenuItem2); + MenuItem subMenuItem3 = buildIconMenuItem(subId3, title3, enabled); + Mockito.when(subMenuItem3.getIcon()).thenReturn(icon3); + Mockito.when(subMenuItem3.isVisible()).thenReturn(true); + Mockito.when(subMenu.getItem(2)).thenReturn(subMenuItem3); + + if (subId4 != 0) { + MenuItem subMenuItem4 = buildIconMenuItem(subId4, title4, enabled); + Mockito.when(subMenuItem4.getIcon()).thenReturn(icon4); + Mockito.when(subMenuItem4.isVisible()).thenReturn(true); + Mockito.when(subMenu.getItem(3)).thenReturn(subMenuItem4); + + if (subId5 != 0) { + MenuItem subMenuItem5 = buildIconMenuItem(subId5, title5, enabled); + Mockito.when(subMenuItem5.getIcon()).thenReturn(icon5); + Mockito.when(subMenuItem5.isVisible()).thenReturn(true); + Mockito.when(subMenu.getItem(4)).thenReturn(subMenuItem5); + } + } + return item; } @@ -336,7 +509,7 @@ @Override public boolean supportsEnterAnimation(int id) { - return true; + return false; } } }
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 new file mode 100644 index 0000000..e38bde54 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -0,0 +1,276 @@ +// 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.appmenu; + +import android.support.test.filters.MediumTest; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.LifecycleObserver; +import org.chromium.chrome.browser.ui.widget.highlight.ViewHighlighterTestUtils; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.R; +import org.chromium.chrome.test.ui.DummyUiActivityTestCase; +import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; + +import java.util.concurrent.TimeoutException; + +/** + * Integration tests the app menu popup. Covers AppMenuCoordinatorImpl and public interface for + * AppMenuHandlerImpl. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class AppMenuTest extends DummyUiActivityTestCase { + private AppMenuCoordinatorImpl mAppMenuCoordinator; + private AppMenuHandlerImpl mAppMenuHandler; + private TestAppMenuPropertiesDelegate mPropertiesDelegate; + private TestAppMenuDelegate mDelegate; + private TestAppMenuObserver mMenuObserver; + private TestActivityLifecycleDispatcher mLifecycleDispatcher; + + @Override + public void setUpTest() throws Exception { + super.setUpTest(); + TestThreadUtils.runOnUiThreadBlocking(this::setUpTestOnUiThread); + mLifecycleDispatcher.observerRegisteredCallbackHelper.waitForCallback(0); + } + + private void setUpTestOnUiThread() { + mLifecycleDispatcher = new TestActivityLifecycleDispatcher(); + mDelegate = new TestAppMenuDelegate(); + mAppMenuCoordinator = new AppMenuCoordinatorImpl(getActivity(), mLifecycleDispatcher, + new TestMenuButtonDelegate(), mDelegate, getActivity().getWindow().getDecorView(), + new View(getActivity())); + mAppMenuHandler = mAppMenuCoordinator.getAppMenuHandlerImplForTesting(); + mMenuObserver = new TestAppMenuObserver(); + mAppMenuCoordinator.getAppMenuHandler().addObserver(mMenuObserver); + mPropertiesDelegate = + (TestAppMenuPropertiesDelegate) mAppMenuCoordinator.getAppMenuPropertiesDelegate(); + } + + @Test + @MediumTest + public void testShowHideAppMenu() throws TimeoutException { + showSimpleMenuAndAssert(); + + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu()); + mMenuObserver.menuHiddenCallback.waitForCallback(0); + + Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after hide", 1, + mPropertiesDelegate.menuDismissedCallback.getCallCount()); + + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuCoordinator.destroy()); + Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after destroy", 1, + mPropertiesDelegate.menuDismissedCallback.getCallCount()); + } + + @Test + @MediumTest + public void testShowDestroyAppMenu() throws TimeoutException { + showSimpleMenuAndAssert(); + + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuCoordinator.destroy()); + + Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after destroy", 1, + mPropertiesDelegate.menuDismissedCallback.getCallCount()); + } + + @Test + @MediumTest + public void testClickMenuItem() throws TimeoutException { + showSimpleMenuAndAssert(); + + TestThreadUtils.runOnUiThreadBlocking( + () + -> AppMenuTestSupport.callOnItemClick( + mAppMenuCoordinator, R.id.menu_item_three)); + mDelegate.itemSelectedCallbackHelper.waitForCallback(0); + + Assert.assertEquals("Incorrect id for last selected item.", R.id.menu_item_three, + mDelegate.lastSelectedItemId); + } + + @Test + @MediumTest + public void testAppMenuBlockers() throws TimeoutException { + Assert.assertTrue("App menu should be allowed to show, no blockers registered", + AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator)); + + AppMenuBlocker blocker1 = () -> false; + AppMenuBlocker blocker2 = () -> true; + + mAppMenuCoordinator.registerAppMenuBlocker(blocker1); + mAppMenuCoordinator.registerAppMenuBlocker(blocker2); + Assert.assertFalse("App menu should not be allowed to show, both blockers registered", + AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator)); + TestThreadUtils.runOnUiThreadBlocking( + () -> mAppMenuCoordinator.showAppMenuForKeyboardEvent()); + Assert.assertFalse( + "App menu should not have been shown.", mAppMenuHandler.isAppMenuShowing()); + + mAppMenuCoordinator.unregisterAppMenuBlocker(blocker1); + Assert.assertTrue("App menu should be allowed to show, only blocker2 registered", + AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator)); + showSimpleMenuAndAssert(); + } + + @Test + @MediumTest + public void testSetMenuHighlight_StandardItem() throws TimeoutException { + Assert.assertFalse(mMenuObserver.menuHighlighting); + + TestThreadUtils.runOnUiThreadBlocking( + () -> mAppMenuHandler.setMenuHighlight(R.id.menu_item_one, false)); + mMenuObserver.menuHighlightChangedCallback.waitForCallback(0); + Assert.assertTrue(mMenuObserver.menuHighlighting); + + showSimpleMenuAndAssert(); + + View itemView = getViewAtPosition(0); + ViewHighlighterTestUtils.checkHighlightOn(itemView); + + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.clearMenuHighlight()); + mMenuObserver.menuHighlightChangedCallback.waitForCallback(1); + Assert.assertFalse(mMenuObserver.menuHighlighting); + ViewHighlighterTestUtils.checkHighlightOff(itemView); + } + + @Test + @MediumTest + public void testSetMenuHighlight_Icon() throws TimeoutException { + mPropertiesDelegate.enableAppIconRow = true; + + Assert.assertFalse(mMenuObserver.menuHighlighting); + + TestThreadUtils.runOnUiThreadBlocking( + () -> mAppMenuHandler.setMenuHighlight(R.id.icon_one, false)); + mMenuObserver.menuHighlightChangedCallback.waitForCallback(0); + Assert.assertTrue(mMenuObserver.menuHighlighting); + + showSimpleMenuAndAssert(); + + View itemView = ((LinearLayout) getViewAtPosition(3)).getChildAt(0); + ViewHighlighterTestUtils.checkHighlightOn(itemView); + + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.clearMenuHighlight()); + mMenuObserver.menuHighlightChangedCallback.waitForCallback(1); + Assert.assertFalse(mMenuObserver.menuHighlighting); + ViewHighlighterTestUtils.checkHighlightOff(itemView); + } + + @Test + @MediumTest + public void testMenuItemContentChanged() throws TimeoutException { + showSimpleMenuAndAssert(); + View itemView = getViewAtPosition(1); + Assert.assertEquals("Menu item text incorrect", "Menu Item Two", + ((TextView) itemView.findViewById(R.id.menu_item_text)).getText()); + + String newText = "Test!"; + TestThreadUtils.runOnUiThreadBlocking(() -> { + mAppMenuHandler.getAppMenu().getMenu().findItem(R.id.menu_item_two).setTitle(newText); + mAppMenuHandler.menuItemContentChanged(R.id.menu_item_two); + }); + + itemView = getViewAtPosition(1); + Assert.assertEquals("Menu item text incorrect", newText, + ((TextView) itemView.findViewById(R.id.menu_item_text)).getText()); + } + + @Test + @MediumTest + public void testHeaderFooter() throws TimeoutException { + mPropertiesDelegate.headerResourceId = R.layout.test_menu_header; + mPropertiesDelegate.footerResourceId = R.layout.test_menu_footer; + showSimpleMenuAndAssert(); + + mPropertiesDelegate.headerInflatedCallback.waitForCallback(0); + mPropertiesDelegate.footerInflatedCallback.waitForCallback(0); + + Assert.assertEquals("Incorrect number of header views", 1, + mAppMenuHandler.getAppMenu().getListView().getHeaderViewsCount()); + Assert.assertNotNull("Footer stub not inflated.", + mAppMenuHandler.getAppMenu().getPopup().getContentView().findViewById( + R.id.app_menu_footer)); + } + + @Test + @MediumTest + public void testAppMenuHiddenOnStopWithNative() throws TimeoutException { + showSimpleMenuAndAssert(); + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.onStopWithNative()); + Assert.assertFalse(mAppMenuHandler.isAppMenuShowing()); + } + + @Test + @MediumTest + public void testAppMenuHiddenOnConfigurationChange() throws TimeoutException { + showSimpleMenuAndAssert(); + TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.onConfigurationChanged(null)); + Assert.assertFalse(mAppMenuHandler.isAppMenuShowing()); + } + + private void showSimpleMenuAndAssert() throws TimeoutException { + int currentCallCount = mMenuObserver.menuShownCallback.getCallCount(); + TestThreadUtils.runOnUiThreadBlocking( + () -> mAppMenuCoordinator.showAppMenuForKeyboardEvent()); + mMenuObserver.menuShownCallback.waitForCallback(currentCallCount); + Assert.assertTrue("Menu should be showing", mAppMenuHandler.isAppMenuShowing()); + + TestThreadUtils.runOnUiThreadBlocking( + () -> mAppMenuHandler.getAppMenu().finishAnimationsForTests()); + } + + private class TestActivityLifecycleDispatcher implements ActivityLifecycleDispatcher { + public CallbackHelper observerRegisteredCallbackHelper = new CallbackHelper(); + @Override + public void register(LifecycleObserver observer) { + observerRegisteredCallbackHelper.notifyCalled(); + } + + @Override + public void unregister(LifecycleObserver observer) {} + + @Override + public int getCurrentActivityState() { + return 0; + } + } + + private class TestMenuButtonDelegate implements MenuButtonDelegate { + @Nullable + @Override + public View getMenuButtonView() { + return null; + } + + @Override + public boolean isMenuFromBottom() { + return false; + } + } + + private View getViewAtPosition(int index) { + // Wait for the view to be available. This is necessary when the menu is first shown. + CriteriaHelper.pollUiThread( + () + -> AppMenuTestSupport.getListView(mAppMenuCoordinator).getChildAt(index) + != null); + return AppMenuTestSupport.getListView(mAppMenuCoordinator).getChildAt(index); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java index 767cf5b..f1956731 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java
@@ -43,7 +43,7 @@ import java.util.concurrent.TimeoutException; /** - * Tests AppMenu popup + * Tests tabbed mode app menu popup. */ @RunWith(ChromeJUnit4ClassRunner.class) @RetryOnFailure @@ -178,29 +178,6 @@ hitEnterAndAssertAppMenuDismissed(); } - /** - * Test that changing orientation hides the menu. - */ - /* - @SmallTest - @Feature({"Browser", "Main"}) - */ - @Test - @DisabledTest(message = "crbug.com/458193") - public void testChangingOrientationHidesMenu() { - mActivityTestRule.getActivity().setRequestedOrientation( - ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - showAppMenuAndAssertMenuShown(); - mActivityTestRule.getActivity().setRequestedOrientation( - ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not dismiss") { - @Override - public boolean isSatisfied() { - return !mAppMenuHandler.isAppMenuShowing(); - } - }); - } - @Test @SmallTest @Feature({"Browser", "Main"})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuDelegate.java new file mode 100644 index 0000000..ad19967e --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuDelegate.java
@@ -0,0 +1,28 @@ +// 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.appmenu; + +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import org.chromium.base.test.util.CallbackHelper; + +class TestAppMenuDelegate implements AppMenuDelegate { + public final CallbackHelper itemSelectedCallbackHelper = new CallbackHelper(); + public int lastSelectedItemId; + + @Override + public boolean onOptionsItemSelected(int itemId, @Nullable Bundle menuItemData) { + lastSelectedItemId = itemId; + itemSelectedCallbackHelper.notifyCalled(); + return true; + } + + @Override + public AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() { + return new TestAppMenuPropertiesDelegate(); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuObserver.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuObserver.java new file mode 100644 index 0000000..908828ea --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuObserver.java
@@ -0,0 +1,32 @@ +// 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.appmenu; + +import org.chromium.base.test.util.CallbackHelper; + +/** + * AppMenuObserver that notifies callbacks when app menu events occur. + */ +public class TestAppMenuObserver implements AppMenuObserver { + public CallbackHelper menuShownCallback = new CallbackHelper(); + public CallbackHelper menuHiddenCallback = new CallbackHelper(); + public CallbackHelper menuHighlightChangedCallback = new CallbackHelper(); + public boolean menuHighlighting; + + @Override + public void onMenuVisibilityChanged(boolean isVisible) { + if (isVisible) { + menuShownCallback.notifyCalled(); + } else { + menuHiddenCallback.notifyCalled(); + } + } + + @Override + public void onMenuHighlightChanged(boolean highlighting) { + menuHighlighting = highlighting; + menuHighlightChangedCallback.notifyCalled(); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuPropertiesDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuPropertiesDelegate.java new file mode 100644 index 0000000..6289c47b --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuPropertiesDelegate.java
@@ -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. + +package org.chromium.chrome.browser.appmenu; + +import android.os.Bundle; +import android.support.v7.content.res.AppCompatResources; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import androidx.annotation.Nullable; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.chrome.test.R; + +import java.util.List; + +class TestAppMenuPropertiesDelegate implements AppMenuPropertiesDelegate { + public final CallbackHelper menuDismissedCallback = new CallbackHelper(); + public final CallbackHelper footerInflatedCallback = new CallbackHelper(); + public final CallbackHelper headerInflatedCallback = new CallbackHelper(); + public int footerResourceId; + public int headerResourceId; + public boolean enableAppIconRow; + + @Override + public void destroy() {} + + @Override + public int getAppMenuLayoutId() { + return R.menu.test_menu; + } + + @Nullable + @Override + public List<CustomViewBinder> getCustomViewBinders() { + return null; + } + + @Override + public void prepareMenu(Menu menu, AppMenuHandler handler) { + menu.findItem(R.id.icon_row_menu_id).setVisible(enableAppIconRow); + if (enableAppIconRow) { + menu.findItem(R.id.icon_one) + .setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(), + R.drawable.test_ic_arrow_forward_black_24dp)); + menu.findItem(R.id.icon_two) + .setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(), + R.drawable.test_ic_arrow_forward_black_24dp)); + menu.findItem(R.id.icon_three) + .setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(), + R.drawable.test_ic_arrow_forward_black_24dp)); + } + } + + @Nullable + @Override + public Bundle getBundleForMenuItem(MenuItem item) { + return null; + } + + @Override + public void loadingStateChanged(boolean isLoading) {} + + @Override + public void onMenuDismissed() { + menuDismissedCallback.notifyCalled(); + } + + @Override + public int getFooterResourceId() { + return footerResourceId; + } + + @Override + public int getHeaderResourceId() { + return headerResourceId; + } + + @Override + public boolean shouldShowFooter(int maxMenuHeight) { + return footerResourceId != 0; + } + + @Override + public boolean shouldShowHeader(int maxMenuHeight) { + return headerResourceId != 0; + } + + @Override + public void onFooterViewInflated(AppMenuHandler appMenuHandler, View view) { + footerInflatedCallback.notifyCalled(); + } + + @Override + public void onHeaderViewInflated(AppMenuHandler appMenuHandler, View view) { + headerInflatedCallback.notifyCalled(); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactDetailsTest.java new file mode 100644 index 0000000..564c351 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactDetailsTest.java
@@ -0,0 +1,157 @@ +// 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.contacts_picker; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.payments.mojom.PaymentAddress; + +import java.util.Arrays; +import java.util.List; + +/** + * Tests for the ContactDetails class. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +public class ContactDetailsTest { + @Rule + public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + + Context mContext; + + @Before + public void setUp() throws Exception { + mContext = InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getApplicationContext(); + } + + private void compareAbbreviatedContactDetails(ContactDetails.AbbreviatedContactDetails expected, + ContactDetails.AbbreviatedContactDetails actual) { + Assert.assertEquals(expected.primaryEmail, actual.primaryEmail); + Assert.assertEquals(expected.overflowEmailCount, actual.overflowEmailCount); + Assert.assertEquals(expected.primaryTelephoneNumber, actual.primaryTelephoneNumber); + Assert.assertEquals( + expected.overflowTelephoneNumberCount, actual.overflowTelephoneNumberCount); + } + + @Test + @SmallTest + public void testBasics() { + PaymentAddress address1 = new PaymentAddress(); + address1.city = "city"; + address1.country = "country"; + address1.addressLine = new String[] {"formattedAddress1"}; + address1.postalCode = "postalCode"; + address1.region = "region"; + address1.dependentLocality = ""; + address1.sortingCode = ""; + address1.organization = ""; + address1.recipient = ""; + address1.phone = ""; + PaymentAddress address2 = new PaymentAddress(); + address2.city = "city"; + address2.country = "country"; + address2.addressLine = new String[] {"formattedAddress2"}; + address2.postalCode = "postalCode"; + address2.region = "region"; + address2.dependentLocality = ""; + address2.sortingCode = ""; + address2.organization = ""; + address2.recipient = ""; + address2.phone = ""; + + ContactDetails contact = new ContactDetails("id", "Display Name", + Arrays.asList("email@example.com", "email2@example.com"), + Arrays.asList("555 123-4567", "555 765-4321"), Arrays.asList(address1, address2)); + + Assert.assertEquals("id", contact.getId()); + Assert.assertEquals("Display Name", contact.getDisplayName()); + Assert.assertEquals("DN", contact.getDisplayNameAbbreviation()); + + List<String> emails = contact.getEmails(); + Assert.assertEquals(2, emails.size()); + Assert.assertEquals("email@example.com", emails.get(0)); + Assert.assertEquals("email2@example.com", emails.get(1)); + + List<String> telephones = contact.getPhoneNumbers(); + Assert.assertEquals(2, telephones.size()); + Assert.assertEquals("555 123-4567", telephones.get(0)); + Assert.assertEquals("555 765-4321", telephones.get(1)); + + List<PaymentAddress> addresses = contact.getAddresses(); + Assert.assertEquals(2, addresses.size()); + Assert.assertEquals("formattedAddress1", addresses.get(0).addressLine[0]); + Assert.assertEquals("formattedAddress2", addresses.get(1).addressLine[0]); + + Assert.assertEquals(false, contact.isSelf()); + Assert.assertEquals(null, contact.getSelfIcon()); + + contact.setIsSelf(true); + + Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.drawColor(Color.BLUE); + BitmapDrawable drawable = new BitmapDrawable(bitmap); + contact.setSelfIcon(drawable); + + Assert.assertEquals(true, contact.isSelf()); + Assert.assertTrue(null != contact.getSelfIcon()); + + Assert.assertEquals("", contact.getContactDetailsAsString(false, false)); + Assert.assertEquals("email@example.com\nemail2@example.com", + contact.getContactDetailsAsString(true, false)); + Assert.assertEquals( + "555 123-4567\n555 765-4321", contact.getContactDetailsAsString(false, true)); + + Resources resources = mContext.getResources(); + ContactDetails.AbbreviatedContactDetails expected = + new ContactDetails.AbbreviatedContactDetails(); + expected.primaryEmail = "email@example.com"; + expected.overflowEmailCount = "(+ 1 more)"; + expected.primaryTelephoneNumber = "555 123-4567"; + expected.overflowTelephoneNumberCount = "(+ 1 more)"; + + // Test with full details. + ContactDetails.AbbreviatedContactDetails actual = contact.getAbbreviatedContactDetails( + /*includeEmails=*/true, /*includeTels=*/true, resources); + compareAbbreviatedContactDetails(expected, actual); + // Test with only email details. + actual = contact.getAbbreviatedContactDetails( + /*includeEmails=*/true, /*includeTels=*/false, resources); + expected.primaryTelephoneNumber = ""; + expected.overflowTelephoneNumberCount = ""; + compareAbbreviatedContactDetails(expected, actual); + // Test with no details. + actual = contact.getAbbreviatedContactDetails( + /*includeEmails=*/false, /*includeTels=*/false, resources); + expected.primaryEmail = ""; + expected.overflowEmailCount = ""; + compareAbbreviatedContactDetails(expected, actual); + // Test with only telephone details. + actual = contact.getAbbreviatedContactDetails( + /*includeEmails=*/false, /*includeTels=*/true, resources); + expected.primaryTelephoneNumber = "555 123-4567"; + expected.overflowTelephoneNumberCount = "(+ 1 more)"; + compareAbbreviatedContactDetails(expected, actual); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java index edaef13f..878eab79 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java
@@ -94,34 +94,6 @@ @Before public void setUp() throws Exception { mActivityTestRule.startMainActivityOnBlankPage(); - mTestContacts = new ArrayList<ContactDetails>(); - - PaymentAddress address = new PaymentAddress(); - address.city = "city"; - address.country = "country"; - address.addressLine = new String[] {"formattedAddress"}; - address.postalCode = "postalCode"; - address.region = "region"; - address.dependentLocality = ""; - address.sortingCode = ""; - address.organization = ""; - address.recipient = ""; - address.phone = ""; - - mTestContacts.add(new ContactDetails("0", "Contact 0", Arrays.asList("0@example.com"), - Arrays.asList("555-1234"), Arrays.asList(address))); - mTestContacts.add(new ContactDetails("1", "Contact 1", /*emails=*/null, - /*phoneNumbers=*/null, /*addresses=*/null)); - mTestContacts.add(new ContactDetails("2", "Contact 2", /*emails=*/null, - /*phoneNumbers=*/null, /*addresses=*/null)); - mTestContacts.add(new ContactDetails("3", "Contact 3", /*emails=*/null, - /*phoneNumbers=*/null, /*addresses=*/null)); - mTestContacts.add(new ContactDetails("4", "Contact 4", /*emails=*/null, - /*phoneNumbers=*/null, /*addresses=*/null)); - mTestContacts.add(new ContactDetails("5", "Contact 5", /*emails=*/null, - /*phoneNumbers=*/null, /*addresses=*/null)); - PickerAdapter.setTestContacts(mTestContacts); - Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(Color.BLUE); @@ -206,6 +178,18 @@ } } + /** + * Clicks a single view in the Recyclerview in search mode. + * @param position The position of the item to click (zero-based).. + * @param expectedSelectionCount The expected selection count after the view has been clicked. + * @param expectSelection True if the clicked-on view should become selected. + */ + private void clickViewInSearchMode(final int position, final int expectedSelectionCount, + final boolean expectSelection) throws Exception { + // Search mode does not have the Select All checkbox, so we don't need to skip it. + clickView(position - 1, expectedSelectionCount, expectSelection); + } + private void clickDone() throws Exception { Assert.assertEquals(false, mClosing); mClosing = true; @@ -269,6 +253,12 @@ TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), search); } + private void setSearchString(String query, int expectedMatches) { + TestThreadUtils.runOnUiThreadBlocking( + () -> mDialog.getCategoryViewForTesting().onSearchTextChanged(query)); + Assert.assertEquals(expectedMatches, getRecyclerView().getAdapter().getItemCount()); + } + private void dismissDialog() throws Exception { Assert.assertEquals(false, mClosing); mClosing = true; @@ -288,9 +278,53 @@ return (TopView) view; } + /** + * Sets the contacts to use during the test. + * @param ownerEmail If not null, includes a few contact entries representing owners. + */ + private void setTestContacts(String ownerEmail) { + mTestContacts = new ArrayList<ContactDetails>(); + PaymentAddress address = new PaymentAddress(); + address.city = "city"; + address.country = "country"; + address.addressLine = new String[] {"formattedAddress"}; + address.postalCode = "postalCode"; + address.region = "region"; + address.dependentLocality = ""; + address.sortingCode = ""; + address.organization = ""; + address.recipient = ""; + address.phone = ""; + + mTestContacts.add(new ContactDetails("0", "Contact 0", Arrays.asList("0@example.com"), + Arrays.asList("555-1234"), Arrays.asList(address))); + mTestContacts.add(new ContactDetails("1", "Contact 1", /*emails=*/null, + /*phoneNumbers=*/null, /*addresses=*/null)); + mTestContacts.add(new ContactDetails("2", "Contact 2", /*emails=*/null, + /*phoneNumbers=*/null, /*addresses=*/null)); + mTestContacts.add(new ContactDetails("3", "Contact 3", /*emails=*/null, + /*phoneNumbers=*/null, /*addresses=*/null)); + mTestContacts.add(new ContactDetails("4", "Contact 4", /*emails=*/null, + /*phoneNumbers=*/null, /*addresses=*/null)); + mTestContacts.add(new ContactDetails("5", "Contact 5", /*emails=*/null, + /*phoneNumbers=*/null, /*addresses=*/null)); + if (ownerEmail != null) { + // Note: The dialog will move Contact 6 (owner) to the top of the list. + ContactDetails owner = new ContactDetails("6", "Contact 6", + Arrays.asList("owner@example.com"), /*phoneNumbers=*/null, /*addresses=*/null); + ContactDetails owner2 = new ContactDetails("7", "Contact 7", + Arrays.asList("owner@example.com"), /*phoneNumbers=*/null, /*addresses=*/null); + mTestContacts.add(owner); + mTestContacts.add(owner2); + } + + PickerAdapter.setTestContactsAndOwner(mTestContacts, ownerEmail); + } + @Test @LargeTest public void testOriginString() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ true, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -311,6 +345,7 @@ @Test @LargeTest public void testFilterVisibilityForDataInclusion() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ false, /* includeTel = */ true, @@ -338,6 +373,7 @@ @Test @LargeTest public void testNoSelection() throws Throwable { + setTestContacts(/*ownerEmail=*/"notanowner@example.com"); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -356,7 +392,30 @@ @Test @LargeTest + public void testOwnerContact() throws Throwable { + setTestContacts(/*ownerEmail=*/"owner@example.com"); + createDialog(/* multiselect = */ false, /* includeNames = */ true, + /* includeEmails = */ true, + /* includeTel = */ true, + /* includeAddresses = */ true); + Assert.assertTrue(mDialog.isShowing()); + + int expectedSelectionCount = 1; + clickView(0, expectedSelectionCount, /* expectSelection = */ true); + clickDone(); + + Assert.assertEquals(ContactsPickerAction.CONTACTS_SELECTED, mLastActionRecorded); + Assert.assertEquals(1, mLastSelectedContacts.size()); + Assert.assertEquals( + mTestContacts.get(0).getDisplayName(), mLastSelectedContacts.get(0).names.get(0)); + Assert.assertEquals(12, mLastPercentageShared); + Assert.assertEquals(15, mLastPropertiesRequested); + } + + @Test + @LargeTest public void testSingleSelectionContacts() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -380,6 +439,7 @@ @Test @LargeTest public void testMultiSelectionContacts() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ true, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -408,6 +468,7 @@ @Test @LargeTest public void testNamesRemoved() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -444,6 +505,7 @@ @Test @LargeTest public void testEmailsRemoved() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -468,6 +530,7 @@ @Test @LargeTest public void testTelephonesRemoved() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -492,6 +555,7 @@ @Test @LargeTest public void testPropertiesRequested() throws Throwable { + setTestContacts(/*ownerEmail=*/null); // Create a dialog showing names only. createDialog(/* multiselect = */ false, /* includeNames = */ true, /* includeEmails = */ false, @@ -532,19 +596,20 @@ @Test @LargeTest public void testSelectAll() throws Throwable { + setTestContacts(/*ownerEmail=*/"owner@example.com"); createDialog(/* multiselect = */ true, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, /* includeAddresses = */ true); Assert.assertTrue(mDialog.isShowing()); - toggleSelectAll(6, ContactsPickerAction.SELECT_ALL); + toggleSelectAll(8, ContactsPickerAction.SELECT_ALL); toggleSelectAll(0, ContactsPickerAction.UNDO_SELECT_ALL); // Manually select one item. clickView(0, /* expectedSelectionCount = */ 1, /* expectSelection = */ true); - toggleSelectAll(6, ContactsPickerAction.SELECT_ALL); + toggleSelectAll(8, ContactsPickerAction.SELECT_ALL); toggleSelectAll(0, ContactsPickerAction.UNDO_SELECT_ALL); // Select the rest of the items manually. @@ -554,14 +619,44 @@ clickView(3, ++expectedSelectionCount, /* expectSelection = */ true); clickView(4, ++expectedSelectionCount, /* expectSelection = */ true); clickView(5, ++expectedSelectionCount, /* expectSelection = */ true); + clickView(6, ++expectedSelectionCount, /* expectSelection = */ true); + clickView(7, ++expectedSelectionCount, /* expectSelection = */ true); - toggleSelectAll(6, ContactsPickerAction.SELECT_ALL); + toggleSelectAll(8, ContactsPickerAction.SELECT_ALL); toggleSelectAll(0, ContactsPickerAction.UNDO_SELECT_ALL); } @Test @LargeTest + public void testSearchString() throws Throwable { + setTestContacts(/*ownerEmail=*/null); + createDialog(/* multiselect = */ false, /* includeNames = */ true, + /* includeEmails = */ true, + /* includeTel = */ true, + /* includeAddresses = */ true); + Assert.assertTrue(mDialog.isShowing()); + + clickSearchButton(); + setSearchString("NoMatches", /*expectedMatches=*/0); + setSearchString("Contact", /*expectedMatches=*/6); + setSearchString("Contact 3", /*expectedMatches=*/1); + + int expectedSelectionCount = 1; + clickViewInSearchMode(0, expectedSelectionCount, /* expectSelection = */ true); + clickDone(); + + Assert.assertEquals(ContactsPickerAction.CONTACTS_SELECTED, mLastActionRecorded); + Assert.assertEquals(1, mLastSelectedContacts.size()); + Assert.assertEquals( + mTestContacts.get(3).getDisplayName(), mLastSelectedContacts.get(0).names.get(0)); + Assert.assertEquals(16, mLastPercentageShared); + Assert.assertEquals(15, mLastPropertiesRequested); + } + + @Test + @LargeTest public void testNoSearchStringNoCrash() throws Throwable { + setTestContacts(/*ownerEmail=*/null); createDialog(/* multiselect = */ true, /* includeNames = */ true, /* includeEmails = */ true, /* includeTel = */ true, @@ -575,7 +670,7 @@ @Test @LargeTest public void testEmptyContactListCrash() throws Throwable { - PickerAdapter.setTestContacts(new ArrayList<ContactDetails>()); + PickerAdapter.setTestContactsAndOwner(new ArrayList<ContactDetails>(), null); createDialog(/* multiselect = */ true, /* includeNames = */ true, /* includeEmails = */ true,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java index 0dccf55..15ae635 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
@@ -18,7 +18,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -74,7 +73,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testFullscreenVideoDetected() throws Throwable { enterFullscreen(); } @@ -83,7 +81,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testFullscreenVideoDetectedOnlyWhenPlaying() throws Throwable { enterFullscreen(); @@ -96,7 +93,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testEnterPip() throws Throwable { enterFullscreen(); triggerAutoPiP(); @@ -108,7 +104,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testExitPipOnNavigation() throws Throwable { testExitOn(() -> JavaScriptUtils.executeJavaScript(getWebContents(), "window.location.href = 'https://www.example.com/';")); @@ -118,7 +113,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testExitOnLeaveFullscreen() throws Throwable { testExitOn(() -> DOMUtils.exitFullscreen(getWebContents())); } @@ -127,7 +121,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testExitOnCloseTab() throws Throwable { // We want 2 Tabs so we can close the first without any special behaviour. mActivityTestRule.loadUrlInNewTab(mTestServer.getURL(TEST_PATH)); @@ -139,7 +132,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testExitOnCrash() throws Throwable { testExitOn(() -> WebContentsUtils.simulateRendererKilled(getWebContents(), false)); } @@ -148,7 +140,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testExitOnNewForegroundTab() throws Throwable { testExitOn(new Runnable() { @Override @@ -166,7 +157,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testNoExitOnIframeNavigation() throws Throwable { // Add a TabObserver so we know when the iFrame navigation has occurred before we check that // we are still in PiP. @@ -190,7 +180,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) - @DisabledTest(message = "https://crbug.com/1000183") public void testReenterPip() throws Throwable { enterFullscreen(); triggerAutoPiP(); @@ -225,7 +214,8 @@ DOMUtils.waitForMediaPlay(getWebContents(), VIDEO_ID); // Trigger requestFullscreen() via a click on a button. - Assert.assertTrue(DOMUtils.clickNode(getWebContents(), "fullscreen")); + Assert.assertTrue(DOMUtils.clickNode(getWebContents(), "fullscreen", + true /* goThroughRootAndroidView */, false /* shouldScrollIntoView */)); // We use the web contents fullscreen heuristic. CriteriaHelper.pollUiThread(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/NightModeTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/NightModeTestUtils.java index f45e47dd..50e441ab 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/NightModeTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/night_mode/NightModeTestUtils.java
@@ -10,6 +10,7 @@ import org.chromium.base.test.params.ParameterSet; import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences; import org.chromium.chrome.test.ui.DummyUiActivity; @@ -64,7 +65,8 @@ * @param nightModeEnabled Whether night mode should be enabled. */ public static void setUpNightModeForChromeActivity(boolean nightModeEnabled) { - ChromePreferenceManager.getInstance().writeInt(ChromePreferenceManager.UI_THEME_SETTING_KEY, + SharedPreferencesManager.getInstance().writeInt( + ChromePreferenceManager.UI_THEME_SETTING_KEY, nightModeEnabled ? ThemePreferences.ThemeSetting.DARK : ThemePreferences.ThemeSetting.LIGHT); } @@ -77,7 +79,7 @@ FeatureUtilities.setNightModeAvailableForTesting(null); NightModeUtils.setNightModeSupportedForTesting(null); GlobalNightModeStateProviderHolder.resetInstanceForTesting(); - ChromePreferenceManager.getInstance().removeKey( + SharedPreferencesManager.getInstance().removeKey( ChromePreferenceManager.UI_THEME_SETTING_KEY); } }
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 56b3dc2c..50db631 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
@@ -19,15 +19,14 @@ import org.junit.runner.RunWith; 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.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.appmenu.AppMenuObserver; import org.chromium.chrome.browser.appmenu.AppMenuTestSupport; +import org.chromium.chrome.browser.appmenu.TestAppMenuObserver; import org.chromium.chrome.browser.util.UrlConstants; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -106,22 +105,6 @@ } } - private static class TestAppMenuObserver implements AppMenuObserver { - CallbackHelper mMenuShownCallback = new CallbackHelper(); - CallbackHelper mMenuHiddenCallback = new CallbackHelper(); - - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - if (isVisible) { - mMenuShownCallback.notifyCalled(); - } else { - mMenuHiddenCallback.notifyCalled(); - } - } - - @Override - public void onMenuHighlightChanged(boolean highlighting) {} - } private MockVersionNumberGetter mMockVersionNumberGetter; private MockMarketURLGetter mMockMarketURLGetter; @@ -278,7 +261,7 @@ Assert.assertEquals("Incorrect item not clicked histogram count after item clicked", 0, getTotalItemNotClickedCount()); - mMenuObserver.mMenuHiddenCallback.waitForCallback(0); + mMenuObserver.menuHiddenCallback.waitForCallback(0); waitForAppMenuDimissedRunnable(); Assert.assertEquals("Incorrect item clicked histogram count after menu dismissed", 1, @@ -311,21 +294,21 @@ } private void showAppMenuAndAssertMenuShown() throws TimeoutException { - int currentCallCount = mMenuObserver.mMenuShownCallback.getCallCount(); + int currentCallCount = mMenuObserver.menuShownCallback.getCallCount(); TestThreadUtils.runOnUiThreadBlocking(() -> { AppMenuTestSupport.showAppMenu( mActivityTestRule.getAppMenuCoordinator(), null, false, false); }); - mMenuObserver.mMenuShownCallback.waitForCallback(currentCallCount); + mMenuObserver.menuShownCallback.waitForCallback(currentCallCount); } private void hideAppMenuAndAssertMenuShown() throws TimeoutException { - int currentCallCount = mMenuObserver.mMenuHiddenCallback.getCallCount(); + int currentCallCount = mMenuObserver.menuHiddenCallback.getCallCount(); TestThreadUtils.runOnUiThreadBlocking( () -> mActivityTestRule.getAppMenuCoordinator().getAppMenuHandler().hideAppMenu()); - mMenuObserver.mMenuHiddenCallback.waitForCallback(currentCallCount); + mMenuObserver.menuHiddenCallback.waitForCallback(currentCallCount); } private int getTotalItemClickedCount() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java index 3cf6214..3685a06 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java
@@ -22,9 +22,9 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.night_mode.NightModeUtils; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.Preferences; import org.chromium.chrome.browser.preferences.PreferencesTest; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences.ThemeSetting; import org.chromium.chrome.browser.ui.widget.RadioButtonWithDescription; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; @@ -61,7 +61,7 @@ @Override public void setUpTest() throws Exception { super.setUpTest(); - ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY); + SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING_KEY); Preferences preferences = PreferencesTest.startPreferences( InstrumentationRegistry.getInstrumentation(), ThemePreferences.class.getName()); mFragment = (ThemePreferences) preferences.getMainFragment(); @@ -71,7 +71,7 @@ @Override public void tearDownTest() throws Exception { - ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY); + SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING_KEY); FeatureUtilities.setNightModeDefaultToLightForTesting(null); super.tearDownTest(); } @@ -101,7 +101,7 @@ assertButtonCheckedCorrectly("System default", 0); Assert.assertEquals(ThemeSetting.SYSTEM_DEFAULT, mPreference.getSetting()); Assert.assertEquals(mPreference.getSetting(), - ChromePreferenceManager.getInstance().readInt(UI_THEME_SETTING_KEY)); + SharedPreferencesManager.getInstance().readInt(UI_THEME_SETTING_KEY)); // Select Light Assert.assertEquals(R.id.light, getButton(1).getId()); @@ -109,7 +109,7 @@ assertButtonCheckedCorrectly("Light", 1); Assert.assertEquals(ThemeSetting.LIGHT, mPreference.getSetting()); Assert.assertEquals(mPreference.getSetting(), - ChromePreferenceManager.getInstance().readInt(UI_THEME_SETTING_KEY)); + SharedPreferencesManager.getInstance().readInt(UI_THEME_SETTING_KEY)); // Select Dark Assert.assertEquals(R.id.dark, getButton(2).getId()); @@ -117,7 +117,7 @@ assertButtonCheckedCorrectly("Dark", 2); Assert.assertEquals(ThemeSetting.DARK, mPreference.getSetting()); Assert.assertEquals(mPreference.getSetting(), - ChromePreferenceManager.getInstance().readInt(UI_THEME_SETTING_KEY)); + SharedPreferencesManager.getInstance().readInt(UI_THEME_SETTING_KEY)); }); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java index 8a88fbb..518fbe78 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/ClearDataDialogResultRecorderTest.java
@@ -26,7 +26,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; /** * Tests for {@link ClearDataDialogResultRecorder}. @@ -34,7 +34,7 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class ClearDataDialogResultRecorderTest { - private final ChromePreferenceManager mPrefsManager = ChromePreferenceManager.getInstance(); + private final SharedPreferencesManager mPrefsManager = SharedPreferencesManager.getInstance(); @Mock ChromeBrowserInitializer mBrowserInitializer; @Mock TrustedWebActivityUmaRecorder mUmaRecorder; @Captor ArgumentCaptor<Runnable> mTaskOnNativeInitCaptor;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java index 046d5a4d..5eda962f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java
@@ -31,7 +31,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.flags.FeatureUtilities; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences; @@ -91,7 +90,7 @@ @After public void tearDown() { - ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY); + SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING_KEY); } @Test @@ -143,12 +142,12 @@ @Test public void testUpdateNightMode_Preference() { // Set preference to dark theme and verify night mode is enabled. - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.DARK); assertTrue(mGlobalNightModeStateController.isInNightMode()); // Set preference to light theme and verify night mode is disabled. - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.LIGHT); assertFalse(mGlobalNightModeStateController.isInNightMode()); @@ -172,7 +171,7 @@ setSystemNightMode(true); assertFalse(mGlobalNightModeStateController.isInNightMode()); - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.DARK); assertFalse(mGlobalNightModeStateController.isInNightMode()); @@ -183,7 +182,7 @@ mGlobalNightModeStateController.onApplicationStateChange(HAS_RUNNING_ACTIVITIES); assertTrue(mGlobalNightModeStateController.isInNightMode()); - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.SYSTEM_DEFAULT); assertTrue(mGlobalNightModeStateController.isInNightMode()); @@ -199,7 +198,7 @@ mGlobalNightModeStateController.addObserver(mObserver); // Verify that observer is called on night mode state changed from false to true. - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.DARK); assertTrue(mGlobalNightModeStateController.isInNightMode()); verify(mObserver, times(1)).onNightModeStateChanged(); @@ -215,14 +214,14 @@ verify(mObserver, times(1)).onNightModeStateChanged(); // Verify that observer is called when set to light theme. - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.LIGHT); assertFalse(mGlobalNightModeStateController.isInNightMode()); verify(mObserver, times(2)).onNightModeStateChanged(); // Verify that observer is not called after it is removed. mGlobalNightModeStateController.removeObserver(mObserver); - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.DARK); assertTrue(mGlobalNightModeStateController.isInNightMode()); verify(mObserver, times(2)).onNightModeStateChanged();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java index fd9fc4a..ef67633 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolderTest.java
@@ -16,7 +16,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.flags.FeatureUtilities; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences; /** @@ -29,7 +29,7 @@ public void tearDown() { FeatureUtilities.setNightModeAvailableForTesting(null); GlobalNightModeStateProviderHolder.resetInstanceForTesting(); - ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY); + SharedPreferencesManager.getInstance().removeKey(UI_THEME_SETTING_KEY); } @Test @@ -40,7 +40,7 @@ assertFalse(GlobalNightModeStateProviderHolder.getInstance().isInNightMode()); // Verify that night mode cannot be enabled. - ChromePreferenceManager.getInstance().writeInt( + SharedPreferencesManager.getInstance().writeInt( UI_THEME_SETTING_KEY, ThemePreferences.ThemeSetting.DARK); assertFalse(GlobalNightModeStateProviderHolder.getInstance().isInNightMode()); }
diff --git a/chrome/android/modules/test_dummy/internal/BUILD.gn b/chrome/android/modules/test_dummy/internal/BUILD.gn index 26f9543b..973480b 100644 --- a/chrome/android/modules/test_dummy/internal/BUILD.gn +++ b/chrome/android/modules/test_dummy/internal/BUILD.gn
@@ -37,7 +37,7 @@ # Test dummy native entrypoints belong in the partition. if (use_native_partitions) { - cflags = [ "-fsymbol-partition=libtest_dummy.so" ] + cflags = [ "-fsymbol-partition=test_dummy_partition" ] } }
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS index e1915cd..0ebe7f2c 100644 --- a/chrome/app/OWNERS +++ b/chrome/app/OWNERS
@@ -6,7 +6,6 @@ cpu@chromium.org grt@chromium.org -jcivelli@chromium.org rockot@google.com per-file bookmarks_strings.grdp=*
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 62e2851..6b06dc53 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -5185,7 +5185,7 @@ Touch to confirm reset </message> <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_STEP1" desc="An instruction to a user to physically unplug a security key from their computer, reinsert it, and then touch the activation button that's on the device."> - Remove your security key from your device, then reinsert and touch it. + To continue, remove your security key from your device, then reinsert and touch it </message> <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_STEP2" desc="An instruction to a user to press the activation button on their security key a second time to confirm that they wish to reset (i.e. erase) their security key (which is an external device for user authentication)."> Touch your security key again to confirm reset. All information stored on the security key, including its PIN, will be erased. @@ -5202,9 +5202,6 @@ <message name="IDS_SETTINGS_SECURITY_KEYS_RESET_NOTALLOWED" desc="A message to the user that an attempt to reset (i.e. erase) their security key (an external device for user authentication) failed because the security key refused to be reset. This is usually caused because a reset is only allowed within the first few seconds after being plugged in, so the user has to perform the operation quickly."> Can’t reset this security key. Try resetting the key immediately after inserting it. </message> - <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_TOUCH" desc="An instruction to a user to physically the activation button on their security key (which is an external device for user authentication)."> - Insert and touch your security key to create or change a PIN. - </message> <message name="IDS_SETTINGS_SECURITY_KEYS_NO_PIN" desc="A failure message shown to a user when they attempt to set a PIN on a security key that does not support PINs. PINs, in this context, are short, often numeric codes that are often used with, for example, ATM cards. Security keys are external devices used to authenticate people."> This security key doesn’t support PINs </message> @@ -5266,10 +5263,10 @@ Hide PINs </message> <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_LABEL" desc="The label for a menu item that when clicked lets the user view and erase credentials on their security key (an authentication hardware device)."> - Manage sign-in data + Sign-in data </message> <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_DESC" desc="The description for a menu item that when clicked lets the user view and erase credentials on their security key (an authentication hardware device)."> - View and delete the sign-in data stored on your security key + View and delete sign-in data stored on your security key </message> <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_DIALOG_TITLE" desc="The title of a dialog that lets users view and erase credentials on their security key (an authentication hardware device)."> Security key sign-in data @@ -5280,12 +5277,6 @@ <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_USERNAME" desc="A column heading of a table that lists credentials stored on a security key (an authentication hardware device). This column contains the user name (e.g. exampleuser@google.com) for each credential."> Username </message> - <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_TOUCH" desc="A label instructing the user to physically touch the activation button on their security key (an authentication hardware device)."> - To view sign-in data, insert and touch your security key - </message> - <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_PIN_PROMPT" desc="A label instructing the user to enter the PIN (short, often numeric codes that are often used with, for example, ATM cards) for their security key (an authentication hardware device)."> - To view sign-in data, enter the PIN for your security key. If you don’t know the PIN, you’ll need to reset the security key. - </message> <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_NO_CREDENTIALS" desc="An error message shown when a user attempts to view the credentials on their security key (an authentication hardware device) but no such credentials exist."> This security key does not have any sign-in data </message> @@ -5307,24 +5298,21 @@ <message name="IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_FAILED" desc="An error message shown when a user attempts to delete an individual credential on their security key (an authentication hardware device)."> Your sign-in data couldn't be deleted </message> + <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_SUBPAGE_LABEL" desc="The label for a menu item that when clicked lets the user view, add, rename, and delete fingerprints on their security key (an authentication hardware device)."> + Fingerprints + </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_SUBPAGE_DESCRIPTION" desc="The description for a menu item that when clicked lets the user view, add, rename, and delete fingerprints on their security key (an authentication hardware device)."> - Add, rename, and delete fingerprints saved on your device + Add and delete fingerprints saved on your security key </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_DIALOG_TITLE" desc="The title of a dialog that lets users view, add, rename, and delete fingerprints on their security key (an authentication hardware device)."> Manage fingerprints </message> - <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_TOUCH" desc="A label instructing the user to physically touch the activation button on their security key (an authentication hardware device)."> - To manage your fingerprints, insert and touch your security key. - </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_CHOOSE_NAME" desc="A label instructing the user to provide a descriptive name for a fingerprint enrolled to a security key."> Choose a name for this fingerprint </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_NAME_LABEL" desc="A label for a text input field containing a descriptive name for a fingerprint enrolled to a security key."> Name </message> - <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_PIN_PROMPT" desc="A label instructing the user to enter the PIN (short, often numeric codes that are often used with, for example, ATM cards) for their security key (an authentication hardware device)."> - To manage your fingerprints, enter the PIN for your security key. If you don’t know the PIN, you’ll need to reset the security key. - </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_NO_ENROLLMENTS" desc="A label informing the user that there are no fingerprints stored on their security key (authentication hardware device)."> Your security key has no fingerprints stored. </message> @@ -5332,9 +5320,18 @@ Fingerprints on this security key </message> <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL" desc="A label instructing the user to repeatedly touch the fingerprint sensor on their security key (authentication hardware device) to take samples for a new fingerprint."> - Keep touching your security key to save your fingerprint. + Keep touching your security key until your fingerprint is captured + </message> + <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL" desc="A label informing the user that adding a fingerprint to their security key succeeded."> + Your fingerprint was captured </message> <message name="IDS_SETTINGS_SECURITY_KEYS_NO_BIOMETRIC_ENROLLMENT" desc="An error message shown when a user attempts to use the fingerprint sensor on their security key (an authentication hardware device) but the security key is not capable of storing fingerprints, or does not have a fingerprint sensor."> Your security key can't store fingerprints </message> + <message name="IDS_SETTINGS_SECURITY_KEYS_TOUCH_TO_CONTINUE" desc="A label instructing the user to physically touch the activation button on their security key (an authentication hardware device)."> + To continue, insert and touch your security key + </message> + <message name="IDS_SETTINGS_SECURITY_KEYS_PIN_PROMPT" desc="A label instructing the user to enter the PIN (short, often numeric codes that are often used with, for example, ATM cards) for their security key (an authentication hardware device)."> + Enter the PIN for your security key. If you don’t know the PIN, you’ll need to reset the security key. + </message> </grit-part>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index c87da67..bc3b4cc 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3075,30 +3075,30 @@ #if !defined(OS_ANDROID) {"chrome-colors", flag_descriptions::kChromeColorsName, flag_descriptions::kChromeColorsDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kChromeColors)}, + FEATURE_VALUE_TYPE(ntp_features::kChromeColors)}, {"chrome-colors-custom-color-picker", flag_descriptions::kChromeColorsCustomColorPickerName, flag_descriptions::kChromeColorsCustomColorPickerDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kChromeColorsCustomColorPicker)}, + FEATURE_VALUE_TYPE(ntp_features::kChromeColorsCustomColorPicker)}, {"ntp-confirm-suggestion-removals", flag_descriptions::kNtpConfirmSuggestionRemovalsName, flag_descriptions::kNtpConfirmSuggestionRemovalsDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kConfirmNtpSuggestionRemovals)}, + FEATURE_VALUE_TYPE(ntp_features::kConfirmSuggestionRemovals)}, {"ntp-customization-menu-v2", flag_descriptions::kNtpCustomizationMenuV2Name, flag_descriptions::kNtpCustomizationMenuV2Description, kOsDesktop, - FEATURE_VALUE_TYPE(features::kNtpCustomizationMenuV2)}, + FEATURE_VALUE_TYPE(ntp_features::kCustomizationMenuV2)}, {"ntp-dismiss-promos", flag_descriptions::kNtpDismissPromosName, flag_descriptions::kNtpDismissPromosDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kDismissNtpPromos)}, + FEATURE_VALUE_TYPE(ntp_features::kDismissPromos)}, {"ntp-realbox", flag_descriptions::kNtpRealboxName, flag_descriptions::kNtpRealboxDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kNtpRealbox)}, + FEATURE_VALUE_TYPE(ntp_features::kRealbox)}, {"webui-a11y-enhancements", flag_descriptions::kWebUIA11yEnhancementsName, flag_descriptions::kWebUIA11yEnhancementsDescription, kOsDesktop,
diff --git a/chrome/browser/accessibility/DEPS b/chrome/browser/accessibility/DEPS new file mode 100644 index 0000000..4f11588 --- /dev/null +++ b/chrome/browser/accessibility/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+services/image_annotation", +]
diff --git a/chrome/browser/accessibility/accessibility_labels_service.cc b/chrome/browser/accessibility/accessibility_labels_service.cc index 4a820e7..9ed91fa2 100644 --- a/chrome/browser/accessibility/accessibility_labels_service.cc +++ b/chrome/browser/accessibility/accessibility_labels_service.cc
@@ -5,16 +5,22 @@ #include "chrome/browser/accessibility/accessibility_labels_service.h" #include "base/metrics/histogram_functions.h" +#include "base/no_destructor.h" #include "build/build_config.h" #include "chrome/browser/accessibility/accessibility_state_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" +#include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/sync_preferences/pref_service_syncable.h" +#include "components/version_info/channel.h" #include "content/public/browser/browser_accessibility_state.h" #include "content/public/common/content_features.h" +#include "google_apis/google_api_keys.h" +#include "services/data_decoder/public/cpp/data_decoder.h" +#include "services/image_annotation/image_annotation_service.h" #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -24,6 +30,41 @@ #include "chrome/browser/ui/browser_list.h" #endif +namespace { + +// Returns the Chrome Google API key for the channel of this build. +std::string APIKeyForChannel() { + if (chrome::GetChannel() == version_info::Channel::STABLE) + return google_apis::GetAPIKey(); + return google_apis::GetNonStableAPIKey(); +} + +AccessibilityLabelsService::ImageAnnotatorBinder& +GetImageAnnotatorBinderOverride() { + static base::NoDestructor<AccessibilityLabelsService::ImageAnnotatorBinder> + binder; + return *binder; +} + +class ImageAnnotatorClient : public image_annotation::Annotator::Client { + public: + ImageAnnotatorClient() = default; + ~ImageAnnotatorClient() override = default; + + // image_annotation::Annotator::Client implementation: + void BindJsonParser(mojo::PendingReceiver<data_decoder::mojom::JsonParser> + receiver) override { + data_decoder_.GetService()->BindJsonParser(std::move(receiver)); + } + + private: + data_decoder::DataDecoder data_decoder_; + + DISALLOW_COPY_AND_ASSIGN(ImageAnnotatorClient); +}; + +} // namespace + AccessibilityLabelsService::~AccessibilityLabelsService() {} // static @@ -109,6 +150,29 @@ #endif } +void AccessibilityLabelsService::BindImageAnnotator( + mojo::PendingReceiver<image_annotation::mojom::Annotator> receiver) { + if (!remote_service_) { + auto service_receiver = remote_service_.BindNewPipeAndPassReceiver(); + auto& binder = GetImageAnnotatorBinderOverride(); + if (binder) { + binder.Run(std::move(service_receiver)); + } else { + service_ = std::make_unique<image_annotation::ImageAnnotationService>( + std::move(service_receiver), APIKeyForChannel(), + profile_->GetURLLoaderFactory(), + std::make_unique<ImageAnnotatorClient>()); + } + } + + remote_service_->BindAnnotator(std::move(receiver)); +} + +void AccessibilityLabelsService::OverrideImageAnnotatorBinderForTesting( + ImageAnnotatorBinder binder) { + GetImageAnnotatorBinderOverride() = std::move(binder); +} + void AccessibilityLabelsService::OnImageLabelsEnabledChanged() { // TODO(dmazzoni) Implement for Android, which doesn't support // AllTabContentses(). crbug.com/905419
diff --git a/chrome/browser/accessibility/accessibility_labels_service.h b/chrome/browser/accessibility/accessibility_labels_service.h index dfb0b174..7ceb9f1 100644 --- a/chrome/browser/accessibility/accessibility_labels_service.h +++ b/chrome/browser/accessibility/accessibility_labels_service.h
@@ -8,10 +8,17 @@ #include "base/memory/weak_ptr.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/image_annotation/public/mojom/image_annotation.mojom.h" #include "ui/accessibility/ax_mode.h" class Profile; +namespace image_annotation { +class ImageAnnotationService; +} + namespace user_prefs { class PrefRegistrySyncable; } @@ -35,6 +42,17 @@ void EnableLabelsServiceOnce(); + // Routes an Annotator interface receiver to the Image Annotation service for + // binding. + void BindImageAnnotator( + mojo::PendingReceiver<image_annotation::mojom::Annotator> receiver); + + // Allows tests to override how this object binds a connection to a remote + // ImageAnnotationService. + using ImageAnnotatorBinder = base::RepeatingCallback<void( + mojo::PendingReceiver<image_annotation::mojom::ImageAnnotationService>)>; + void OverrideImageAnnotatorBinderForTesting(ImageAnnotatorBinder binder); + private: friend class AccessibilityLabelsServiceFactory; @@ -51,6 +69,10 @@ PrefChangeRegistrar pref_change_registrar_; + // Implementation of and remote connection to the Image Annotation service. + std::unique_ptr<image_annotation::ImageAnnotationService> service_; + mojo::Remote<image_annotation::mojom::ImageAnnotationService> remote_service_; + base::WeakPtrFactory<AccessibilityLabelsService> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AccessibilityLabelsService);
diff --git a/chrome/browser/accessibility/image_annotation_browsertest.cc b/chrome/browser/accessibility/image_annotation_browsertest.cc index e3ce5e3..fc03b62 100644 --- a/chrome/browser/accessibility/image_annotation_browsertest.cc +++ b/chrome/browser/accessibility/image_annotation_browsertest.cc
@@ -8,8 +8,9 @@ #include "base/strings/string_util.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" +#include "chrome/browser/accessibility/accessibility_labels_service.h" +#include "chrome/browser/accessibility/accessibility_labels_service_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_impl.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" @@ -207,8 +208,9 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - ProfileImpl::OverrideImageAnnotationServiceBinderForTesting( - base::BindRepeating(&BindImageAnnotatorService)); + AccessibilityLabelsServiceFactory::GetForProfile(browser()->profile()) + ->OverrideImageAnnotatorBinderForTesting( + base::BindRepeating(&BindImageAnnotatorService)); ui::AXMode mode = ui::kAXModeComplete; mode.set_mode(ui::AXMode::kLabelImages, true); @@ -218,8 +220,8 @@ } void TearDownOnMainThread() override { - ProfileImpl::OverrideImageAnnotationServiceBinderForTesting( - base::NullCallback()); + AccessibilityLabelsServiceFactory::GetForProfile(browser()->profile()) + ->OverrideImageAnnotatorBinderForTesting(base::NullCallback()); InProcessBrowserTest::TearDownOnMainThread(); }
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index c8492e9f..18779202 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -504,7 +504,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kRevampedContextMenu{"RevampedContextMenu", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kScrollToExpandPaymentHandler{ "ScrollToExpandPaymentHandler", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/vr/ui_module_factory.cc b/chrome/browser/android/vr/ui_module_factory.cc index 61e14b5..5efa5a6 100644 --- a/chrome/browser/android/vr/ui_module_factory.cc +++ b/chrome/browser/android/vr/ui_module_factory.cc
@@ -28,8 +28,26 @@ // Do not dlclose() the library. Doing so causes issues with cardboard on // Android M. It's not clear whether there is a use-after-free in VR code, or // a linker or system issue. See https://crbug.com/994029. - void* ui_library_handle = - base::android::BundleUtils::DlOpenModuleLibraryPartition("vr"); + + // TODO(https://crbug.com/1019853): When all VR native code moves into the + // feature module, this factory will completely disappear. In the meantime, + // make it tolerant of two different variants of the VR lib (one for Chrome, + // one for Monochrome). + const std::vector<const std::string> library_name_possibilities = { + "monochrome_vr", + "chrome_vr", + }; + + void* ui_library_handle = nullptr; + const std::string partition_name = "vr"; + for (const auto& library_name : library_name_possibilities) { + ui_library_handle = + base::android::BundleUtils::DlOpenModuleLibraryPartition( + library_name, partition_name); + if (ui_library_handle != nullptr) { + break; + } + } DCHECK(ui_library_handle != nullptr) << "Could not open VR UI library:" << dlerror();
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 d6fb7ecd..d747358 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
@@ -21,6 +21,7 @@ #include "base/mac/foundation_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/macros.h" +#include "base/stl_util.h" #include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h" #include "chrome/browser/apps/app_shim/app_shim_host_mac.h" #include "chrome/browser/apps/app_shim/app_shim_listener.h" @@ -522,21 +523,10 @@ const std::string& app_id = bootstrap->GetAppId(); DCHECK(crx_file::id_util::IdIsValid(app_id)); - // TODO(https://crbug.com/982024): If no profile path is specified by the - // bootstrap, then load an appropriate profile. - base::FilePath profile_path = bootstrap->GetProfilePath(); - - if (delegate_->IsProfileLockedForPath(profile_path)) { - LOG(WARNING) << "Requested profile is locked. Showing User Manager."; - bootstrap->OnFailedToConnectToHost(APP_SHIM_LAUNCH_PROFILE_LOCKED); - delegate_->LaunchUserManager(); - return; - } - - LoadProfileAndApp( - profile_path, app_id, + GetProfilesForAppAsync( + app_id, base::BindOnce( - &ExtensionAppShimHandler::OnShimProcessConnectedAndAppLoaded, + &ExtensionAppShimHandler::OnShimProcessConnectedAndProfilesRetrieved, weak_factory_.GetWeakPtr(), std::move(bootstrap))); } @@ -630,6 +620,63 @@ std::move(callback).Run(profile, extension); } +base::FilePath ExtensionAppShimHandler::SelectProfileForApp( + const std::string& app_id, + const base::FilePath& specified_profile_path, + const std::vector<base::FilePath>& profile_paths) const { + // If the specified profile path is valid, and the app is installed for that + // profile, then use the specified profile. + if (!specified_profile_path.empty()) { + if (base::Contains(profile_paths, specified_profile_path)) + return specified_profile_path; + } + + // If the app is active for a profile, use the profile for which the app + // is active. + auto found_app = apps_.find(app_id); + if (found_app != apps_.end()) { + AppState* app_state = found_app->second.get(); + DCHECK(app_state); + if (!app_state->profiles.empty()) { + Profile* active_profile = app_state->profiles.begin()->first; + return active_profile->GetPath(); + } + } + + // Otherwise, return the first profile. This assumes that |profile_paths| + // are sorted in most-recently-used order. + return profile_paths.front(); +} + +void ExtensionAppShimHandler::OnShimProcessConnectedAndProfilesRetrieved( + std::unique_ptr<AppShimHostBootstrap> bootstrap, + const std::vector<base::FilePath>& profile_paths) { + // If the app is installed for no profiles, quit. + if (profile_paths.empty()) { + LOG(ERROR) << "App " << bootstrap->GetAppId() + << " installed for no profiles."; + bootstrap->OnFailedToConnectToHost(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND); + return; + } + + std::string app_id = bootstrap->GetAppId(); + base::FilePath profile_path = + SelectProfileForApp(app_id, bootstrap->GetProfilePath(), profile_paths); + + if (delegate_->IsProfileLockedForPath(profile_path)) { + LOG(WARNING) << "Requested profile is locked. Showing User Manager."; + bootstrap->OnFailedToConnectToHost(APP_SHIM_LAUNCH_PROFILE_LOCKED); + delegate_->LaunchUserManager(); + return; + } + + LoadProfileAndApp( + profile_path, app_id, + base::BindOnce( + &ExtensionAppShimHandler::OnShimProcessConnectedAndAppLoaded, + weak_factory_.GetWeakPtr(), std::move(bootstrap))); +} + void ExtensionAppShimHandler::OnShimProcessConnectedAndAppLoaded( std::unique_ptr<AppShimHostBootstrap> bootstrap, Profile* profile,
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 cd60953..ac36fa72 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
@@ -217,7 +217,22 @@ // Close one specified app. void CloseShimForApp(Profile* profile, const std::string& app_id); - // Continuation of OnShimProcessConnected, once the profile has loaded. + // Return the profile that should be opened for |app_id|, preferring + // |specified_profile_path| if is valid, otherwise prefering the most recently + // used of |profile_paths|. + base::FilePath SelectProfileForApp( + const std::string& app_id, + const base::FilePath& specified_profile_path, + const std::vector<base::FilePath>& profile_paths) const; + + // Continuation of OnShimProcessConnected, once the query for all profiles + // with the app installed has returned.profiles + void OnShimProcessConnectedAndProfilesRetrieved( + std::unique_ptr<AppShimHostBootstrap> bootstrap, + const std::vector<base::FilePath>& profiles); + + // Continuation of OnShimProcessConnectedAndProfilesRetrieved, once the + // decided profile has loaded. void OnShimProcessConnectedAndAppLoaded( std::unique_ptr<AppShimHostBootstrap> bootstrap, Profile* profile,
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 c00ed4c..fafa707 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
@@ -178,6 +178,7 @@ void SetProfileMenuItems( std::vector<chrome::mojom::ProfileMenuItemPtr> new_profile_menu_items) { new_profile_menu_items_ = std::move(new_profile_menu_items); + OnAvatarMenuChanged(nullptr); } void UpdateProfileMenuItems() override { profile_menu_items_.clear(); @@ -325,6 +326,14 @@ profile_path_a_, kTestAppIdA, true /* is_from_bookmark */, &bootstrap_aa_result_)) ->GetWeakPtr(); + bootstrap_ba_ = (new TestingAppShimHostBootstrap( + profile_path_b_, kTestAppIdA, + true /* is_from_bookmark */, &bootstrap_ba_result_)) + ->GetWeakPtr(); + bootstrap_xa_ = (new TestingAppShimHostBootstrap( + base::FilePath(), kTestAppIdA, + true /* is_from_bookmark */, &bootstrap_xa_result_)) + ->GetWeakPtr(); bootstrap_ab_ = (new TestingAppShimHostBootstrap( profile_path_a_, kTestAppIdB, false /* is_from_bookmark */, &bootstrap_ab_result_)) @@ -375,6 +384,19 @@ .SetID(kTestAppIdB) .Build(); + { + auto item_a = chrome::mojom::ProfileMenuItem::New(); + item_a->profile_path = profile_path_a_; + item_a->menu_index = 0; + auto item_b = chrome::mojom::ProfileMenuItem::New(); + item_b->profile_path = profile_path_b_; + item_b->menu_index = 1; + std::vector<chrome::mojom::ProfileMenuItemPtr> items; + items.push_back(std::move(item_a)); + items.push_back(std::move(item_b)); + handler_->SetProfileMenuItems(std::move(items)); + } + EXPECT_CALL(*delegate_, IsProfileLockedForPath(profile_path_a_)) .WillRepeatedly(Return(false)); EXPECT_CALL(*delegate_, ProfileForPath(profile_path_a_)) @@ -411,6 +433,8 @@ // deleted yet. Note that this must be done after the profiles and hosts // have been destroyed (because they may now own the bootstraps). delete bootstrap_aa_.get(); + delete bootstrap_ba_.get(); + delete bootstrap_xa_.get(); delete bootstrap_ab_.get(); delete bootstrap_bb_.get(); delete bootstrap_aa_duplicate_.get(); @@ -426,6 +450,7 @@ if (host) delegate_->SetHostForCreate(std::move(host)); bootstrap->DoTestLaunch(launch_type, files); + EXPECT_TRUE(delegate_->RunGetProfilesForAppCallback()); } void NormalLaunch(base::WeakPtr<TestingAppShimHostBootstrap> bootstrap, @@ -471,12 +496,16 @@ TestingProfile profile_b_; base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_aa_; + base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_ba_; + base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_xa_; base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_ab_; base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_bb_; base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_aa_duplicate_; base::WeakPtr<TestingAppShimHostBootstrap> bootstrap_aa_thethird_; base::Optional<apps::AppShimLaunchResult> bootstrap_aa_result_; + base::Optional<apps::AppShimLaunchResult> bootstrap_ba_result_; + base::Optional<apps::AppShimLaunchResult> bootstrap_xa_result_; base::Optional<apps::AppShimLaunchResult> bootstrap_ab_result_; base::Optional<apps::AppShimLaunchResult> bootstrap_bb_result_; base::Optional<apps::AppShimLaunchResult> bootstrap_aa_duplicate_result_; @@ -973,6 +1002,7 @@ delegate_->SetHostForCreate(std::move(host_aa_unique_)); EXPECT_CALL(*delegate_, DoLaunchShim(&profile_a_, extension_a_.get(), false)); handler_->OnAppActivated(&profile_a_, kTestAppIdA); + EXPECT_TRUE(delegate_->RunGetProfilesForAppCallback()); EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA)); // Launch the shim. @@ -984,7 +1014,6 @@ const auto& menu_items = host_aa_->test_app_shim_->profile_menu_items_; // We should have no menu items, because there is only one installed profile. - EXPECT_TRUE(delegate_->RunGetProfilesForAppCallback()); EXPECT_FALSE(delegate_->RunGetProfilesForAppCallback()); EXPECT_TRUE(menu_items.empty()); @@ -1004,7 +1033,6 @@ items.push_back(std::move(item_b)); handler_->SetProfileMenuItems(std::move(items)); } - handler_->OnAvatarMenuChanged(nullptr); EXPECT_TRUE(delegate_->RunGetProfilesForAppCallback()); EXPECT_FALSE(delegate_->RunGetProfilesForAppCallback()); @@ -1020,4 +1048,59 @@ EXPECT_FALSE(delegate_->RunGetProfilesForAppCallback()); } +TEST_F(ExtensionAppShimHandlerTest, FindProfileFromBadProfile) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAppShimMultiProfile}, + /*disabled_features=*/{}); + + // Set this app to be installed for profile A. + { + auto item_a = chrome::mojom::ProfileMenuItem::New(); + item_a->profile_path = profile_path_a_; + item_a->menu_index = 999; + + std::vector<chrome::mojom::ProfileMenuItemPtr> items; + items.push_back(std::move(item_a)); + handler_->SetProfileMenuItems(std::move(items)); + } + + // Launch the shim requesting profile B. + delegate_->SetHostForCreate(std::move(host_aa_unique_)); + EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, extension_a_.get(), _)) + .Times(1); + EXPECT_CALL(*delegate_, LaunchApp(&profile_b_, extension_a_.get(), _)) + .Times(0); + NormalLaunch(bootstrap_ba_, nullptr); + EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *bootstrap_ba_result_); + EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA)); +} + +TEST_F(ExtensionAppShimHandlerTest, FindProfileFromNoProfile) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAppShimMultiProfile}, + /*disabled_features=*/{}); + + // Set this app to be installed for profile A. + { + auto item_a = chrome::mojom::ProfileMenuItem::New(); + item_a->profile_path = profile_path_a_; + item_a->menu_index = 999; + + std::vector<chrome::mojom::ProfileMenuItemPtr> items; + items.push_back(std::move(item_a)); + handler_->SetProfileMenuItems(std::move(items)); + } + + // Launch the shim without specifying a profile. + delegate_->SetHostForCreate(std::move(host_aa_unique_)); + EXPECT_CALL(*delegate_, LaunchApp(&profile_a_, extension_a_.get(), _)) + .Times(1); + EXPECT_CALL(*delegate_, LaunchApp(&profile_b_, extension_a_.get(), _)) + .Times(0); + NormalLaunch(bootstrap_xa_, nullptr); + EXPECT_EQ(APP_SHIM_LAUNCH_SUCCESS, *bootstrap_xa_result_); + EXPECT_EQ(host_aa_.get(), handler_->FindHost(&profile_a_, kTestAppIdA)); +} } // namespace apps
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index a8bc3fb..64fe2dc 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -6,6 +6,8 @@ #include "base/feature_list.h" #include "build/build_config.h" +#include "chrome/browser/accessibility/accessibility_labels_service.h" +#include "chrome/browser/accessibility/accessibility_labels_service_factory.h" #include "chrome/browser/content_settings/content_settings_manager_impl.h" #include "chrome/browser/navigation_predictor/navigation_predictor.h" #include "chrome/browser/profiles/profile.h" @@ -36,13 +38,14 @@ namespace chrome { namespace internal { -// Forward image Annotator requests to the profile's ImageAnnotationService. +// Forward image Annotator requests to the profile's AccessibilityLabelsService. void BindImageAnnotator( content::RenderFrameHost* const frame_host, mojo::PendingReceiver<image_annotation::mojom::Annotator> receiver) { - Profile::FromBrowserContext(frame_host->GetProcess()->GetBrowserContext()) - ->GetImageAnnotationService() - ->BindAnnotator(std::move(receiver)); + AccessibilityLabelsServiceFactory::GetForProfile( + Profile::FromBrowserContext( + frame_host->GetProcess()->GetBrowserContext())) + ->BindImageAnnotator(std::move(receiver)); } #if defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index 5cc1649..3d8ee32 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -570,10 +570,11 @@ // repeatedly until the window is selected. SendKeyPress(ui::VKEY_TAB); std::string utterance = speech_monitor_.GetNextUtterance(); - if (base::MatchPattern(utterance, "Chrom* - about:blank")) + if (base::MatchPattern(utterance, "Chrom*")) break; } - EXPECT_EQ("Button", speech_monitor_.GetNextUtterance()); + EXPECT_EQ("about:blank,", speech_monitor_.GetNextUtterance()); + EXPECT_EQ("window", speech_monitor_.GetNextUtterance()); } #if defined(MEMORY_SANITIZER) || defined(OS_CHROMEOS)
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc index 4b9ac93..3babe68 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <set> +#include "base/base64.h" #include "base/bind.h" #include "base/callback.h" #include "base/json/json_reader.h" @@ -53,10 +54,15 @@ constexpr char kKeyChrome[] = "chrome"; constexpr char kKeyDuration[] = "duration"; constexpr char kKeyGlobalEvents[] = "global_events"; +constexpr char kKeyIcon[] = "icon"; +constexpr char kKeyInformation[] = "information"; constexpr char kKeyInput[] = "input"; constexpr char kKeyViews[] = "views"; +constexpr char kKeyPlatform[] = "platform"; constexpr char kKeySystem[] = "system"; constexpr char kKeyTaskId[] = "task_id"; +constexpr char kKeyTimestamp[] = "timestamp"; +constexpr char kKeyTitle[] = "title"; constexpr char kAcquireBufferQuery[] = "android:onMessageReceived/android:handleMessageInvalidate/" @@ -1520,6 +1526,20 @@ return true; } +bool ReadDuration(const base::Value* root, uint32_t* duration) { + const base::Value* duration_value = root->FindKey(kKeyDuration); + if (!duration_value || + (!duration_value->is_double() && !duration_value->is_int())) { + return false; + } + + *duration = duration_value->GetDouble(); + if (*duration < 0) + return false; + + return true; +} + } // namespace ArcTracingGraphicsModel::BufferEvent::BufferEvent(BufferEventType type, @@ -1759,6 +1779,10 @@ chrome_buffer_id_to_task_id_.clear(); system_model_.Reset(); duration_ = 0; + app_title_ = std::string(); + app_icon_png_.clear(); + platform_ = std::string(); + timestamp_ = base::Time(); } void ArcTracingGraphicsModel::VsyncTrim() { @@ -1827,8 +1851,23 @@ // System. root->SetKey(kKeySystem, system_model_.Serialize()); - // Duration. - root->SetKey(kKeyDuration, base::Value(static_cast<double>(duration_))); + // Information + base::DictionaryValue information; + information.SetKey(kKeyDuration, base::Value(static_cast<double>(duration_))); + if (!platform_.empty()) + information.SetKey(kKeyPlatform, base::Value(platform_)); + if (!timestamp_.is_null()) + information.SetKey(kKeyTimestamp, base::Value(timestamp_.ToJsTime())); + if (!app_title_.empty()) + information.SetKey(kKeyTitle, base::Value(app_title_)); + if (!app_icon_png_.empty()) { + const std::string png_data_as_string( + reinterpret_cast<const char*>(&app_icon_png_[0]), app_icon_png_.size()); + std::string icon_content; + base::Base64Encode(png_data_as_string, &icon_content); + information.SetKey(kKeyIcon, base::Value(icon_content)); + } + root->SetKey(kKeyInformation, std::move(information)); return root; } @@ -1891,13 +1930,37 @@ if (!system_model_.Load(root.FindKey(kKeySystem))) return false; - const base::Value* duration = root.FindKey(kKeyDuration); - if (!duration || (!duration->is_double() && !duration->is_int())) - return false; + const base::Value* informaton = + root.FindKeyOfType(kKeyInformation, base::Value::Type::DICTIONARY); + if (informaton) { + if (!ReadDuration(informaton, &duration_)) + return false; - duration_ = duration->GetDouble(); - if (duration_ < 0) - return false; + const base::Value* platform_value = + informaton->FindKeyOfType(kKeyPlatform, base::Value::Type::STRING); + if (platform_value) + platform_ = platform_value->GetString(); + const base::Value* title_value = + informaton->FindKeyOfType(kKeyTitle, base::Value::Type::STRING); + if (title_value) + app_title_ = title_value->GetString(); + const base::Value* icon_value = + informaton->FindKeyOfType(kKeyIcon, base::Value::Type::STRING); + if (icon_value) { + std::string icon_content; + if (!base::Base64Decode(icon_value->GetString(), &icon_content)) + return false; + app_icon_png_ = + std::vector<unsigned char>(icon_content.begin(), icon_content.end()); + } + const base::Value* timestamp_value = + informaton->FindKeyOfType(kKeyTimestamp, base::Value::Type::DOUBLE); + if (timestamp_value) + timestamp_ = base::Time::FromJsTime(timestamp_value->GetDouble()); + } else { + if (!ReadDuration(&root, &duration_)) + return false; + } return true; }
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h index 60f6423..fd13491 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_graphics_model.h
@@ -11,6 +11,7 @@ #include <vector> #include "base/macros.h" +#include "base/time/time.h" #include "base/values.h" #include "chrome/browser/chromeos/arc/tracing/arc_system_model.h" @@ -169,6 +170,12 @@ bool LoadFromValue(const base::DictionaryValue& root); uint64_t duration() const { return duration_; } + base::Time timestamp() const { return timestamp_; } + const std::string& app_title() const { return app_title_; } + const std::vector<unsigned char>& app_icon_png() const { + return app_icon_png_; + } + const std::string& platform() const { return platform_; } const ViewMap& view_buffers() const { return view_buffers_; } @@ -183,6 +190,13 @@ ArcSystemModel& system_model() { return system_model_; } const ArcSystemModel& system_model() const { return system_model_; } + void set_timestamp(base::Time timestamp) { timestamp_ = timestamp; } + void set_app_title(const std::string& app_title) { app_title_ = app_title; } + void set_app_icon_png(const std::vector<unsigned char>& app_icon_png) { + app_icon_png_ = app_icon_png; + } + void set_platform(const std::string& platform) { platform_ = platform; } + void set_skip_structure_validation() { skip_structure_validation_ = true; } private: @@ -209,6 +223,15 @@ EventsContainer input_; // Total duration of this model. uint32_t duration_ = 0; + // Title of the traced app. + std::string app_title_; + // PNG content of traced app. + std::vector<unsigned char> app_icon_png_; + // Tested platform, it includes board, and versions. + std::string platform_; + // Timestamp of tracing. + base::Time timestamp_; + // Map Chrome buffer id to task id. std::map<std::string, int> chrome_buffer_id_to_task_id_; // CPU event model.
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc index d048829..9bf57dcf 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_model_unittest.cc
@@ -127,6 +127,10 @@ EXPECT_EQ(model1.view_buffers(), model2.view_buffers()); EXPECT_EQ(model1.system_model(), model2.system_model()); EXPECT_EQ(model1.duration(), model2.duration()); + EXPECT_EQ(model1.app_title(), model2.app_title()); + EXPECT_EQ(model1.app_icon_png(), model2.app_icon_png()); + EXPECT_EQ(model1.timestamp(), model2.timestamp()); + EXPECT_EQ(model1.platform(), model2.platform()); } } // namespace @@ -512,6 +516,13 @@ std::unique_ptr<ArcTracingGraphicsModel> model = LoadGraphicsModel("gm_good.json"); ASSERT_TRUE(model); + EXPECT_EQ("CrOS 12642.0.0 (Official Build) dev-channel eve", + model->platform()); + EXPECT_EQ("Play Store", model->app_title()); + EXPECT_FALSE(model->app_icon_png().empty()); + EXPECT_EQ(base::Time::FromJsTime(1572898642036L), model->timestamp()); + EXPECT_EQ(1000U, model->duration()); + ArcTracingGraphicsModel test_model; EXPECT_TRUE(test_model.LoadFromJson(model->SerializeToJson())); EnsureGraphicsModelsEqual(*model, test_model);
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc index 8f61bb5..9ef227f 100644 --- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc +++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -551,7 +551,7 @@ } // Flaky in debug builds - crbug.com/1021191 -#if defined(DEBUG) +#if !defined(NDEBUG) #define MAYBE_TestActiveDirectoryEnrollment_Success \ DISABLED_TestActiveDirectoryEnrollment_Success #else @@ -590,7 +590,7 @@ } // Flaky in debug builds - crbug.com/1021191 -#if defined(DEBUG) +#if !defined(NDEBUG) #define MAYBE_TestActiveDirectoryEnrollment_DistinguishedName \ DISABLED_TestActiveDirectoryEnrollment_DistinguishedName #else @@ -631,7 +631,7 @@ } // Flaky in debug builds - crbug.com/1021191 -#if defined(DEBUG) +#if !defined(NDEBUG) #define MAYBE_TestActiveDirectoryEnrollment_UIErrors \ DISABLED_TestActiveDirectoryEnrollment_UIErrors #else @@ -686,7 +686,7 @@ } // Flaky in debug builds - crbug.com/1021191 -#if defined(DEBUG) +#if !defined(NDEBUG) #define MAYBE_TestActiveDirectoryEnrollment_ErrorCard \ DISABLED_TestActiveDirectoryEnrollment_ErrorCard #else @@ -716,7 +716,7 @@ } // Flaky in debug builds - crbug.com/1021191 -#if defined(DEBUG) +#if !defined(NDEBUG) #define MAYBE_TestActiveDirectoryEnrollment_Streamline \ DISABLED_TestActiveDirectoryEnrollment_Streamline #else
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 6034b62..f078c300 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -466,10 +466,16 @@ DISALLOW_COPY_AND_ASSIGN(SamlTest); }; +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_SamlUI DISABLED_SamlUI +#else +#define MAYBE_SamlUI SamlUI +#endif // Tests that signin frame should display the SAML notice and the 'back' button // when SAML IdP page is loaded. And the 'back' button goes back to gaia on // clicking. -IN_PROC_BROWSER_TEST_F(SamlTest, SamlUI) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_SamlUI) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -501,8 +507,14 @@ test::OobeJS().ExpectHiddenPath({"gaia-signin", "saml-notice-container"}); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_CredentialPassingAPI DISABLED_CredentialPassingAPI +#else +#define MAYBE_CredentialPassingAPI CredentialPassingAPI +#endif // Tests the sign-in flow when the credentials passing API is used. -IN_PROC_BROWSER_TEST_F(SamlTest, CredentialPassingAPI) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_CredentialPassingAPI) { base::HistogramTester histogram_tester; fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html"); fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html"); @@ -534,8 +546,14 @@ histogram_tester.ExpectUniqueSample("ChromeOS.SAML.APILogin", 1, 1); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_ScrapedSingle DISABLED_ScrapedSingle +#else +#define MAYBE_ScrapedSingle ScrapedSingle +#endif // Tests the single password scraped flow. -IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedSingle) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_ScrapedSingle) { base::HistogramTester histogram_tester; fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -572,8 +590,14 @@ 1, 1); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_ScrapedDynamic DISABLED_ScrapedDynamic +#else +#define MAYBE_ScrapedDynamic ScrapedDynamic +#endif // Tests password scraping from a dynamically created password field. -IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedDynamic) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_ScrapedDynamic) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -599,8 +623,14 @@ kFirstSAMLUserGaiaId))); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_ScrapedMultiple DISABLED_ScrapedMultiple +#else +#define MAYBE_ScrapedMultiple ScrapedMultiple +#endif // Tests the multiple password scraped flow. -IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedMultiple) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_ScrapedMultiple) { base::HistogramTester histogram_tester; fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html"); @@ -630,8 +660,14 @@ 2, 1); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_ScrapedNone DISABLED_ScrapedNone +#else +#define MAYBE_ScrapedNone ScrapedNone +#endif // Tests the no password scraped flow. -IN_PROC_BROWSER_TEST_F(SamlTest, ScrapedNone) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_ScrapedNone) { base::HistogramTester histogram_tester; fake_saml_idp()->SetLoginHTMLTemplate("saml_login_no_passwords.html"); @@ -662,10 +698,17 @@ 0, 1); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_UseAutenticatedUserEmailAddress \ + DISABLED_UseAutenticatedUserEmailAddress +#else +#define MAYBE_UseAutenticatedUserEmailAddress UseAutenticatedUserEmailAddress +#endif // Types |bob@corp.example.com| into the GAIA login form but then authenticates // as |alice@corp.example.com| via SAML. Verifies that the logged-in user is // correctly identified as Alice. -IN_PROC_BROWSER_TEST_F(SamlTest, UseAutenticatedUserEmailAddress) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_UseAutenticatedUserEmailAddress) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); // Type |bob@corp.example.com| into the GAIA login form. StartSamlAndWaitForIdpPageLoad(kSecondSAMLUserEmail); @@ -685,9 +728,18 @@ EXPECT_EQ(kFirstSAMLUserEmail, user->GetAccountId().GetUserEmail()); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_FailToRetrieveAutenticatedUserEmailAddress \ + DISABLED_FailToRetrieveAutenticatedUserEmailAddress +#else +#define MAYBE_FailToRetrieveAutenticatedUserEmailAddress \ + FailToRetrieveAutenticatedUserEmailAddress +#endif // Verifies that if the authenticated user's e-mail address cannot be retrieved, // an error message is shown. -IN_PROC_BROWSER_TEST_F(SamlTest, FailToRetrieveAutenticatedUserEmailAddress) { +IN_PROC_BROWSER_TEST_F(SamlTest, + MAYBE_FailToRetrieveAutenticatedUserEmailAddress) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -701,9 +753,15 @@ WaitForAndGetFatalErrorMessage()); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_PasswordConfirmFlow DISABLED_PasswordConfirmFlow +#else +#define MAYBE_PasswordConfirmFlow PasswordConfirmFlow +#endif // Tests the password confirm flow when more than one password is scraped: show // error on the first failure and fatal error on the second failure. -IN_PROC_BROWSER_TEST_F(SamlTest, PasswordConfirmFlow) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_PasswordConfirmFlow) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login_two_passwords.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -734,10 +792,16 @@ WaitForAndGetFatalErrorMessage()); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_NoticeUpdatedOnRedirect DISABLED_NoticeUpdatedOnRedirect +#else +#define MAYBE_NoticeUpdatedOnRedirect NoticeUpdatedOnRedirect +#endif // Verifies that when the login flow redirects from one host to another, the // notice shown to the user is updated. This guards against regressions of // http://crbug.com/447818. -IN_PROC_BROWSER_TEST_F(SamlTest, NoticeUpdatedOnRedirect) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_NoticeUpdatedOnRedirect) { // Start another https server at |kAdditionalIdPHost|. HTTPSForwarder saml_https_forwarder_2; ASSERT_TRUE(saml_https_forwarder_2.Initialize( @@ -784,9 +848,15 @@ test::OobeJS().ExpectVisiblePath({"gaia-signin", "saml-notice-container"}); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_HTTPRedirectDisallowed DISABLED_HTTPRedirectDisallowed +#else +#define MAYBE_HTTPRedirectDisallowed HTTPRedirectDisallowed +#endif // Verifies that when GAIA attempts to redirect to a SAML IdP served over http, // not https, the redirect is blocked and an error message is shown. -IN_PROC_BROWSER_TEST_F(SamlTest, HTTPRedirectDisallowed) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_HTTPRedirectDisallowed) { fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); WaitForSigninScreen(); @@ -801,10 +871,16 @@ WaitForAndGetFatalErrorMessage()); } +// Flakily times out in debug builds. crbug.com/1021594 +#if !defined(NDEBUG) +#define MAYBE_MetaRefreshToHTTPDisallowed DISABLED_MetaRefreshToHTTPDisallowed +#else +#define MAYBE_MetaRefreshToHTTPDisallowed MetaRefreshToHTTPDisallowed +#endif // Verifies that when GAIA attempts to redirect to a page served over http, not // https, via an HTML meta refresh, the redirect is blocked and an error message // is shown. This guards against regressions of http://crbug.com/359515. -IN_PROC_BROWSER_TEST_F(SamlTest, MetaRefreshToHTTPDisallowed) { +IN_PROC_BROWSER_TEST_F(SamlTest, MAYBE_MetaRefreshToHTTPDisallowed) { const GURL url = embedded_test_server()->base_url().Resolve("/SSO"); fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html"); fake_saml_idp()->SetRefreshURL(url);
diff --git a/chrome/browser/enterprise_reporting/profile_report_generator.cc b/chrome/browser/enterprise_reporting/profile_report_generator.cc index 50db0b7..270a3ce5 100644 --- a/chrome/browser/enterprise_reporting/profile_report_generator.cc +++ b/chrome/browser/enterprise_reporting/profile_report_generator.cc
@@ -14,6 +14,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -31,6 +33,10 @@ policies_enabled_ = enabled; } +void ProfileReportGenerator::set_extension_request_enabled(bool enabled) { + extension_request_enabled_ = enabled; +} + std::unique_ptr<em::ChromeUserProfileInfo> ProfileReportGenerator::MaybeGenerate(const base::FilePath& path, const std::string& name) { @@ -47,6 +53,7 @@ GetSigninUserInfo(); GetExtensionInfo(); + GetExtensionRequest(); if (policies_enabled_) { // TODO(crbug.com/983151): Upload policy error as their IDs. @@ -91,5 +98,14 @@ AppendMachineLevelUserCloudPolicyFetchTimestamp(report_.get()); } +void ProfileReportGenerator::GetExtensionRequest() { + if (!extension_request_enabled_) + return; + const auto pending_list = profile_->GetPrefs() + ->GetList(prefs::kCloudExtensionRequestIds) + ->GetList(); + for (const base::Value& pending_request : pending_list) + report_->add_extension_requests()->set_id(pending_request.GetString()); +} } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/profile_report_generator.h b/chrome/browser/enterprise_reporting/profile_report_generator.h index 330427db..eb12ab27 100644 --- a/chrome/browser/enterprise_reporting/profile_report_generator.h +++ b/chrome/browser/enterprise_reporting/profile_report_generator.h
@@ -33,6 +33,7 @@ void set_extensions_enabled(bool enabled); void set_policies_enabled(bool enabled); + void set_extension_request_enabled(bool enabled); // Generates report for Profile if it's activated. Returns the report with // |callback| once it's ready. The report is null if it can't be generated. @@ -48,6 +49,7 @@ void GetChromePolicyInfo(); void GetExtensionPolicyInfo(); void GetPolicyFetchTimestampInfo(); + void GetExtensionRequest(); private: Profile* profile_; @@ -55,6 +57,7 @@ bool extensions_enabled_ = true; bool policies_enabled_ = true; + bool extension_request_enabled_ = false; std::unique_ptr<em::ChromeUserProfileInfo> report_ = nullptr;
diff --git a/chrome/browser/enterprise_reporting/profile_report_generator_unittest.cc b/chrome/browser/enterprise_reporting/profile_report_generator_unittest.cc index af8a397d..4e1ad293 100644 --- a/chrome/browser/enterprise_reporting/profile_report_generator_unittest.cc +++ b/chrome/browser/enterprise_reporting/profile_report_generator_unittest.cc
@@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" @@ -18,8 +19,9 @@ namespace enterprise_reporting { namespace { -const char kProfile[] = "Profile"; -const char kIdleProfile[] = "IdleProfile"; +constexpr char kProfile[] = "Profile"; +constexpr char kIdleProfile[] = "IdleProfile"; +constexpr char kExtensionId[] = "abcdefghijklmnopabcdefghijklmnop"; } // namespace @@ -56,6 +58,15 @@ return report; } + void SetExtensionToPendingList(const std::vector<std::string>& ids) { + base::Value::ListStorage id_values; + for (auto id : ids) + id_values.push_back(base::Value(id)); + profile()->GetTestingPrefService()->SetUserPref( + prefs::kCloudExtensionRequestIds, + std::make_unique<base::Value>(std::move(id_values))); + } + TestingProfile* profile() { return profile_; } TestingProfileManager* profile_manager() { return &profile_manager_; } @@ -97,4 +108,23 @@ report->chrome_signed_in_user().obfudscated_gaia_id()); } +TEST_F(ProfileReportGeneratorTest, PendingRequest) { + generator_.set_extension_request_enabled(true); + std::vector<std::string> ids = {kExtensionId}; + SetExtensionToPendingList(ids); + + auto report = GenerateReport(); + EXPECT_EQ(1, report->extension_requests_size()); + EXPECT_EQ(kExtensionId, report->extension_requests(0).id()); +} + +TEST_F(ProfileReportGeneratorTest, NoPendingRequestWhenItsDisabled) { + generator_.set_extension_request_enabled(false); + std::vector<std::string> ids = {kExtensionId}; + SetExtensionToPendingList(ids); + + auto report = GenerateReport(); + EXPECT_EQ(0, report->extension_requests_size()); +} + } // namespace enterprise_reporting
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8dcb419..9498cae 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -3406,7 +3406,7 @@ { "name": "translate-ui-bubble-options", "owners": [ "hhw", "anthonyvd", "chrome-language@google.com" ], - "expiry_milestone": 78 + "expiry_milestone": 82 }, { "name": "treat-unsafe-downloads-as-active-content",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 28af2a7..86076c4 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3013,7 +3013,7 @@ "minutes."; const char kWebUIA11yEnhancementsName[] = - "Enable accessibility enahncements in WebUI"; + "Enable accessibility enhancements in WebUI"; const char kWebUIA11yEnhancementsDescription[] = "This flag covers a wide variety of accessibility enhancements in WebUI " "and is used to demonstrate the enhancements for review and testing. When "
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index c250459..2771359 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -970,7 +970,7 @@ if (!sync) { return false; } - ObserveServiceForSyncDisables(sync, profile->GetPrefs()); + StartObserving(sync, profile->GetPrefs()); return true; } @@ -1018,13 +1018,13 @@ ukm_service_->Purge(); } -void ChromeMetricsServiceClient::OnSyncPrefsChanged(bool must_purge) { +void ChromeMetricsServiceClient::OnUkmAllowedStateChanged(bool must_purge) { if (!ukm_service_) return; if (must_purge) { ukm_service_->Purge(); - ukm_service_->ResetClientState(ukm::ResetReason::kOnSyncPrefsChanged); - } else if (!SyncStateAllowsExtensionUkm()) { + ukm_service_->ResetClientState(ukm::ResetReason::kOnUkmAllowedStateChanged); + } else if (!IsUkmAllowedWithExtensionsForAllProfiles()) { ukm_service_->PurgeExtensions(); } @@ -1086,12 +1086,12 @@ g_is_process_running = func; } -bool ChromeMetricsServiceClient::SyncStateAllowsUkm() { - return SyncDisableObserver::SyncStateAllowsUkm(); +bool ChromeMetricsServiceClient::IsUkmAllowedForAllProfiles() { + return UkmConsentStateObserver::IsUkmAllowedForAllProfiles(); } -bool ChromeMetricsServiceClient::SyncStateAllowsExtensionUkm() { - return SyncDisableObserver::SyncStateAllowsExtensionUkm(); +bool ChromeMetricsServiceClient::IsUkmAllowedWithExtensionsForAllProfiles() { + return UkmConsentStateObserver::IsUkmAllowedWithExtensionsForAllProfiles(); } bool g_notification_listeners_failed = false;
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index e19b078..9f5630d1 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -25,7 +25,7 @@ #include "components/metrics/metrics_service_client.h" #include "components/omnibox/browser/omnibox_event_global_tracker.h" #include "components/ukm/observers/history_delete_observer.h" -#include "components/ukm/observers/sync_disable_observer.h" +#include "components/ukm/observers/ukm_consent_state_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ppapi/buildflags/buildflags.h" @@ -46,7 +46,7 @@ class ChromeMetricsServiceClient : public metrics::MetricsServiceClient, public content::NotificationObserver, public ukm::HistoryDeleteObserver, - public ukm::SyncDisableObserver { + public ukm::UkmConsentStateObserver { public: ~ChromeMetricsServiceClient() override; @@ -81,8 +81,8 @@ bool IsReportingPolicyManaged() override; metrics::EnableMetricsDefault GetMetricsReportingDefaultState() override; bool IsUMACellularUploadLogicEnabled() override; - bool SyncStateAllowsUkm() override; - bool SyncStateAllowsExtensionUkm() override; + bool IsUkmAllowedForAllProfiles() override; + bool IsUkmAllowedWithExtensionsForAllProfiles() override; bool AreNotificationListenersEnabledOnAllProfiles() override; std::string GetAppPackageName() override; std::string GetUploadSigningKey() override; @@ -92,8 +92,8 @@ // ukm::HistoryDeleteObserver: void OnHistoryDeleted() override; - // ukm::SyncDisableObserver: - void OnSyncPrefsChanged(bool must_purge) override; + // ukm::UkmConsentStateObserver: + void OnUkmAllowedStateChanged(bool must_purge) override; // Determine what to do with a file based on filename. Visible for testing. using IsProcessRunningFunction = bool (*)(base::ProcessId);
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index d370e56..3ec1a373 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -169,6 +169,8 @@ void FillPasswordForm( const autofill::PasswordFormFillData& form_data) override {} + void InformNoSavedCredentials() override {} + void FillIntoFocusedField(bool is_password, const base::string16& credential) override {} void AnnotateFieldsWithParsingResult(
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index 61e8445..abd96240 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -3876,14 +3876,19 @@ autofill::AutofillPopupController* controller = autofill_client->popup_controller_for_testing().get(); ASSERT_TRUE(controller); - // Two credentials and "Manage passwords" should be displyed. + // Two credentials and "Manage passwords" should be displayed. EXPECT_EQ(3, controller->GetLineCount()); + // Trigger user gesture so that autofill happens. + ASSERT_TRUE(content::ExecuteScript( + WebContents(), "document.getElementById('username_field').click();")); + WaitForElementValue("username_field", "admin"); + // Delete one credential. It should not be in the dropdown. password_store->RemoveLogin(admin_form); WaitForPasswordStore(); - // Wait wor the refetch to finish. + // Wait for the refetch to finish. EXPECT_FALSE(autofill_client->popup_controller_for_testing()); WaitForPasswordStore(); // Reshow the dropdown. @@ -3895,17 +3900,23 @@ EXPECT_EQ(base::ASCIIToUTF16("user"), controller->GetElidedValueAt(0)); EXPECT_NE(base::ASCIIToUTF16("admin"), controller->GetElidedValueAt(1)); + // TODO(crbug.com/1004777): Here the username_field should get re-filled with + // "user" instead of "admin". + // WaitForElementValue("username_field", "user"); + // Delete all the credentials. password_store->RemoveLogin(user_form); WaitForPasswordStore(); - // Wait wor the refetch to finish. + // Wait for the refetch to finish. EXPECT_FALSE(autofill_client->popup_controller_for_testing()); WaitForPasswordStore(); // Reshow the dropdown won't work because there is nothing to suggest. driver->ShowPasswordSuggestions(base::i18n::LEFT_TO_RIGHT, base::string16(), 0, gfx::RectF()); EXPECT_FALSE(autofill_client->popup_controller_for_testing()); + + WaitForElementValue("username_field", ""); } IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, FormDynamicallyChanged) {
diff --git a/chrome/browser/previews/previews_content_util_unittest.cc b/chrome/browser/previews/previews_content_util_unittest.cc index 54324f7..52367e4a 100644 --- a/chrome/browser/previews/previews_content_util_unittest.cc +++ b/chrome/browser/previews/previews_content_util_unittest.cc
@@ -166,14 +166,14 @@ DetermineAllowedClientPreviewsStateDataSaverDisabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( - "Previews,ResourceLoadingHints,NoScriptPreviews", + "Previews,DeferAllScript,ResourceLoadingHints,NoScriptPreviews", {} /* disable_features */); PreviewsUserData user_data(1); bool is_reload = false; bool previews_triggering_logic_already_ran = false; bool is_data_saver_user = true; - EXPECT_EQ(content::OFFLINE_PAGE_ON | content::RESOURCE_LOADING_HINTS_ON | - content::NOSCRIPT_ON, + EXPECT_EQ(content::OFFLINE_PAGE_ON | content::DEFER_ALL_SCRIPT_ON | + content::RESOURCE_LOADING_HINTS_ON | content::NOSCRIPT_ON, previews::CallDetermineAllowedClientPreviewsState( &user_data, GURL("http://www.google.com"), is_reload, previews_triggering_logic_already_ran, is_data_saver_user, @@ -190,7 +190,7 @@ DetermineAllowedClientPreviewsStateOfflineAndRedirects) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( - "Previews", "ResourceLoadingHints,NoScriptPreviews"); + "Previews", "DeferAllScript,ResourceLoadingHints,NoScriptPreviews"); PreviewsUserData user_data(1); bool is_reload = false; bool previews_triggering_logic_already_ran = false;
diff --git a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc index 03083c80..0a2b3df 100644 --- a/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc +++ b/chrome/browser/printing/print_preview_dialog_controller_browsertest.cc
@@ -221,10 +221,16 @@ DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest); }; +// Flaky on Linux: crbug.com/1021545 +#if defined(OS_LINUX) +#define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab +#else +#define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab +#endif // Test to verify that when a initiator navigates, we can create a new preview // dialog for the new tab contents. IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest, - NavigateFromInitiatorTab) { + MAYBE_NavigateFromInitiatorTab) { // Print for the first time. PrintPreview(); @@ -251,10 +257,16 @@ EXPECT_TRUE(new_preview_dialog); } +// Flaky on Linux: crbug.com/1021545 +#if defined(OS_LINUX) +#define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab +#else +#define MAYBE_ReloadInitiatorTab ReloadInitiatorTab +#endif // Test to verify that after reloading the initiator, it creates a new print // preview dialog. IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest, - ReloadInitiatorTab) { + MAYBE_ReloadInitiatorTab) { // Print for the first time. PrintPreview(); @@ -285,10 +297,16 @@ EXPECT_TRUE(new_preview_dialog); } +// Flaky on Linux: crbug.com/1021545 +#if defined(OS_LINUX) +#define MAYBE_PdfPluginDisabled DISABLED_PdfPluginDisabled +#else +#define MAYBE_PdfPluginDisabled PdfPluginDisabled +#endif // Test to verify that after print preview works even when the PDF plugin is // disabled for webpages. IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest, - PdfPluginDisabled) { + MAYBE_PdfPluginDisabled) { // Make sure plugins are loaded. { base::RunLoop run_loop; @@ -352,8 +370,14 @@ } // namespace +// Flaky on Linux: crbug.com/1021545 +#if defined(OS_LINUX) +#define MAYBE_TaskManagementTest DISABLED_TaskManagementTest +#else +#define MAYBE_TaskManagementTest TaskManagementTest +#endif IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest, - TaskManagementTest) { + MAYBE_TaskManagementTest) { // This test starts with two tabs open. EXPECT_EQ(2U, GetTrackedTags().size()); @@ -394,8 +418,14 @@ base::CompareCase::INSENSITIVE_ASCII)); } +// Flaky on Linux: crbug.com/1021545 +#if defined(OS_LINUX) +#define MAYBE_PrintPreviewPdfAccessibility DISABLED_PrintPreviewPdfAccessibility +#else +#define MAYBE_PrintPreviewPdfAccessibility PrintPreviewPdfAccessibility +#endif IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest, - PrintPreviewPdfAccessibility) { + MAYBE_PrintPreviewPdfAccessibility) { content::BrowserAccessibilityState::GetInstance()->EnableAccessibility(); ui_test_utils::NavigateToURL(browser(), GURL("data:text/html,HelloWorld")); PrintPreview();
diff --git a/chrome/browser/profiles/DEPS b/chrome/browser/profiles/DEPS index e890d7c..101a51c 100644 --- a/chrome/browser/profiles/DEPS +++ b/chrome/browser/profiles/DEPS
@@ -3,8 +3,5 @@ # Profile embeds the Identity Service, but the dependence # should be used *only* for Identity Service creation. "+services/identity/identity_service.h", - - # Profile embeds the image_annotation service. - "+services/image_annotation/image_annotation_service.h", ], }
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index fdddddc8..2621807 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -293,11 +293,6 @@ return nullptr; } -image_annotation::mojom::ImageAnnotationService* -Profile::GetImageAnnotationService() { - return nullptr; -} - bool Profile::IsNewProfile() { #if !defined(OS_ANDROID) // The profile is new if the preference files has just been created, except on
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 17eb57b..756fa14 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -45,12 +45,6 @@ } // namespace mojom } // namespace identity -namespace image_annotation { -namespace mojom { -class ImageAnnotationService; -} -} // namespace image_annotation - namespace policy { class SchemaRegistryService; class ProfilePolicyConnector; @@ -394,11 +388,6 @@ // null if the profile does not have a corresponding service instance. virtual identity::mojom::IdentityService* GetIdentityService(); - // Exposes access to the profile's Image Annotation service instance. This may - // return null if the profile does not have a corresponding service instance. - virtual image_annotation::mojom::ImageAnnotationService* - GetImageAnnotationService(); - // Stop sending accessibility events until ResumeAccessibilityEvents(). // Calls to Pause nest; no events will be sent until the number of // Resume calls matches the number of Pause calls received.
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 32ad2cc..257bad6 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -155,14 +155,12 @@ #include "content/public/browser/url_data_source.h" #include "content/public/common/content_constants.h" #include "extensions/buildflags/buildflags.h" -#include "google_apis/google_api_keys.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" #include "services/data_decoder/public/mojom/constants.mojom.h" #include "services/identity/identity_service.h" -#include "services/image_annotation/image_annotation_service.h" #include "services/network/public/cpp/features.h" #include "services/preferences/public/cpp/in_process_service_factory.h" #include "services/preferences/public/mojom/preferences.mojom.h" @@ -257,13 +255,6 @@ const char kPrefExitTypeCrashed[] = "Crashed"; const char kPrefExitTypeSessionEnded[] = "SessionEnded"; -// Returns the Chrome Google API key for the channel of this build. -std::string APIKeyForChannel() { - if (chrome::GetChannel() == version_info::Channel::STABLE) - return google_apis::GetAPIKey(); - return google_apis::GetNonStableAPIKey(); -} - // Gets the creation time for |path|, returning base::Time::Now() on failure. base::Time GetCreationTimeForPath(const base::FilePath& path) { base::File::Info info; @@ -339,28 +330,6 @@ } #endif // defined(OS_CHROMEOS) -class ImageAnnotatorClient : public image_annotation::Annotator::Client { - public: - ImageAnnotatorClient() = default; - ~ImageAnnotatorClient() override = default; - - // image_annotation::Annotator::Client implementation: - void BindJsonParser(mojo::PendingReceiver<data_decoder::mojom::JsonParser> - receiver) override { - content::GetSystemConnector()->Connect(data_decoder::mojom::kServiceName, - std::move(receiver)); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ImageAnnotatorClient); -}; - -ProfileImpl::ImageAnnotationServiceBinder& -GetImageAnnotationServiceBinderOverride() { - static base::NoDestructor<ProfileImpl::ImageAnnotationServiceBinder> binder; - return *binder; -} - } // namespace // static @@ -1099,24 +1068,6 @@ return remote_identity_service_.get(); } -image_annotation::mojom::ImageAnnotationService* -ProfileImpl::GetImageAnnotationService() { - if (!remote_image_annotation_service_) { - auto receiver = - remote_image_annotation_service_.BindNewPipeAndPassReceiver(); - const auto& binder = GetImageAnnotationServiceBinderOverride(); - if (binder) { - binder.Run(std::move(receiver)); - } else { - image_annotation_service_impl_ = - std::make_unique<image_annotation::ImageAnnotationService>( - std::move(receiver), APIKeyForChannel(), GetURLLoaderFactory(), - std::make_unique<ImageAnnotatorClient>()); - } - } - return remote_image_annotation_service_.get(); -} - PrefService* ProfileImpl::GetPrefs() { return const_cast<PrefService*>( static_cast<const ProfileImpl*>(this)->GetPrefs()); @@ -1511,12 +1462,6 @@ creation_time_ = creation_time; } -// static -void ProfileImpl::OverrideImageAnnotationServiceBinderForTesting( - ImageAnnotationServiceBinder binder) { - GetImageAnnotationServiceBinderOverride() = std::move(binder); -} - GURL ProfileImpl::GetHomePage() { // --homepage overrides any preferences. const base::CommandLine& command_line =
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index 4a4479c..10d7388 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -26,7 +26,6 @@ #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/identity/public/mojom/identity_service.mojom.h" -#include "services/image_annotation/public/mojom/image_annotation.mojom.h" #if !defined(OS_ANDROID) #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" @@ -53,10 +52,6 @@ class IdentityService; } -namespace image_annotation { -class ImageAnnotationService; -} - namespace policy { class ConfigurationPolicyProvider; class ProfilePolicyConnector; @@ -171,8 +166,6 @@ bool ShouldRestoreOldSessionCookies() override; bool ShouldPersistSessionCookies() override; identity::mojom::IdentityService* GetIdentityService() override; - image_annotation::mojom::ImageAnnotationService* GetImageAnnotationService() - override; #if defined(OS_CHROMEOS) void ChangeAppLocale(const std::string& locale, AppLocaleChangedVia) override; @@ -182,13 +175,6 @@ void SetCreationTimeForTesting(base::Time creation_time) override; - // Overrides how the ImageAnnotationService service instance is bound in a - // testing environment. If |binder| is null, any existing override is removed. - using ImageAnnotationServiceBinder = base::RepeatingCallback<void( - mojo::PendingReceiver<image_annotation::mojom::ImageAnnotationService>)>; - static void OverrideImageAnnotationServiceBinderForTesting( - ImageAnnotationServiceBinder binder); - private: #if defined(OS_CHROMEOS) friend class chromeos::KioskTest; @@ -261,12 +247,6 @@ // |GetIdentityService()|. mojo::Remote<identity::mojom::IdentityService> remote_identity_service_; - // The Image Annotation service instance for this profile. - std::unique_ptr<image_annotation::ImageAnnotationService> - image_annotation_service_impl_; - mojo::Remote<image_annotation::mojom::ImageAnnotationService> - remote_image_annotation_service_; - // !!! BIG HONKING WARNING !!! // The order of the members below is important. Do not change it unless // you know what you're doing. Also, if adding a new member here make sure
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc index f37c36d..c318ff72b 100644 --- a/chrome/browser/profiles/profile_info_cache.cc +++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -50,7 +50,7 @@ const char kAccountIdKey[] = "account_id_key"; #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) const char kLegacyProfileNameMigrated[] = "legacy.profile.name.migrated"; -bool migration_enabled_for_testing_ = false; +bool migration_enabled_for_testing = false; #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) void DeleteBitmap(const base::FilePath& image_path) { @@ -117,9 +117,9 @@ LoadGAIAPictureIfNeeded(); bool migrate_legacy_profile_names = - (!prefs_->GetBoolean(kLegacyProfileNameMigrated) && - ProfileAttributesEntry::ShouldConcatenateGaiaAndProfileName()) || - migration_enabled_for_testing_; + ProfileAttributesEntry::ShouldConcatenateGaiaAndProfileName() && + (!prefs_->GetBoolean(kLegacyProfileNameMigrated) || + migration_enabled_for_testing); if (migrate_legacy_profile_names) { MigrateLegacyProfileNamesAndRecomputeIfNeeded(); prefs_->SetBoolean(kLegacyProfileNameMigrated, true); @@ -689,8 +689,8 @@ } // static -void ProfileInfoCache::EnableLegacyProfileMigrationForTesting() { - migration_enabled_for_testing_ = true; +void ProfileInfoCache::SetLegacyProfileMigrationForTesting(bool value) { + migration_enabled_for_testing = value; } #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h index 100bfb6..c59d2800 100644 --- a/chrome/browser/profiles/profile_info_cache.h +++ b/chrome/browser/profiles/profile_info_cache.h
@@ -186,7 +186,7 @@ // i.e. Two or more profiles with the profile name "Person 1" would be // recomputed to "Person 1" and "Person 2". void MigrateLegacyProfileNamesAndRecomputeIfNeeded(); - static void EnableLegacyProfileMigrationForTesting(); + static void SetLegacyProfileMigrationForTesting(bool value); #endif // !defined(OS_ANDROID) && !defined(OS_CHROMEOS) std::vector<std::string> keys_;
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc index 4a06d3c..3ed1b4654 100644 --- a/chrome/browser/profiles/profile_info_cache_unittest.cc +++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -883,7 +883,9 @@ EXPECT_EQ(12U, GetCache()->GetNumberOfProfiles()); ResetCache(); - ProfileInfoCache::EnableLegacyProfileMigrationForTesting(); + ProfileInfoCache::SetLegacyProfileMigrationForTesting(true); + GetCache(); + ProfileInfoCache::SetLegacyProfileMigrationForTesting(false); EXPECT_EQ(name_5, GetCache()->GetNameToDisplayOfProfileAtIndex( GetCache()->GetIndexOfProfileWithPath(path_5)));
diff --git a/chrome/browser/resources/bookmarks/bookmarks.html b/chrome/browser/resources/bookmarks/bookmarks.html index 077405e..5e8532d2 100644 --- a/chrome/browser/resources/bookmarks/bookmarks.html +++ b/chrome/browser/resources/bookmarks/bookmarks.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/bookmarks/item.html b/chrome/browser/resources/bookmarks/item.html index 9191430e..6543b57 100644 --- a/chrome/browser/resources/bookmarks/item.html +++ b/chrome/browser/resources/bookmarks/item.html
@@ -29,6 +29,10 @@ background-color: var(--highlight-color); } + :host([is-selected-item_]) cr-icon-button { + --cr-icon-button-focus-color: var(--highlight-color); + } + @media (prefers-color-scheme: dark) { :host([is-selected-item_]), :host([is-selected-item_]) .folder-icon { @@ -103,7 +107,7 @@ <div id="website-url" class="elided-text" title="[[item_.url]]"> [[item_.url]] </div> - <cr-icon-button class$="[[crIcon_]]" + <cr-icon-button class="icon-more-vert" id="menuButton" tabindex="[[ironListTabIndex]]" title="$i18n{moreActionsButtonTitle}"
diff --git a/chrome/browser/resources/bookmarks/item.js b/chrome/browser/resources/bookmarks/item.js index e2f0aa7..667e5de 100644 --- a/chrome/browser/resources/bookmarks/item.js +++ b/chrome/browser/resources/bookmarks/item.js
@@ -17,11 +17,6 @@ ironListTabIndex: Number, - crIcon_: { - type: String, - value: 'icon-more-vert', - }, - /** @private {BookmarkNode} */ item_: { type: Object, @@ -32,7 +27,6 @@ isSelectedItem_: { type: Boolean, reflectToAttribute: true, - observer: 'onIsSelectedItemChanged_', }, /** @private */ @@ -139,12 +133,6 @@ }, /** @private */ - onIsSelectedItemChanged_: function() { - this.crIcon_ = this.isSelectedItem_ ? 'icon-more-vert-light-mode' : - 'icon-more-vert'; - }, - - /** @private */ onItemIdChanged_: function() { // TODO(tsergeant): Add a histogram to measure whether this assertion fails // for real users.
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js index f4aa026..13ede3c 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
@@ -51,11 +51,9 @@ title += ' '; title += new Date(model.information.timestamp).toLocaleString(); } - if (model.information.duration) { - title += ' '; - title += (model.information.duration * 0.000001).toFixed(2); - title += 's'; - } + title += ' '; + title += (model.information.duration * 0.000001).toFixed(2); + title += 's'; if (model.information.platform) { title += ' on '; title += model.information.platform; @@ -77,6 +75,8 @@ setModelHeader(model); + var duration = model.information.duration; + // Microseconds per pixel. 100% zoom corresponds to 100 mcs per pixel. var resolution = zooms[zoomLevel]; var parent = $('arc-event-bands'); @@ -93,9 +93,9 @@ 406 /* kVsyncTimestamp */); var cpusTitle = new EventBandTitle(parent, 'CPUs', 'arc-events-band-title'); - var cpusBands = new CpuEventBands( - cpusTitle, 'arc-events-band', resolution, 0, model.duration); - cpusBands.setWidth(cpusBands.timestampToOffset(model.duration)); + var cpusBands = + new CpuEventBands(cpusTitle, 'arc-events-band', resolution, 0, duration); + cpusBands.setWidth(cpusBands.timestampToOffset(duration)); cpusBands.setModel(model); cpusBands.addChartToExistingArea(0 /* top */, cpusBands.height); cpusBands.addChartSources( @@ -114,9 +114,9 @@ var memoryTitle = new EventBandTitle(parent, 'Memory', 'arc-events-band-title'); - var memoryBands = new EventBands( - memoryTitle, 'arc-events-band', resolution, 0, model.duration); - memoryBands.setWidth(memoryBands.timestampToOffset(model.duration)); + var memoryBands = + new EventBands(memoryTitle, 'arc-events-band', resolution, 0, duration); + memoryBands.setWidth(memoryBands.timestampToOffset(duration)); memoryBands.addChart(chartHeight, topBandPadding); // Used memory chart. memoryBands.addChartSources( @@ -146,9 +146,9 @@ var chromeTitle = new EventBandTitle(parent, 'Chrome graphics', 'arc-events-band-title'); - var chromeBands = new EventBands( - chromeTitle, 'arc-events-band', resolution, 0, model.duration); - chromeBands.setWidth(chromeBands.timestampToOffset(model.duration)); + var chromeBands = + new EventBands(chromeTitle, 'arc-events-band', resolution, 0, duration); + chromeBands.setWidth(chromeBands.timestampToOffset(duration)); for (var i = 0; i < model.chrome.buffers.length; i++) { chromeBands.addBand( new Events(model.chrome.buffers[i], 500, 599), topBandHeight, @@ -173,9 +173,9 @@ var androidTitle = new EventBandTitle(parent, 'Android graphics', 'arc-events-band-title'); - var androidBands = new EventBands( - androidTitle, 'arc-events-band', resolution, 0, model.duration); - androidBands.setWidth(androidBands.timestampToOffset(model.duration)); + var androidBands = + new EventBands(androidTitle, 'arc-events-band', resolution, 0, duration); + androidBands.setWidth(androidBands.timestampToOffset(duration)); androidBands.addBand( new Events(model.android.buffers[0], 400, 499), topBandHeight, topBandPadding); @@ -208,8 +208,8 @@ var activityTitle = new EventBandTitle( parent, activityTitleText, 'arc-events-band-title', icon); var activityBands = new EventBands( - activityTitle, 'arc-events-band', resolution, 0, model.duration); - activityBands.setWidth(activityBands.timestampToOffset(model.duration)); + activityTitle, 'arc-events-band', resolution, 0, duration); + activityBands.setWidth(activityBands.timestampToOffset(duration)); for (var j = 0; j < view.buffers.length; j++) { // Android buffer events. activityBands.addBand( @@ -245,9 +245,9 @@ if (model.input && model.input.buffers.length > 0) { var inputTitle = new EventBandTitle(parent, 'Input', 'arc-events-band-title'); - var inputBands = new EventBands( - inputTitle, 'arc-events-band', resolution, 0, model.duration); - inputBands.setWidth(inputBands.timestampToOffset(model.duration)); + var inputBands = + new EventBands(inputTitle, 'arc-events-band', resolution, 0, duration); + inputBands.setWidth(inputBands.timestampToOffset(duration)); for (var i = 0; i < model.input.buffers.length; i++) { inputBands.addBand( new Events(model.input.buffers[i], 700, 799), topBandHeight, @@ -262,8 +262,8 @@ var timeRulerTitle = new EventBandTitle(parent, '' /* title */, 'arc-time-ruler-title'); var timeRulerBands = new EventBands( - timeRulerTitle, 'arc-events-band', resolution, 0, model.duration); - timeRulerBands.setWidth(timeRulerBands.timestampToOffset(model.duration)); + timeRulerTitle, 'arc-events-band', resolution, 0, duration); + timeRulerBands.setWidth(timeRulerBands.timestampToOffset(duration)); // Reseve space for ticks and global events. timeRulerBands.updateHeight(timeRulerEventHeight, 0 /* padding */); @@ -273,7 +273,7 @@ var timeTick = 0; var timeTickOffset = 20 * resolution; var timeTickIndex = 0; - while (timeTick < model.duration) { + while (timeTick < duration) { if ((timeTickIndex % 10) == 0) { timeEvents.push([kTimeMark, timeTick]); } else { @@ -303,7 +303,7 @@ timeRulerBands.updateHeight(timeRulerLabelHeight, 0 /* padding */); timeTick = 0; timeTickOffset = 200 * resolution; - while (timeTick < model.duration) { + while (timeTick < duration) { SVG.addText( timeRulerBands.svg, timeRulerBands.timestampToOffset(timeTick), timeRulerEventHeight, timeRulerBands.fontSize,
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_overview_tracing_ui.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_overview_tracing_ui.js index 398df64..f5d87a9 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_overview_tracing_ui.js +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_overview_tracing_ui.js
@@ -98,9 +98,7 @@ new Date(model.information.timestamp).toLocaleString() : 'Unknown date'; header.getElementsByClassName('arc-tracing-app-date')[0].textContent = date; - var duration = model.information.duration ? - (model.information.duration * 0.000001).toFixed(2) : - 'unknown duration'; + var duration = (model.information.duration * 0.000001).toFixed(2); header.getElementsByClassName('arc-tracing-app-duration')[0].textContent = duration; var platform = model.information.platform ? model.information.platform : @@ -108,14 +106,12 @@ header.getElementsByClassName('arc-tracing-app-platform')[0].textContent = platform; - if (model.information.duration) { - header.getElementsByClassName('arc-tracing-app-fps')[0].textContent = - calculateFPS(getAppCommitEvents(model), model.information.duration) - .toFixed(2); - header.getElementsByClassName('arc-tracing-chrome-fps')[0].textContent = - calculateFPS(getChromeSwapEvents(model), model.information.duration) - .toFixed(2); - } + header.getElementsByClassName('arc-tracing-app-fps')[0].textContent = + calculateFPS(getAppCommitEvents(model), model.information.duration) + .toFixed(2); + header.getElementsByClassName('arc-tracing-chrome-fps')[0].textContent = + calculateFPS(getChromeSwapEvents(model), model.information.duration) + .toFixed(2); var cpuPower = getAveragePower(model, 10 /* kCpuPower */); var gpuPower = getAveragePower(model, 11 /* kGpuPower */); @@ -458,7 +454,7 @@ var duration = 0; for (i = 0; i < models.length; i++) { - duration = Math.max(duration, models[i].duration); + duration = Math.max(duration, models[i].information.duration); } for (i = 0; i < models.length; i++) { @@ -516,14 +512,6 @@ * @param {object} model to add. */ function addModel(model) { - // Patch old models that do not have model.information to simplify checks. - if (!model.information) { - model.information = {}; - if (!model.information.duration) { - model.information.duration = model.duration; - } - } - models.push(model); setModelColor(model);
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.html b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html index 9991144..fa12548 100644 --- a/chrome/browser/resources/chromeos/login/enterprise_enrollment.html +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html
@@ -15,7 +15,8 @@ <div id="step-signin" hidden$="[[!eq_(currentStep_, 'signin')]]"> <oobe-dialog class="gaia-dialog" role="dialog" id="enrollment-gaia-dialog" has-buttons no-header - no-footer-padding> + no-footer-padding + show-buttons-overlay="[[authenticatorDialogDisplayed_]]"> <div slot="footer" class="flex layout vertical"> <webview id="oauth-enroll-auth-view" name="oauth-enroll-auth-view">
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js index 477449d..dfcd586 100644 --- a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
@@ -232,13 +232,11 @@ this.authenticator_.addEventListener( 'dialogShown', (function(e) { this.authenticatorDialogDisplayed_ = true; - // TODO(alemate): update the visual style. }).bind(this)); this.authenticator_.addEventListener( 'dialogHidden', (function(e) { this.authenticatorDialogDisplayed_ = false; - // TODO(alemate): update the visual style. }).bind(this)); this.authenticator_.insecureContentBlockedCallback =
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.css b/chrome/browser/resources/chromeos/login/oobe_dialog.css index 4d21904d..ac536f3c 100644 --- a/chrome/browser/resources/chromeos/login/oobe_dialog.css +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.css
@@ -71,6 +71,10 @@ z-index: 1; } +#buttons-overlay { + background: rgba(var(--google-grey-900-rgb), 0.6); +} + :host #oobe-bottom[no-buttons-padding] { padding: unset; }
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.html b/chrome/browser/resources/chromeos/login/oobe_dialog.html index 95d5040..dceb9729 100644 --- a/chrome/browser/resources/chromeos/login/oobe_dialog.html +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.html
@@ -84,6 +84,8 @@ <div id="oobe-bottom" hideShadow$="[[hideShadow]]" class="slot-container layout horizontal center"> <slot name="bottom-buttons"></slot> + <div id="buttons-overlay" class="fit" hidden="[[!showButtonsOverlay]]"> + </div> </div> </template> </template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.js b/chrome/browser/resources/chromeos/login/oobe_dialog.js index 86f3f56..2bf6b43 100644 --- a/chrome/browser/resources/chromeos/login/oobe_dialog.js +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.js
@@ -55,6 +55,14 @@ reflectToAttribute: true, observer: 'onfullScreenDialogChanged_', }, + + /** + * Shows overlay on top of the bottom buttons. + */ + showButtonsOverlay: { + type: Boolean, + value: false, + }, }, focus: function() {
diff --git a/chrome/browser/resources/chromeos/login/oobe_network.js b/chrome/browser/resources/chromeos/login/oobe_network.js index 725c91f7..eb44b164 100644 --- a/chrome/browser/resources/chromeos/login/oobe_network.js +++ b/chrome/browser/resources/chromeos/login/oobe_network.js
@@ -21,21 +21,30 @@ * setup. * @type {boolean} */ - isDemoModeSetup: false, + isDemoModeSetup: { + type: Boolean, + value: false, + }, /** * Whether offline demo mode is enabled. If it is enabled offline setup * option will be shown in UI. * @type {boolean} */ - offlineDemoModeEnabled: false, + offlineDemoModeEnabled: { + type: Boolean, + value: false, + }, /** * Whether device is connected to the network. * @type {boolean} * @private */ - isConnected_: false, + isConnected_: { + type: Boolean, + value: false, + }, }, /** Called when dialog is shown. */
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css index 423807a..71f2628 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -120,7 +120,3 @@ :host(.saml) #signin-frame-container { padding-top: 44px; } - -#gaia-screen-buttons-overlay { - background: rgba(0, 0, 0, 0.6); -}
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html index bd43c0bc..a6dce40 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
@@ -10,6 +10,7 @@ <template> <oobe-dialog id="signin-frame-dialog" class="gaia-dialog" role="dialog" has-buttons no-header no-footer-padding + show-buttons-overlay="[[!navigationEnabled_]]" hidden="[[!isSigninFrameDialogVisible_(screenMode_, pinDialogParameters_)]]"> <div slot="footer" class="flex layout vertical"> @@ -36,9 +37,6 @@ disabled="[[!secondaryActionButtonEnabled_]]" >[[secondaryActionButtonLabel_]]</oobe-text-button> </div> - <div id="gaia-screen-buttons-overlay" class="fit" - hidden="[[navigationEnabled_]]"> - </div> </div> </oobe-dialog> <offline-gaia id="offline-gaia" class="gaia-dialog"
diff --git a/chrome/browser/resources/downloads/downloads.html b/chrome/browser/resources/downloads/downloads.html index 437c6414..e900f1f 100644 --- a/chrome/browser/resources/downloads/downloads.html +++ b/chrome/browser/resources/downloads/downloads.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <if expr="not optimize_webui">
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html index de540f6..7e729cf 100644 --- a/chrome/browser/resources/extensions/extensions.html +++ b/chrome/browser/resources/extensions/extensions.html
@@ -1,6 +1,6 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}" - class="loading $i18n{loadTimeClasses}"> + class="loading $i18n{loadTimeClasses}" $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/history/history.html b/chrome/browser/resources/history/history.html index af0c23e..5fd5f3c 100644 --- a/chrome/browser/resources/history/history.html +++ b/chrome/browser/resources/history/history.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/history/shared_vars.html b/chrome/browser/resources/history/shared_vars.html index ba04f03..ade6397 100644 --- a/chrome/browser/resources/history/shared_vars.html +++ b/chrome/browser/resources/history/shared_vars.html
@@ -23,8 +23,6 @@ --history-item-time-color: #646464; --interactive-color: var(--google-blue-500); --item-height: 44px; - --iron-icon-height: var(--cr-icon-size); - --iron-icon-width: var(--cr-icon-size); --separator-color: rgba(0, 0, 0, 0.08); --side-bar-width: 256px; --sidebar-footer-text-color: var(--google-grey-refresh-700);
diff --git a/chrome/browser/resources/inspect/OWNERS b/chrome/browser/resources/inspect/OWNERS index 80e7c6a..13224fd71 100644 --- a/chrome/browser/resources/inspect/OWNERS +++ b/chrome/browser/resources/inspect/OWNERS
@@ -1,4 +1,5 @@ dgozman@chromium.org pfeldman@chromium.org +yangguo@chromium.org # COMPONENT: Platform>DevTools
diff --git a/chrome/browser/resources/pdf/elements/viewer-zoom-button.html b/chrome/browser/resources/pdf/elements/viewer-zoom-button.html index d6081f25..edb614f 100644 --- a/chrome/browser/resources/pdf/elements/viewer-zoom-button.html +++ b/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
@@ -32,12 +32,12 @@ } cr-icon-button { - --cr-icon-button-size: 36px; + --cr-icon-button-color: var(--paper-grey-700); --cr-icon-button-icon-size: 20px; - --cr-icon-button-ripple-opacity: .4; + --cr-icon-button-size: 36px; + --cr-icon-button-focus-color: rgb(242, 242, 242); background-color: rgb(242, 242, 242); border-radius: 50%; - color: var(--paper-grey-700); overflow: visible; @apply --shadow-elevation-2dp; } @@ -47,9 +47,10 @@ } :host-context([is-print-preview]) cr-icon-button { + --cr-icon-button-color: white; + --cr-icon-button-focus-color: var(--google-grey-600); --cr-icon-button-size: 32px; background-color: var(--google-grey-600); - color: white; } @media (prefers-color-scheme: light) { @@ -60,8 +61,9 @@ @media (prefers-color-scheme: dark) { :host-context([is-print-preview]) cr-icon-button { + --cr-icon-button-color: var(--google-grey-200); + --cr-icon-button-focus-color: var(--google-grey-900); background-color: var(--google-grey-900); - color: var(--google-grey-200); } }
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index 8a5ff5d..ade4c62 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -1,5 +1,5 @@ <!doctype html> -<html> +<html $i18n{a11yenhanced}> <head> <meta charset="utf-8">
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html index 51305f3c..086f350 100644 --- a/chrome/browser/resources/print_preview/print_preview.html +++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced} + class="loading"> <head> <meta charset="utf-8"> <if expr="not optimize_webui">
diff --git a/chrome/browser/resources/print_preview/ui/link_container.html b/chrome/browser/resources/print_preview/ui/link_container.html index 3268cb4..2f9274b 100644 --- a/chrome/browser/resources/print_preview/ui/link_container.html +++ b/chrome/browser/resources/print_preview/ui/link_container.html
@@ -62,7 +62,7 @@ hidden$="[[!shouldShowSystemDialogLink_]]" on-click="onSystemDialogClick_"> <div class="label">$i18n{systemDialogOption}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" hidden$="[[openingSystemDialog_]]" disabled="[[systemDialogLinkDisabled_]]" aria-label="$i18n{systemDialogOption}"></cr-icon-button> @@ -73,7 +73,7 @@ <div class="link" id="openPdfInPreviewLink" actionable$="[[!disabled]]" on-click="onOpenInPreviewClick_"> <div class="label">$i18n{openPdfInPreviewOption}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" hidden$="[[openingInPreview_]]" disabled="[[disabled]]" aria-label="$i18n{openPdfInPreviewOption}"></cr-icon-button> <div id="openPdfInPreviewThrobber" hidden$="[[!openingInPreview_]]"
diff --git a/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html b/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html index ce8e559f..3fbfea419 100644 --- a/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html +++ b/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html
@@ -21,6 +21,9 @@ --cr-form-field-label-line-height: .75rem; --destination-item-height: 32px; --preview-area-background-color: var(--google-grey-refresh-300); + --iron-icon-fill-color: var(--google-grey-refresh-700); + --iron-icon-height: var(--cr-icon-size); + --iron-icon-width: var(--cr-icon-size); } @media (prefers-color-scheme: dark) { @@ -30,6 +33,7 @@ opacity: var(--cr-disabled-opacity); } --print-preview-settings-border: var(--cr-separator-line); + --iron-icon-fill-color: var(--google-grey-refresh-500); } } </style>
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html index ccc488cb..7d86a99 100644 --- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -245,7 +245,7 @@ $i18n{a11yWebStore} </div> </div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{additionalFeaturesTitle}" aria-describedby="moreFeaturesSecondary"></cr-icon-button> </a>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html index 92340b7..1cd59ad 100644 --- a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html +++ b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
@@ -16,10 +16,8 @@ <style include="settings-shared"></style> <template is="dom-if" if="[[androidAppsInfo.settingsAppAvailable]]" restamp> - <cr-link-row id="manageApps" icon-class="icon-external" - label="$i18n{androidAppsManageApps}" - on-click="onManageAndroidAppsTap_" external> - </cr-link-row> + <cr-link-row id="manageApps" label="$i18n{androidAppsManageApps}" + on-click="onManageAndroidAppsTap_" external></cr-link-row> </template> <!-- Use 'restamp' so tests can check if the row exists. -->
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.html b/chrome/browser/resources/settings/autofill_page/autofill_section.html index 027cac1..58164cb1 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.html +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.html
@@ -73,7 +73,7 @@ </cr-icon-button> </template> <template is="dom-if" if="[[!item.metadata.isLocal]]"> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" on-click="onRemoteEditAddressTap_"></cr-icon-button> </template> </div>
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html index 4f62b13e..1d3bbd05 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html +++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
@@ -47,9 +47,8 @@ </cr-icon-button> </template> <template is="dom-if" if="[[!showDots_(creditCard.metadata)]]"> - <cr-icon-button actionable class="icon-external" - id="remoteCreditCardLink" on-click="onRemoteEditClick_"> - </cr-icon-button> + <cr-icon-button class="icon-external" id="remoteCreditCardLink" + on-click="onRemoteEditClick_"></cr-icon-button> </template> </div> </div>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.html b/chrome/browser/resources/settings/chromeos/os_settings.html index e9d471e..d006dbf 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.html +++ b/chrome/browser/resources/settings/chromeos/os_settings.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <title>$i18n{settings}</title>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 101f44c..ab46a97 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -177,7 +177,7 @@ <div class="start settings-box-text"> $i18n{personalizeGoogleServicesTitle} </div> - <cr-icon-button actionable class="icon-external"></cr-icon-button> + <cr-icon-button class="icon-external"></cr-icon-button> </a> <a id="syncDashboardLink" @@ -187,7 +187,7 @@ <div class="start settings-box-text"> $i18n{manageSyncedDataTitle} </div> - <cr-icon-button actionable class="icon-external"></cr-icon-button> + <cr-icon-button class="icon-external"></cr-icon-button> </a> <div id="encryptionDescription"
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chrome/browser/resources/settings/printing_page/cloud_printers.html index 21bcb4b..fb6f35b 100644 --- a/chrome/browser/resources/settings/printing_page/cloud_printers.html +++ b/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -24,7 +24,7 @@ <div class="start"> $i18n{printingManageCloudPrintDevices} </div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{printingManageCloudPrintDevices}"></cr-icon-button> </a> </template>
diff --git a/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chrome/browser/resources/settings/privacy_page/BUILD.gn index 028266d95..d5e67c9 100644 --- a/chrome/browser/resources/settings/privacy_page/BUILD.gn +++ b/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -110,6 +110,7 @@ deps = [ ":security_keys_browser_proxy", ":security_keys_pin_field", + "//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted", "//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc", "//ui/webui/resources/js:i18n_behavior", ]
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index e17198e..19c65072 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -450,7 +450,7 @@ target="_blank" href="https://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html"> <div class="start">$i18n{adobeFlashStorage}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{adobeFlashStorage}"></cr-icon-button> </a> </if>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html index e1d92c20..f48c130 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html +++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.html
@@ -6,6 +6,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> @@ -52,15 +53,13 @@ <iron-pages attr-for-selected="id" selected="[[dialogPage_]]" on-iron-select="onIronSelect_"> <div id="initial"> - <p>$i18n{securityKeysBioEnrollmentTouch}</p> + <p>$i18n{securityKeysTouchToContinue}</p> <paper-spinner-lite style="padding-bottom: 16px;" active> </paper-spinner-lite> </div> <div id="pinPrompt"> - <p>$i18n{securityKeysBioEnrollmentPinPrompt}</p> - <settings-security-keys-pin-field - id="pin" label="$i18n{securityKeysPIN}"> + <settings-security-keys-pin-field id="pin"> </settings-security-keys-pin-field> </div> @@ -110,7 +109,7 @@ </div> <div id="enroll"> - <p>$i18n{securityKeysBioEnrollmentEnrollingLabel}</p> + <p>[[progressArcLabel_]]</p> <cr-fingerprint-progress-arc id="arc"></cr-fingerprint-progress-arc> </div>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js index 43253425..fc7b070 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js +++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
@@ -54,6 +54,9 @@ enrollments_: Array, /** @private */ + progressArcLabel_: String, + + /** @private */ recentEnrollmentName_: String, }, @@ -68,6 +71,10 @@ /** @override */ attached: function() { + Polymer.RenderStatus.afterNextRender(this, function() { + Polymer.IronA11yAnnouncer.requestAvailability(); + }); + this.$.dialog.showModal(); this.addWebUIListener( 'security-keys-bio-enroll-error', this.onError_.bind(this)); @@ -171,6 +178,8 @@ this.maxSamples_ = -1; // Reset maxSamples_ before enrolling starts. this.$.arc.reset(); + this.progressArcLabel_ = + this.i18n('securityKeysBioEnrollmentEnrollingLabel'); this.recentEnrollmentId_ = ''; this.recentEnrollmentName_ = ''; @@ -216,7 +225,11 @@ this.cancelButtonVisible_ = false; this.confirmButtonVisible_ = true; this.confirmButtonDisabled_ = false; + this.progressArcLabel_ = + this.i18n('securityKeysBioEnrollmentEnrollingCompleteLabel'); this.$.confirmButton.focus(); + // Make screen-readers announce enrollment completion. + this.fire('iron-announce', {text: this.progressArcLabel_}); } this.fire('bio-enroll-dialog-ready-for-testing'); },
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html index 5436aeca1..199da223 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html +++ b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html
@@ -63,14 +63,12 @@ <iron-pages attr-for-selected="id" selected="[[dialogPage_]]" on-iron-select="onIronSelect_"> <div id="initial"> - <p>$i18n{securityKeysCredentialManagementTouch}</p> + <p>$i18n{securityKeysTouchToContinue}</p> <paper-spinner-lite active></paper-spinner-lite> </div> <div id="pinPrompt"> - <p>$i18nRaw{securityKeysCredentialManagementPinPrompt}</p> - <settings-security-keys-pin-field - id="pin" label="$i18n{securityKeysPIN}"> + <settings-security-keys-pin-field id="pin"> </settings-security-keys-pin-field> </div>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.html b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.html index f185cba..c07206d 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.html +++ b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.html
@@ -17,11 +17,12 @@ } </style> + <p>$i18n{securityKeysPINPrompt}</p> <cr-input id="pin" value="{{value}}" minLength="4" maxLength="255" spellcheck="false" on-input="onPINInput_" invalid="[[isNonEmpty_(error)]]" - label="[[label]]" tabindex="0" + label="$i18n{securityKeysPIN}" tabindex="0" type$="[[inputType_(inputVisible_)]]" error-message="[[error]]"> <cr-icon-button slot="suffix" id="showButton"
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.js b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.js index 72159d83..591a530 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.js +++ b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.js
@@ -14,16 +14,13 @@ ], properties: { - /** The label of the input field. */ - label: String, - - /** The validation error label of the input field. */ + // The validation error label of the input field. error: { type: String, observer: 'errorChanged_', }, - /** The value of the input field. */ + // The value of the input field. value: String, /**
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html index 94f201d..fe7a2d24 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html +++ b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.html
@@ -42,7 +42,7 @@ <iron-pages attr-for-selected="id" selected="[[shown_]]" on-iron-select="onIronSelect_"> <div id="initial"> - <p>$i18n{securityKeysPINTouch}</p> + <p>$i18n{securityKeysTouchToContinue}</p> <paper-spinner-lite active></paper-spinner-lite> </div>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html index 8f242c4..4754df03 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html +++ b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.html
@@ -27,20 +27,20 @@ sub-label="$i18n{securityKeysCredentialManagementDesc}" on-click="onCredentialManagement_"></cr-link-row> </template> + <template is="dom-if" if="[[enableBioEnrollment_]]"> + <cr-link-row + id="bioEnrollButton" + class="hr" + label="$i18n{securityKeysBioEnrollmentSubpageLabel}" + sub-label="$i18n{securityKeysBioEnrollmentSubpageDescription}" + on-click="onBioEnroll_"></cr-link-row> + </template> <cr-link-row id="resetButton" class="hr" label="$i18n{securityKeysReset}" sub-label="$i18n{securityKeysResetDesc}" on-click="onReset_"></cr-link-row> - <template is="dom-if" if="[[enableBioEnrollment_]]"> - <cr-link-row - id="bioEnrollButton" - class="hr" - label="$i18n{securityKeysBioEnrollmentDialogTitle}" - sub-label="$i18n{securityKeysBioEnrollmentSubpageDescription}" - on-click="onBioEnroll_"></cr-link-row> - </template> <template is="dom-if" if="[[showSetPINDialog_]]" restamp> <settings-security-keys-set-pin-dialog on-close="onSetPINDialogClosed_">
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html index 7842e79..55f5804 100644 --- a/chrome/browser/resources/settings/settings.html +++ b/chrome/browser/resources/settings/settings.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <title>$i18n{settings}</title>
diff --git a/chrome/browser/resources/settings/settings_icons_css.html b/chrome/browser/resources/settings/settings_icons_css.html index cdfd12f1..39e914c 100644 --- a/chrome/browser/resources/settings/settings_icons_css.html +++ b/chrome/browser/resources/settings/settings_icons_css.html
@@ -6,10 +6,10 @@ <style> <if expr="chromeos"> cr-icon-button.icon-add-circle { - background-image: url(./images/settings_icon_add_circle.svg); + --cr-icon-image: url(./images/settings_icon_add_circle.svg); } cr-icon-button.icon-add-wifi { - background-image: url(./images/settings_icon_add_wifi.svg); + --cr-icon-image: url(./images/settings_icon_add_wifi.svg); } </if> </style>
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html index 0bcf848..5f7a88b 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.html +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -231,7 +231,7 @@ on-click="onExtensionsLinkClick_" title="$i18n{extensionsLinkTooltip}"> <span>$i18n{extensionsPageTitle}</span> - <iron-icon class="cr-icon icon-external" actionable></iron-icon> + <iron-icon icon="cr:open-in-new"></iron-icon> </a> <a id="about-menu" href="/help">$i18n{aboutPageTitle}</a> </iron-selector>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html index 6b80d2a..b2e0ed6a 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -192,7 +192,6 @@ <cr-link-row class="hr two-line" data-route="SITE_SETTINGS_SERIAL_PORTS" - icon-class="subpage-arrow" id="serial-ports" label="$i18n{siteSettingsSerialPorts}" on-click="onTapNavigate_" @@ -206,7 +205,7 @@ <template is="dom-if" if="[[enableNativeFileSystemWriteContentSetting_]]"> <cr-link-row class="hr two-line" data-route="SITE_SETTINGS_NATIVE_FILE_SYSTEM_WRITE" - icon-class="subpage-arrow" id="native-file-system-write" + id="native-file-system-write" label="$i18n{siteSettingsNativeFileSystemWrite}" on-click="onTapNavigate_" start-icon="settings:save-original" sub-label="[[defaultSettingLabel_(
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index fd87709..b59e8a93 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -613,13 +613,14 @@ if (is_google) { config_data.SetBoolean( "richerPicker", - base::FeatureList::IsEnabled(features::kNtpCustomizationMenuV2)); + base::FeatureList::IsEnabled(ntp_features::kCustomizationMenuV2)); config_data.SetBoolean("chromeColors", base::FeatureList::IsEnabled( - features::kChromeColors)); + ntp_features::kChromeColors)); config_data.SetBoolean("chromeColorsCustomColorPicker", base::FeatureList::IsEnabled( - features::kChromeColorsCustomColorPicker)); - config_data.SetBoolean("realboxEnabled", features::IsNtpRealboxEnabled()); + ntp_features::kChromeColorsCustomColorPicker)); + config_data.SetBoolean("realboxEnabled", + ntp_features::IsRealboxEnabled()); config_data.SetBoolean( "suggestionTransparencyEnabled", base::FeatureList::IsEnabled( @@ -1033,12 +1034,12 @@ "\" as=\"image\">"; } - bool realbox_enabled = features::IsNtpRealboxEnabled(); + bool realbox_enabled = ntp_features::IsRealboxEnabled(); replacements["hiddenIfRealboxEnabled"] = realbox_enabled ? "hidden" : ""; replacements["hiddenIfRealboxDisabled"] = realbox_enabled ? "" : "hidden"; bool use_google_g_icon = - base::FeatureList::IsEnabled(features::kNtpRealboxUseGoogleGIcon); + base::FeatureList::IsEnabled(ntp_features::kRealboxUseGoogleGIcon); replacements["realboxIconClass"] = use_google_g_icon ? "google-g-icon" : "search-icon";
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc index cb95bc83c..e57b805f 100644 --- a/chrome/browser/search/ntp_features.cc +++ b/chrome/browser/search/ntp_features.cc
@@ -10,7 +10,7 @@ #include "components/omnibox/common/omnibox_features.h" #include "ui/base/ui_base_features.h" -namespace features { +namespace ntp_features { // If enabled, 'Chrome Colors' menu becomes visible in the customization picker. const base::Feature kChromeColors{"ChromeColors", @@ -22,31 +22,30 @@ // If enabled, shows a confirm dialog before removing search suggestions from // the New Tab page real search box ("realbox"). -const base::Feature kConfirmNtpSuggestionRemovals{ +const base::Feature kConfirmSuggestionRemovals{ "ConfirmNtpSuggestionRemovals", base::FEATURE_DISABLED_BY_DEFAULT}; +// If enabled, the user will see the second version of the customization picker. +const base::Feature kCustomizationMenuV2{"NtpCustomizationMenuV2", + base::FEATURE_DISABLED_BY_DEFAULT}; + // If enabled, "middle slot" promos on the bottom of the NTP will show a dismiss // UI that allows users to close them and not see them again. -const base::Feature kDismissNtpPromos{"DismissNtpPromos", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// If enabled, the user will see the second version of the customization picker. -const base::Feature kNtpCustomizationMenuV2{"NtpCustomizationMenuV2", - base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDismissPromos{"DismissNtpPromos", + base::FEATURE_DISABLED_BY_DEFAULT}; // If enabled, the real search box ("realbox") on the New Tab page will show a // Google (g) icon instead of the typical magnifying glass (aka loupe). -const base::Feature kNtpRealboxUseGoogleGIcon{ - "NtpRealboxUseGoogleGIcon", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kRealboxUseGoogleGIcon{"NtpRealboxUseGoogleGIcon", + base::FEATURE_DISABLED_BY_DEFAULT}; // If enabled, the search box in the middle of the NTP will accept input // directly (i.e. not be a "fake" box) and search results will show directly // below the non-fake input ("realbox"). -const base::Feature kNtpRealbox{"NtpRealbox", - base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kRealbox{"NtpRealbox", base::FEATURE_DISABLED_BY_DEFAULT}; -bool IsNtpRealboxEnabled() { - return base::FeatureList::IsEnabled(kNtpRealbox) || +bool IsRealboxEnabled() { + return base::FeatureList::IsEnabled(kRealbox) || base::FeatureList::IsEnabled(omnibox::kZeroSuggestionsOnNTPRealbox) || (base::FeatureList::IsEnabled(omnibox::kOnFocusSuggestions) && !OmniboxFieldTrial::GetZeroSuggestVariants( @@ -54,4 +53,4 @@ .empty()); } -} // namespace features +} // namespace ntp_features
diff --git a/chrome/browser/search/ntp_features.h b/chrome/browser/search/ntp_features.h index eb25682..6505d6c 100644 --- a/chrome/browser/search/ntp_features.h +++ b/chrome/browser/search/ntp_features.h
@@ -7,26 +7,26 @@ #include "base/feature_list.h" -namespace features { +namespace ntp_features { // The features should be documented alongside the definition of their values in // the .cc file. extern const base::Feature kChromeColors; extern const base::Feature kChromeColorsCustomColorPicker; -extern const base::Feature kConfirmNtpSuggestionRemovals; -extern const base::Feature kDismissNtpPromos; -extern const base::Feature kNtpCustomizationMenuV2; -extern const base::Feature kNtpRealboxUseGoogleGIcon; +extern const base::Feature kConfirmSuggestionRemovals; +extern const base::Feature kCustomizationMenuV2; +extern const base::Feature kDismissPromos; +extern const base::Feature kRealboxUseGoogleGIcon; // Note: only exposed for about:flags. Use IsNtpRealboxEnabled() instead. -extern const base::Feature kNtpRealbox; +extern const base::Feature kRealbox; -// Returns true if either kNtpRealbox or omnibox::kZeroSuggestionsOnNTPRealbox +// Returns true if either kRealbox or omnibox::kZeroSuggestionsOnNTPRealbox // are enabled; or omnibox::kOnFocusSuggestions is enabled and configured to // show suggestions of some type in the NTP Realbox. -bool IsNtpRealboxEnabled(); +bool IsRealboxEnabled(); -} // namespace features +} // namespace ntp_features #endif // CHROME_BROWSER_SEARCH_NTP_FEATURES_H_
diff --git a/chrome/browser/search/ntp_features_unittest.cc b/chrome/browser/search/ntp_features_unittest.cc index 2db6685..805559e 100644 --- a/chrome/browser/search/ntp_features_unittest.cc +++ b/chrome/browser/search/ntp_features_unittest.cc
@@ -11,40 +11,40 @@ #include "components/omnibox/common/omnibox_features.h" #include "testing/gtest/include/gtest/gtest.h" -namespace features { +namespace ntp_features { -TEST(NTPFeaturesTest, IsNtpRealboxEnabled) { +TEST(NTPFeaturesTest, IsRealboxEnabled) { base::test::ScopedFeatureList feature_list; - EXPECT_FALSE(IsNtpRealboxEnabled()); + EXPECT_FALSE(IsRealboxEnabled()); - feature_list.InitAndEnableFeature(kNtpRealbox); - EXPECT_TRUE(IsNtpRealboxEnabled()); + feature_list.InitAndEnableFeature(kRealbox); + EXPECT_TRUE(IsRealboxEnabled()); feature_list.Reset(); - EXPECT_FALSE(IsNtpRealboxEnabled()); + EXPECT_FALSE(IsRealboxEnabled()); feature_list.InitAndEnableFeature(omnibox::kZeroSuggestionsOnNTPRealbox); - EXPECT_TRUE(IsNtpRealboxEnabled()); + EXPECT_TRUE(IsRealboxEnabled()); feature_list.Reset(); - EXPECT_FALSE(IsNtpRealboxEnabled()); + EXPECT_FALSE(IsRealboxEnabled()); // zero-prefix suggestions are configured for the NTP Omnibox. feature_list.InitWithFeaturesAndParameters( {{omnibox::kOnFocusSuggestions, {{"ZeroSuggestVariant:7:*", "Does not matter"}}}}, {}); - EXPECT_FALSE(IsNtpRealboxEnabled()); + EXPECT_FALSE(IsRealboxEnabled()); feature_list.Reset(); - EXPECT_FALSE(IsNtpRealboxEnabled()); + EXPECT_FALSE(IsRealboxEnabled()); // zero-prefix suggestions are configured for the NTP Realbox. feature_list.InitWithFeaturesAndParameters( {{omnibox::kOnFocusSuggestions, {{"ZeroSuggestVariant:15:*", "Does not matter"}}}}, {}); - EXPECT_TRUE(IsNtpRealboxEnabled()); + EXPECT_TRUE(IsRealboxEnabled()); } -} // namespace features +} // namespace ntp_features
diff --git a/chrome/browser/search/promos/promo_service.cc b/chrome/browser/search/promos/promo_service.cc index 4e040c0..1c94e886 100644 --- a/chrome/browser/search/promos/promo_service.cc +++ b/chrome/browser/search/promos/promo_service.cc
@@ -41,7 +41,7 @@ const char kXSSIResponsePreamble[] = ")]}'"; bool CanBlockPromos() { - return base::FeatureList::IsEnabled(features::kDismissNtpPromos); + return base::FeatureList::IsEnabled(ntp_features::kDismissPromos); } GURL GetGoogleBaseUrl() {
diff --git a/chrome/browser/search/promos/promo_service_unittest.cc b/chrome/browser/search/promos/promo_service_unittest.cc index e914032f..53db672 100644 --- a/chrome/browser/search/promos/promo_service_unittest.cc +++ b/chrome/browser/search/promos/promo_service_unittest.cc
@@ -157,7 +157,7 @@ TEST_F(PromoServiceTest, GoodPromoResponseCanDismiss) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); std::string response_string = "{\"update\":{\"promos\":{\"middle\":\"<style></style><div><script></" @@ -180,7 +180,7 @@ TEST_F(PromoServiceTest, GoodPromoResponseNoIdField) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); std::string response_string = "{\"update\":{\"promos\":{\"middle\":\"<style></style><div><script></" @@ -203,7 +203,7 @@ TEST_F(PromoServiceTest, GoodPromoResponseNoIdFieldNorLogUrl) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); std::string response_string = "{\"update\":{\"promos\":{\"middle\":\"<style></style><div><script></" @@ -224,7 +224,7 @@ TEST_F(PromoServiceTest, GoodPromoWithBlockedID) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); { DictionaryPrefUpdate update(prefs(), prefs::kNtpPromoBlocklist); @@ -248,7 +248,7 @@ TEST_F(PromoServiceTest, BlocklistPromo) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); std::string response_string = "{\"update\":{\"promos\":{\"middle\":\"<style></style><div><script></" @@ -282,7 +282,7 @@ TEST_F(PromoServiceTest, BlocklistExpiration) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); { DictionaryPrefUpdate update(prefs(), prefs::kNtpPromoBlocklist); @@ -316,7 +316,7 @@ TEST_F(PromoServiceTest, BlocklistWrongExpiryType) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kDismissNtpPromos); + feature_list.InitAndEnableFeature(ntp_features::kDismissPromos); { DictionaryPrefUpdate update(prefs(), prefs::kNtpPromoBlocklist);
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc index e0f2e77..0e2bed83b 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
@@ -85,6 +85,7 @@ return nullptr; return std::make_unique<SharingService>( + &profile_, /* sync_prefs= */ nullptr, /* vapid_key_manager= */ nullptr, std::make_unique<MockSharingDeviceRegistration>(), @@ -96,8 +97,7 @@ /* gcm_driver= */ nullptr, /* device_info_tracker= */ nullptr, /* local_device_info_provider= */ nullptr, - /* sync_service */ nullptr, - /* notification_display_service= */ nullptr); + /* sync_service */ nullptr); } base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/mock_sharing_service.cc b/chrome/browser/sharing/mock_sharing_service.cc index 850f9fa3..0d1c6020 100644 --- a/chrome/browser/sharing/mock_sharing_service.cc +++ b/chrome/browser/sharing/mock_sharing_service.cc
@@ -11,6 +11,7 @@ MockSharingService::MockSharingService() : SharingService( + /*profile=*/nullptr, /*sync_prefs=*/nullptr, /*vapid_key_manager=*/nullptr, std::make_unique<SharingDeviceRegistration>( @@ -26,7 +27,6 @@ /*gcm_driver=*/nullptr, /*device_info_tracker=*/nullptr, /*local_device_info_provider=*/nullptr, - /*sync_service*/ nullptr, - /*notification_display_service=*/nullptr) {} + /*sync_service*/ nullptr) {} MockSharingService::~MockSharingService() = default;
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_browsertest.cc b/chrome/browser/sharing/shared_clipboard/remote_copy_browsertest.cc new file mode 100644 index 0000000..d846c76 --- /dev/null +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_browsertest.cc
@@ -0,0 +1,109 @@ +// 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 <memory> +#include <string> + +#include "base/guid.h" +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sharing/shared_clipboard/feature_flags.h" +#include "chrome/browser/sharing/sharing_constants.h" +#include "chrome/browser/sharing/sharing_fcm_handler.h" +#include "chrome/browser/sharing/sharing_service.h" +#include "chrome/browser/sharing/sharing_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/test/test_clipboard.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" + +namespace { +const char kText[] = "clipboard text"; +const char kDeviceName[] = "DeviceName"; +} // namespace + +// Browser tests for the Remote Copy feature. +class RemoteCopyBrowserTestBase : public InProcessBrowserTest { + public: + RemoteCopyBrowserTestBase() = default; + ~RemoteCopyBrowserTestBase() override = default; + + void SetUpOnMainThread() override { + ui::TestClipboard::CreateForCurrentThread(); + notification_tester_ = std::make_unique<NotificationDisplayServiceTester>( + browser()->profile()); + sharing_service_ = + SharingServiceFactory::GetForBrowserContext(browser()->profile()); + } + + void TearDownOnMainThread() override { + notification_tester_.reset(); + ui::Clipboard::DestroyClipboardForCurrentThread(); + } + + gcm::IncomingMessage CreateMessage(std::string guid, + std::string device_name, + std::string text) { + chrome_browser_sharing::SharingMessage sharing_message; + sharing_message.set_sender_guid(guid); + sharing_message.set_sender_device_name(device_name); + sharing_message.mutable_remote_copy_message()->set_text(text); + + gcm::IncomingMessage incoming_message; + std::string serialized_sharing_message; + sharing_message.SerializeToString(&serialized_sharing_message); + incoming_message.raw_data = serialized_sharing_message; + return incoming_message; + } + + std::string GetClipboardText() { + base::string16 text; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &text); + return base::UTF16ToUTF8(text); + } + + message_center::Notification GetNotification() { + auto notifications = notification_tester_->GetDisplayedNotificationsForType( + NotificationHandler::Type::SHARING); + EXPECT_EQ(notifications.size(), 1u); + + const message_center::Notification& notification = notifications[0]; + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, notification.type()); + + return notification; + } + + protected: + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; + SharingService* sharing_service_; + + private: + DISALLOW_COPY_AND_ASSIGN(RemoteCopyBrowserTestBase); +}; + +class RemoteCopyBrowserTest : public RemoteCopyBrowserTestBase { + public: + RemoteCopyBrowserTest() { + feature_list_.InitWithFeatures({kRemoteCopyReceiver}, {}); + } +}; + +IN_PROC_BROWSER_TEST_F(RemoteCopyBrowserTest, HandleMessage) { + sharing_service_->GetFCMHandlerForTesting()->OnMessage( + kSharingFCMAppID, + CreateMessage(base::GenerateGUID(), kDeviceName, kText)); + EXPECT_EQ(GetClipboardText(), kText); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_NOTIFICATION_TITLE, + base::ASCIIToUTF16(kDeviceName)), + GetNotification().title()); +}
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc index 5f5ced12..d998f10 100644 --- a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc
@@ -10,6 +10,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/grit/generated_resources.h" #include "components/sync/protocol/sharing_message.pb.h" #include "components/sync/protocol/sharing_remote_copy_message.pb.h" @@ -22,9 +23,8 @@ #include "ui/message_center/public/cpp/notifier_id.h" #include "url/gurl.h" -RemoteCopyMessageHandler::RemoteCopyMessageHandler( - NotificationDisplayService* notification_display_service) - : notification_display_service_(notification_display_service) {} +RemoteCopyMessageHandler::RemoteCopyMessageHandler(Profile* profile) + : profile_(profile) {} RemoteCopyMessageHandler::~RemoteCopyMessageHandler() = default; @@ -43,8 +43,6 @@ void RemoteCopyMessageHandler::ShowNotification( const std::string& device_name) { - DCHECK(notification_display_service_); - std::string notification_id = base::GenerateGUID(); // TODO(mvanouwerkerk): Adjust notification text and icon once we have mocks. @@ -67,6 +65,6 @@ message_center::RichNotificationData(), /*delegate=*/nullptr); - notification_display_service_->Display(NotificationHandler::Type::SHARING, - notification, /*metadata=*/nullptr); + NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( + NotificationHandler::Type::SHARING, notification, /*metadata=*/nullptr); }
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.h b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.h index 8cdd22f5..5514d79e 100644 --- a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.h +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.h
@@ -10,13 +10,12 @@ #include "base/macros.h" #include "chrome/browser/sharing/sharing_message_handler.h" -class NotificationDisplayService; +class Profile; // Handles incoming messages for the remote copy feature. class RemoteCopyMessageHandler : public SharingMessageHandler { public: - explicit RemoteCopyMessageHandler( - NotificationDisplayService* notification_display_service); + explicit RemoteCopyMessageHandler(Profile* profile); ~RemoteCopyMessageHandler() override; // SharingMessageHandler implementation: @@ -26,7 +25,7 @@ private: void ShowNotification(const std::string& device_name); - NotificationDisplayService* notification_display_service_ = nullptr; + Profile* profile_ = nullptr; DISALLOW_COPY_AND_ASSIGN(RemoteCopyMessageHandler); };
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc index 525756d..908d9d5 100644 --- a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc
@@ -7,13 +7,14 @@ #include "base/bind_helpers.h" #include "base/guid.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/notifications/stub_notification_display_service.h" #include "chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/testing_profile.h" #include "components/sync/protocol/sharing_message.pb.h" #include "components/sync/protocol/sharing_remote_copy_message.pb.h" #include "components/sync/protocol/sync_enums.pb.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" namespace { @@ -29,8 +30,7 @@ void SetUp() override { SharedClipboardTestBase::SetUp(); - message_handler_ = std::make_unique<RemoteCopyMessageHandler>( - notification_display_service_.get()); + message_handler_ = std::make_unique<RemoteCopyMessageHandler>(&profile_); } chrome_browser_sharing::SharingMessage CreateMessage(std::string guid,
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.cc index 5c0e1ae..5a48a23 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.cc +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.cc
@@ -8,6 +8,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/notifications/notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image.h" @@ -17,17 +18,14 @@ SharedClipboardMessageHandlerDesktop::SharedClipboardMessageHandlerDesktop( SharingService* sharing_service, - NotificationDisplayService* notification_display_service) - : SharedClipboardMessageHandler(sharing_service), - notification_display_service_(notification_display_service) {} + Profile* profile) + : SharedClipboardMessageHandler(sharing_service), profile_(profile) {} SharedClipboardMessageHandlerDesktop::~SharedClipboardMessageHandlerDesktop() = default; void SharedClipboardMessageHandlerDesktop::ShowNotification( const std::string& device_name) { - DCHECK(notification_display_service_); - std::string notification_id = base::GenerateGUID(); base::string16 notification_title = @@ -49,6 +47,7 @@ message_center::RichNotificationData(), /* delegate= */ nullptr); - notification_display_service_->Display(NotificationHandler::Type::SHARING, - notification, /* metadata= */ nullptr); + NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( + NotificationHandler::Type::SHARING, notification, + /* metadata= */ nullptr); }
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h index 9e8c2fb..5604ce0 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h
@@ -8,23 +8,22 @@ #include "base/macros.h" #include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler.h" -class NotificationDisplayService; +class Profile; class SharingService; // Handles incoming messages for the shared clipboard feature. class SharedClipboardMessageHandlerDesktop : public SharedClipboardMessageHandler { public: - SharedClipboardMessageHandlerDesktop( - SharingService* sharing_service, - NotificationDisplayService* notification_display_service); + SharedClipboardMessageHandlerDesktop(SharingService* sharing_service, + Profile* profile); ~SharedClipboardMessageHandlerDesktop() override; private: // SharedClipboardMessageHandler implementation. void ShowNotification(const std::string& device_name) override; - NotificationDisplayService* notification_display_service_ = nullptr; + Profile* profile_ = nullptr; DISALLOW_COPY_AND_ASSIGN(SharedClipboardMessageHandlerDesktop); };
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop_unittest.cc index d208ac5..f324e57 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop_unittest.cc +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop_unittest.cc
@@ -7,15 +7,16 @@ #include "base/guid.h" #include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" -#include "chrome/browser/notifications/stub_notification_display_service.h" #include "chrome/browser/sharing/mock_sharing_service.h" #include "chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/testing_profile.h" #include "components/sync/protocol/sharing_shared_clipboard_message.pb.h" #include "components/sync/protocol/sync_enums.pb.h" #include "components/sync_device_info/device_info.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/public/cpp/notification.h" namespace { @@ -33,7 +34,7 @@ void SetUp() override { SharedClipboardTestBase::SetUp(); message_handler_ = std::make_unique<SharedClipboardMessageHandlerDesktop>( - sharing_service_.get(), notification_display_service_.get()); + sharing_service_.get(), &profile_); } chrome_browser_sharing::SharingMessage CreateMessage(std::string guid,
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc index fb2e176..cbce9514 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/notifications/stub_notification_display_service.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/sharing/mock_sharing_service.h" #include "components/sync/protocol/sharing_message.pb.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,8 +18,8 @@ SharedClipboardTestBase::~SharedClipboardTestBase() = default; void SharedClipboardTestBase::SetUp() { - notification_display_service_ = - std::make_unique<StubNotificationDisplayService>(&profile_); + notification_tester_ = + std::make_unique<NotificationDisplayServiceTester>(&profile_); sharing_service_ = std::make_unique<MockSharingService>(); ui::TestClipboard::CreateForCurrentThread(); } @@ -45,9 +45,8 @@ } message_center::Notification SharedClipboardTestBase::GetNotification() { - auto notifications = - notification_display_service_->GetDisplayedNotificationsForType( - NotificationHandler::Type::SHARING); + auto notifications = notification_tester_->GetDisplayedNotificationsForType( + NotificationHandler::Type::SHARING); EXPECT_EQ(notifications.size(), 1u); const message_center::Notification& notification = notifications[0];
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h index 007af78..f9a95d8 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.h
@@ -14,7 +14,7 @@ #include "testing/gtest/include/gtest/gtest.h" class MockSharingService; -class StubNotificationDisplayService; +class NotificationDisplayServiceTester; namespace chrome_browser_sharing { class SharingMessage; @@ -42,9 +42,9 @@ protected: content::BrowserTaskEnvironment task_environment_; - std::unique_ptr<StubNotificationDisplayService> notification_display_service_; - std::unique_ptr<MockSharingService> sharing_service_; TestingProfile profile_; + std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; + std::unique_ptr<MockSharingService> sharing_service_; private: DISALLOW_COPY_AND_ASSIGN(SharedClipboardTestBase);
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc index 3ba3cf38..d33aa94 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc
@@ -69,6 +69,7 @@ return nullptr; return std::make_unique<SharingService>( + &profile_, /* sync_prefs= */ nullptr, /* vapid_key_manager= */ nullptr, std::make_unique<MockSharingDeviceRegistration>(), @@ -80,8 +81,7 @@ /* gcm_driver= */ nullptr, /* device_info_tracker= */ nullptr, /* local_device_info_provider= */ nullptr, - /* sync_service */ nullptr, - /* notification_display_service= */ nullptr); + /* sync_service */ nullptr); } base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc index 83f6368..5031af30 100644 --- a/chrome/browser/sharing/sharing_service.cc +++ b/chrome/browser/sharing/sharing_service.cc
@@ -50,6 +50,7 @@ #endif SharingService::SharingService( + Profile* profile, std::unique_ptr<SharingSyncPreference> sync_prefs, std::unique_ptr<VapidKeyManager> vapid_key_manager, std::unique_ptr<SharingDeviceRegistration> sharing_device_registration, @@ -59,8 +60,7 @@ gcm::GCMDriver* gcm_driver, syncer::DeviceInfoTracker* device_info_tracker, syncer::LocalDeviceInfoProvider* local_device_info_provider, - syncer::SyncService* sync_service, - NotificationDisplayService* notification_display_service) + syncer::SyncService* sync_service) : sync_prefs_(std::move(sync_prefs)), vapid_key_manager_(std::move(vapid_key_manager)), sharing_device_registration_(std::move(sharing_device_registration)), @@ -118,8 +118,7 @@ std::make_unique<SharedClipboardMessageHandlerAndroid>(this); #else shared_clipboard_message_handler_ = - std::make_unique<SharedClipboardMessageHandlerDesktop>( - this, notification_display_service); + std::make_unique<SharedClipboardMessageHandlerDesktop>(this, profile); #endif // defined(OS_ANDROID) fcm_handler_->AddSharingHandler( chrome_browser_sharing::SharingMessage::kSharedClipboardMessage, @@ -129,8 +128,8 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \ defined(OS_CHROMEOS) if (sharing_device_registration_->IsRemoteCopySupported()) { - remote_copy_message_handler_ = std::make_unique<RemoteCopyMessageHandler>( - notification_display_service); + remote_copy_message_handler_ = + std::make_unique<RemoteCopyMessageHandler>(profile); fcm_handler_->AddSharingHandler( chrome_browser_sharing::SharingMessage::kRemoteCopyMessage, remote_copy_message_handler_.get()); @@ -244,6 +243,10 @@ return sync_prefs_.get(); } +SharingFCMHandler* SharingService::GetFCMHandlerForTesting() const { + return fcm_handler_.get(); +} + void SharingService::OnDeviceInfoChange() { if (!device_info_tracker_->IsSyncing() || !local_device_info_provider_->GetLocalDeviceInfo()) {
diff --git a/chrome/browser/sharing/sharing_service.h b/chrome/browser/sharing/sharing_service.h index 52206c9..f89a437 100644 --- a/chrome/browser/sharing/sharing_service.h +++ b/chrome/browser/sharing/sharing_service.h
@@ -43,7 +43,7 @@ class SyncService; } // namespace syncer -class NotificationDisplayService; +class Profile; class RemoteCopyMessageHandler; class SharedClipboardMessageHandler; class SharingFCMHandler; @@ -73,6 +73,7 @@ }; SharingService( + Profile* profile, std::unique_ptr<SharingSyncPreference> sync_prefs, std::unique_ptr<VapidKeyManager> vapid_key_manager, std::unique_ptr<SharingDeviceRegistration> sharing_device_registration, @@ -82,8 +83,7 @@ gcm::GCMDriver* gcm_driver, syncer::DeviceInfoTracker* device_info_tracker, syncer::LocalDeviceInfoProvider* local_device_info_provider, - syncer::SyncService* sync_service, - NotificationDisplayService* notification_display_service); + syncer::SyncService* sync_service); ~SharingService() override; // Returns the device matching |guid|, or nullptr if no match was found. @@ -126,6 +126,9 @@ // Returns SharingSyncPreference for integration tests. SharingSyncPreference* GetSyncPreferencesForTesting() const; + // Returns SharingFCMHandler for testing. + SharingFCMHandler* GetFCMHandlerForTesting() const; + private: // Overrides for syncer::SyncServiceObserver. void OnSyncShutdown(syncer::SyncService* sync) override;
diff --git a/chrome/browser/sharing/sharing_service_factory.cc b/chrome/browser/sharing/sharing_service_factory.cc index d4a975a..186e317 100644 --- a/chrome/browser/sharing/sharing_service_factory.cc +++ b/chrome/browser/sharing/sharing_service_factory.cc
@@ -9,7 +9,6 @@ #include "base/memory/singleton.h" #include "chrome/browser/gcm/gcm_profile_service_factory.h" #include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h" -#include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sharing/sharing_device_registration.h" #include "chrome/browser/sharing/sharing_fcm_handler.h" @@ -53,7 +52,6 @@ DependsOn(instance_id::InstanceIDProfileServiceFactory::GetInstance()); DependsOn(DeviceInfoSyncServiceFactory::GetInstance()); DependsOn(ProfileSyncServiceFactory::GetInstance()); - DependsOn(NotificationDisplayServiceFactory::GetInstance()); } SharingServiceFactory::~SharingServiceFactory() = default; @@ -81,9 +79,6 @@ syncer::LocalDeviceInfoProvider* local_device_info_provider = device_info_sync_service->GetLocalDeviceInfoProvider(); - NotificationDisplayService* notification_display_service = - NotificationDisplayServiceFactory::GetForProfile(profile); - std::unique_ptr<SharingSyncPreference> sync_prefs = std::make_unique<SharingSyncPreference>(profile->GetPrefs(), device_info_sync_service); @@ -103,12 +98,11 @@ std::make_unique<SharingMessageSender>(fcm_sender.get(), sync_prefs.get(), local_device_info_provider); - return new SharingService(std::move(sync_prefs), std::move(vapid_key_manager), - std::move(sharing_device_registration), - std::move(fcm_sender), std::move(fcm_handler), - std::move(sharing_message_sender), gcm_driver, - device_info_tracker, local_device_info_provider, - sync_service, notification_display_service); + return new SharingService( + profile, std::move(sync_prefs), std::move(vapid_key_manager), + std::move(sharing_device_registration), std::move(fcm_sender), + std::move(fcm_handler), std::move(sharing_message_sender), gcm_driver, + device_info_tracker, local_device_info_provider, sync_service); } content::BrowserContext* SharingServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/sharing/sharing_service_unittest.cc b/chrome/browser/sharing/sharing_service_unittest.cc index 9f8722e9..56bda61 100644 --- a/chrome/browser/sharing/sharing_service_unittest.cc +++ b/chrome/browser/sharing/sharing_service_unittest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/sharing/sharing_fcm_sender.h" #include "chrome/browser/sharing/sharing_sync_preference.h" #include "chrome/browser/sharing/vapid_key_manager.h" +#include "chrome/test/base/testing_profile.h" #include "components/gcm_driver/crypto/gcm_encryption_provider.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/sync/driver/test_sync_service.h" @@ -215,14 +216,14 @@ SharingService* GetSharingService() { if (!sharing_service_) { sharing_service_ = std::make_unique<SharingService>( - base::WrapUnique(sync_prefs_), base::WrapUnique(vapid_key_manager_), + &profile_, base::WrapUnique(sync_prefs_), + base::WrapUnique(vapid_key_manager_), base::WrapUnique(sharing_device_registration_), nullptr, base::WrapUnique(fcm_handler_), base::WrapUnique(sharing_message_sender_), nullptr, fake_device_info_sync_service.GetDeviceInfoTracker(), fake_device_info_sync_service.GetLocalDeviceInfoProvider(), - &test_sync_service_, - /* notification_display_service= */ nullptr); + &test_sync_service_); } task_environment_.RunUntilIdle(); return sharing_service_.get(); @@ -231,6 +232,7 @@ base::test::ScopedFeatureList scoped_feature_list_; content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + TestingProfile profile_; syncer::FakeDeviceInfoSyncService fake_device_info_sync_service; syncer::TestSyncService test_sync_service_;
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc index 9c9a95a..17a5aae 100644 --- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc
@@ -72,8 +72,6 @@ base::SimpleTestClock* test_clock() { return test_clock_; } private: - base::ScopedTempDir scoped_dir_; - content::BrowserTaskEnvironment task_environment_; base::HistogramTester histogram_tester_; TestingProfile testing_profile_;
diff --git a/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/chrome/browser/sync/profile_sync_service_factory_unittest.cc index 9e0ff42..1a6f92245 100644 --- a/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -46,7 +46,7 @@ // Returns the collection of default datatypes. std::vector<syncer::ModelType> DefaultDatatypes() { - static_assert(41 == syncer::ModelType::NUM_ENTRIES, + static_assert(40 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled).");
diff --git a/chrome/browser/sync/test/integration/encryption_helper.cc b/chrome/browser/sync/test/integration/encryption_helper.cc index 48873c8..25b667e 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.cc +++ b/chrome/browser/sync/test/integration/encryption_helper.cc
@@ -161,6 +161,28 @@ expected_passphrase_type_; } +ServerNigoriKeyNameChecker::ServerNigoriKeyNameChecker( + const std::string& expected_key_name, + syncer::ProfileSyncService* service, + fake_server::FakeServer* fake_server) + : SingleClientStatusChangeChecker(service), + fake_server_(fake_server), + expected_key_name_(expected_key_name) {} + +bool ServerNigoriKeyNameChecker::IsExitConditionSatisfied(std::ostream* os) { + std::vector<sync_pb::SyncEntity> nigori_entities = + fake_server_->GetPermanentSyncEntitiesByModelType(syncer::NIGORI); + DCHECK_EQ(nigori_entities.size(), 1U); + + const std::string given_key_name = + nigori_entities[0].specifics().nigori().encryption_keybag().key_name(); + + *os << "Waiting for a Nigori node with proper key bag encryption key name (" + << expected_key_name_ << ") to become available on the server." + << "The server key bag encryption key name is " << given_key_name << "."; + return given_key_name == expected_key_name_; +} + PassphraseRequiredStateChecker::PassphraseRequiredStateChecker( syncer::ProfileSyncService* service, bool desired_state)
diff --git a/chrome/browser/sync/test/integration/encryption_helper.h b/chrome/browser/sync/test/integration/encryption_helper.h index 011d184..02ed85e0 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.h +++ b/chrome/browser/sync/test/integration/encryption_helper.h
@@ -64,6 +64,21 @@ const syncer::PassphraseType expected_passphrase_type_; }; +// Checker used to block until a Nigori with a given keybag encryption key name +// is available on the server. +class ServerNigoriKeyNameChecker : public SingleClientStatusChangeChecker { + public: + ServerNigoriKeyNameChecker(const std::string& expected_key_name, + syncer::ProfileSyncService* service, + fake_server::FakeServer* fake_server); + + bool IsExitConditionSatisfied(std::ostream* os) override; + + private: + fake_server::FakeServer* const fake_server_; + const std::string expected_key_name_; +}; + // Checker used to block until Sync requires or stops requiring a passphrase. class PassphraseRequiredStateChecker : public SingleClientStatusChangeChecker { public:
diff --git a/chrome/browser/sync/test/integration/preferences_helper.cc b/chrome/browser/sync/test/integration/preferences_helper.cc index bcb6a8ae..0b5351a 100644 --- a/chrome/browser/sync/test/integration/preferences_helper.cc +++ b/chrome/browser/sync/test/integration/preferences_helper.cc
@@ -108,14 +108,8 @@ } scoped_refptr<PrefStore> BuildPrefStoreFromPrefsFile(Profile* profile) { - profile->GetPrefs()->CommitPendingWrite(); - // Writes are scheduled on the IO thread. The JsonPrefStore requires all - // access (construction, Get, Set, ReadPrefs) to be made from the same thread. - // So instead of reading the file from the IO thread, we simply schedule a - // dummy task to avoid races with writing the file and reading it. base::RunLoop run_loop; - profile->GetIOTaskRunner()->PostTask(FROM_HERE, - base::BindOnce(run_loop.QuitClosure())); + profile->GetPrefs()->CommitPendingWrite(run_loop.QuitClosure()); run_loop.Run(); auto pref_store = base::MakeRefCounted<JsonPrefStore>( @@ -124,6 +118,7 @@ if (pref_store->ReadPrefs() != PersistentPrefStore::PREF_READ_ERROR_NONE) { ADD_FAILURE() << " Failed reading the prefs file into the store."; } + return pref_store; }
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 053fff09..a8bc2d69 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -68,11 +68,16 @@ if (service()->IsEngineInitialized()) return true; // Engine initialization is blocked by an auth error. - if (HasAuthError(service())) + if (HasAuthError(service())) { + LOG(WARNING) << "Sync engine initialization blocked by auth error"; return true; + } // Engine initialization is blocked by a failure to fetch Oauth2 tokens. - if (service()->IsRetryingAccessTokenFetchForTest()) + if (service()->IsRetryingAccessTokenFetchForTest()) { + LOG(WARNING) << "Sync engine initialization blocked by failure to fetch " + "access tokens"; return true; + } // Still waiting on engine initialization. return false; } @@ -460,13 +465,18 @@ return false; } - if (!service()->IsEngineInitialized()) { - LOG(ERROR) << "Service engine not initialized."; + if (HasAuthError(service())) { + LOG(ERROR) << "Credentials were rejected. Sync cannot proceed."; return false; } - if (HasAuthError(service())) { - LOG(ERROR) << "Credentials were rejected. Sync cannot proceed."; + if (service()->IsRetryingAccessTokenFetchForTest()) { + LOG(ERROR) << "Failed to fetch access token. Sync cannot proceed."; + return false; + } + + if (!service()->IsEngineInitialized()) { + LOG(ERROR) << "Service engine not initialized."; return false; }
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc index f42e7276..ed29112 100644 --- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -69,6 +69,14 @@ std::move(encoded_key)}; } +std::string ComputeKeyName(const KeyParams& key_params) { + std::string key_name; + syncer::Nigori::CreateByDerivation(key_params.derivation_params, + key_params.password) + ->Permute(syncer::Nigori::Password, syncer::kNigoriKeyName, &key_name); + return key_name; +} + // Builds NigoriSpecifics with following fields: // 1. encryption_keybag contains all keys derived from |keybag_keys_params| // and encrypted with a key derived from |keybag_decryptor_params|. @@ -329,6 +337,22 @@ } IN_PROC_BROWSER_TEST_P(SingleClientNigoriSyncTestWithUssTests, + ShouldRotateKeystoreKey) { + ASSERT_TRUE(SetupSync()); + + GetFakeServer()->TriggerKeystoreKeyRotation(); + const std::vector<std::string>& keystore_keys = + GetFakeServer()->GetKeystoreKeys(); + ASSERT_THAT(keystore_keys, SizeIs(2)); + const KeyParams new_keystore_key_params = KeystoreKeyParams(keystore_keys[1]); + const std::string expected_key_bag_key_name = + ComputeKeyName(new_keystore_key_params); + EXPECT_TRUE(ServerNigoriKeyNameChecker(expected_key_bag_key_name, + GetSyncService(0), GetFakeServer()) + .Wait()); +} + +IN_PROC_BROWSER_TEST_P(SingleClientNigoriSyncTestWithUssTests, ShouldExposeExperimentalAuthenticationKey) { const std::vector<std::string>& keystore_keys = GetFakeServer()->GetKeystoreKeys(); @@ -370,16 +394,22 @@ PRE_ShouldCompleteKeystoreInitializationAfterRestart) { GetFakeServer()->TriggerCommitError(sync_pb::SyncEnums::THROTTLED); ASSERT_TRUE(SetupSync()); + + sync_pb::NigoriSpecifics specifics; + ASSERT_TRUE(GetServerNigori(GetFakeServer(), &specifics)); + ASSERT_EQ(specifics.passphrase_type(), + sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE); } // After browser restart the client should commit initialized Nigori. IN_PROC_BROWSER_TEST_P(SingleClientNigoriSyncTestWithNotAwaitQuiescence, ShouldCompleteKeystoreInitializationAfterRestart) { + sync_pb::NigoriSpecifics specifics; + ASSERT_TRUE(GetServerNigori(GetFakeServer(), &specifics)); + ASSERT_EQ(specifics.passphrase_type(), + sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE); + ASSERT_TRUE(SetupClients()); - ASSERT_TRUE(ServerNigoriChecker(GetSyncService(0), GetFakeServer(), - syncer::PassphraseType::kImplicitPassphrase) - .Wait()); - GetFakeServer()->TriggerCommitError(sync_pb::SyncEnums::SUCCESS); EXPECT_TRUE(ServerNigoriChecker(GetSyncService(0), GetFakeServer(), syncer::PassphraseType::kKeystorePassphrase) .Wait());
diff --git a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc index 34b0ca23..78f1c9b5 100644 --- a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.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 <map> + #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" @@ -11,6 +13,7 @@ #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/json_pref_store.h" @@ -34,7 +37,33 @@ ~SingleClientPreferencesSyncTest() override {} + // If non-empty, |contents| will be written to the Preferences file of the + // profile at |index| before that Profile object is created. + void SetPreexistingPreferencesFileContents(int index, + const std::string& contents) { + preexisting_preferences_file_contents_[index] = contents; + } + + protected: + void BeforeSetupClient(int index, + const base::FilePath& profile_path) override { + const std::string& contents = preexisting_preferences_file_contents_[index]; + if (contents.empty()) { + return; + } + + base::FilePath pref_path(profile_path.Append(chrome::kPreferencesFilename)); + ASSERT_TRUE(base::CreateDirectory(profile_path)); + ASSERT_NE(-1, + base::WriteFile(pref_path, contents.c_str(), contents.size())); + } + private: + // The contents to be written to a profile's Preferences file before the + // Profile object is created. If empty, no preexisting file will be written. + // The map key corresponds to the profile's index. + std::map<int, std::string> preexisting_preferences_file_contents_; + DISALLOW_COPY_AND_ASSIGN(SingleClientPreferencesSyncTest); };
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index 8fc3b2c..f3bc200 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -348,7 +348,8 @@ return entry->GetHttpStatusCode() == 200; } -void SyncTest::BeforeSetupClient(int index) {} +void SyncTest::BeforeSetupClient(int index, + const base::FilePath& profile_path) {} bool SyncTest::CreateProfile(int index) { base::FilePath profile_path; @@ -383,6 +384,8 @@ base::StringPrintf("SyncIntegrationTestClient%d", index)); } + BeforeSetupClient(index, profile_path); + if (UsingExternalServers()) { // If running against an EXTERNAL_LIVE_SERVER, we signin profiles using real // GAIA server. This requires creating profiles with no test hooks. @@ -435,27 +438,6 @@ } Profile* SyncTest::MakeTestProfile(base::FilePath profile_path, int index) { - const auto& preference_contents_it = - preexisting_preferences_file_contents_.find(index); - if (preference_contents_it != preexisting_preferences_file_contents_.end() && - !preference_contents_it->second.empty()) { - // The profile directory might not exist yet (e.g. for the verifier_ - // profile). - if (!base::PathExists(profile_path) && - !base::CreateDirectory(profile_path)) { - LOG(FATAL) << "Could not create profile directory: " << profile_path; - } - base::FilePath pref_path(profile_path.Append(chrome::kPreferencesFilename)); - int write_result = - base::WriteFile(pref_path, preference_contents_it->second.c_str(), - preference_contents_it->second.size()); - if (write_result != - static_cast<int>(preference_contents_it->second.size())) { - LOG(FATAL) << "Preexisting Preferences file could not be written to " - << pref_path; - } - } - std::unique_ptr<Profile> profile = Profile::CreateProfile(profile_path, profile_delegates_[index].get(), Profile::CREATE_MODE_SYNCHRONOUS); @@ -598,7 +580,6 @@ #endif for (int i = 0; i < num_clients_; ++i) { - BeforeSetupClient(i); if (!CreateProfile(i)) { return false; } @@ -1203,9 +1184,3 @@ return nullptr; #endif } - -void SyncTest::SetPreexistingPreferencesFileContents( - int index, - const std::string& contents) { - preexisting_preferences_file_contents_[index] = contents; -}
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index 16b5bf3..97abb9a 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -289,18 +289,14 @@ void OnWillCreateBrowserContextServices(content::BrowserContext* context); - virtual void BeforeSetupClient(int index); + // Invoked immediately before creating profile |index| under |profile_path|. + virtual void BeforeSetupClient(int index, const base::FilePath& profile_path); // Implementations of the EnableNotifications() and DisableNotifications() // functions defined above. void DisableNotificationsImpl(); void EnableNotificationsImpl(); - // If non-empty, |contents| will be written to the Preferences file of the - // profile at |index| before that Profile object is created. - void SetPreexistingPreferencesFileContents(int index, - const std::string& contents); - // Helper to ProfileManager::CreateProfileAsync that creates a new profile // used for UI Signin. Blocks until profile is created. static Profile* MakeProfileForUISignin(base::FilePath profile_path); @@ -360,9 +356,8 @@ instance_id::InstanceIDDriver* instance_id_driver, content::BrowserContext* context); - // Helper to Profile::CreateProfile that handles path creation, setting up - // preexisting pref files, and registering the created profile as a testing - // profile. + // Helper to Profile::CreateProfile that handles path creation. It creates + // a profile then registers it as a testing profile. Profile* MakeTestProfile(base::FilePath profile_path, int index); // Helper method used to create a Gaia account at runtime. @@ -511,11 +506,6 @@ // creation via http requests. bool create_gaia_account_at_runtime_; - // The contents to be written to a profile's Preferences file before the - // Profile object is created. If empty, no preexisting file will be written. - // The map key corresponds to the profile's index. - std::map<int, std::string> preexisting_preferences_file_contents_; - // Disable extension install verification. extensions::ScopedInstallVerifierBypassForTest ignore_install_verification_;
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 86e295f..16f24c1 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
@@ -2,6 +2,7 @@ // 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 "base/guid.h" @@ -189,39 +190,39 @@ DISALLOW_COPY_AND_ASSIGN(TwoClientPreferencesSyncTestWithSelfNotifications); }; -// Flaky. https://crbug.com/1012688 -// This was E2E_ENABLED(ShouldKeepLocalDataOnTypeMismatch). IN_PROC_BROWSER_TEST_F(TwoClientPreferencesSyncTestWithSelfNotifications, - DISABLED_ShouldKeepLocalDataOnTypeMismatch) { + E2E_ENABLED(ShouldKeepLocalDataOnTypeMismatch)) { ResetSyncForPrimaryAccount(); - // Client 1 has type-conflicting data in it's pref file. Verify that incoming - // values from sync of other type do not modify the local state. - SetPreexistingPreferencesFileContents( - 1, "{\"testing\":{\"my-test-preference\": \"some-string\"}}"); ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; constexpr char pref_name[] = "testing.my-test-preference"; + constexpr char string_value[] = "some-string"; + + // Client 0 registers a boolean preference, client 1 registers a string. GetRegistry(GetProfile(0)) ->RegisterBooleanPref(pref_name, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + GetRegistry(GetProfile(1)) + ->RegisterStringPref(pref_name, "", + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + + // Set non-default values on both clients. + ChangeBooleanPref(0, pref_name); + ChangeStringPref(1, pref_name, string_value); + ASSERT_THAT(GetPrefs(0)->GetBoolean(pref_name), Eq(true)); + ASSERT_THAT(GetPrefs(1)->GetString(pref_name), Eq(string_value)); + + // Start sync and await until they sync mutually. + base::HistogramTester histogram_tester; ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ChangeBooleanPref(0, pref_name); - ASSERT_THAT(GetPrefs(0)->GetBoolean(pref_name), Eq(true)); - GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)); + // Verify that neither of the clients got updated, because of type mismatch. + EXPECT_THAT(GetPrefs(0)->GetBoolean(pref_name), Eq(true)); + EXPECT_THAT(GetPrefs(1)->GetString(pref_name), Eq(string_value)); - // Verify the value got not stored at client1 (because of type mismatch). - scoped_refptr<PrefStore> pref_store = - BuildPrefStoreFromPrefsFile(GetProfile(1)); - const base::Value* result; - ASSERT_TRUE(pref_store->GetValue("testing.my-test-preference", &result)); - EXPECT_THAT(result->GetString(), Eq("some-string")); - - // Verify reads at client1 get served the default value. - GetRegistry(GetProfile(1)) - ->RegisterBooleanPref(pref_name, false, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - EXPECT_THAT(GetPrefs(1)->GetBoolean(pref_name), Eq(false)); + // Only one of the two clients sees the mismatch, the one sync-ing last. + histogram_tester.ExpectTotalCount("Sync.Preferences.RemotePrefTypeMismatch", + 1); } // Verifies that priority synced preferences and regular sycned preferences are
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index bae72c0..401d1ac 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -516,7 +516,15 @@ ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyApp())); } -IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeHostedAppTabAfterReload) { +// Flaky - crbug.com/102553 +#if defined(OS_LINUX) +#define MAYBE_NoticeHostedAppTabAfterReload \ + DISABLED_NoticeHostedAppTabAfterReload +#else +#define MAYBE_NoticeHostedAppTabAfterReload NoticeHostedAppTabAfterReload +#endif +IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, + MAYBE_NoticeHostedAppTabAfterReload) { // The app under test acts on URLs whose host is "localhost", // so the URLs we navigate to must have host "localhost". GURL base_url = embedded_test_server()->GetURL( @@ -546,7 +554,15 @@ ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyExtension())); } -IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeHostedAppTabBeforeReload) { +// Flaky - crbug.com/102553 +#if defined(OS_LINUX) +#define MAYBE_NoticeHostedAppTabBeforeReload \ + DISABLED_NoticeHostedAppTabBeforeReload +#else +#define MAYBE_NoticeHostedAppTabBeforeReload NoticeHostedAppTabBeforeReload +#endif +IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, + MAYBE_NoticeHostedAppTabBeforeReload) { // The app under test acts on URLs whose host is "localhost", // so the URLs we navigate to must have host "localhost". GURL base_url = embedded_test_server()->GetURL(
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java index 4898545f..3ee263f 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java
@@ -82,7 +82,7 @@ if (isVisible) { mBottomSheetController.addObserver(mBottomSheetObserver); mBottomSheetController.requestShowContent(this, true); - } else { + } else if (mBottomSheetController.isSheetOpen()) { mBottomSheetController.hideContent(this, true); } }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index fc9f628..e10078b6 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -932,6 +932,10 @@ "global_error/global_error_service.h", "global_error/global_error_service_factory.cc", "global_error/global_error_service_factory.h", + "global_media_controls/cast_media_notification_item.cc", + "global_media_controls/cast_media_notification_item.h", + "global_media_controls/cast_media_notification_provider.cc", + "global_media_controls/cast_media_notification_provider.h", "global_media_controls/media_dialog_delegate.cc", "global_media_controls/media_dialog_delegate.h", "global_media_controls/media_notification_container_impl.h",
diff --git a/chrome/browser/ui/browser_tabstrip.cc b/chrome/browser/ui/browser_tabstrip.cc index b45b337..255ff82d 100644 --- a/chrome/browser/ui/browser_tabstrip.cc +++ b/chrome/browser/ui/browser_tabstrip.cc
@@ -112,10 +112,6 @@ if (nav_params->disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || nav_params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { nav_params->group = model->GetTabGroupForTab(source_index); - // TODO(crbug.com / 997344): Re-evaluate implicit link creation, and either - // remove this or add tests. - if (!nav_params->group) - nav_params->group = model->AddToNewGroup({source_index}); } }
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc b/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc new file mode 100644 index 0000000..3fc29ff --- /dev/null +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_item.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 "chrome/browser/ui/global_media_controls/cast_media_notification_item.h" + +#include "services/media_session/public/mojom/media_session.mojom.h" + +namespace { + +media_session::mojom::MediaSessionInfoPtr CreateSessionInfo() { + auto session_info = media_session::mojom::MediaSessionInfo::New(); + session_info->state = + media_session::mojom::MediaSessionInfo::SessionState::kSuspended; + session_info->force_duck = false; + session_info->playback_state = + media_session::mojom::MediaPlaybackState::kPaused; + session_info->is_controllable = true; + session_info->prefer_stop_for_gain_focus_loss = false; + return session_info; +} + +} // namespace + +CastMediaNotificationItem::CastMediaNotificationItem( + media_message_center::MediaNotificationController* notification_controller) + : session_info_(CreateSessionInfo()) {} + +CastMediaNotificationItem::~CastMediaNotificationItem() = default; + +void CastMediaNotificationItem::SetView( + media_message_center::MediaNotificationView* view) { + view_ = view; +} + +void CastMediaNotificationItem::OnMediaSessionActionButtonPressed( + media_session::mojom::MediaSessionAction action) { + // TODO(crbug.com/987479): Forward the action to the Cast receiver. +} + +void CastMediaNotificationItem::Dismiss() { + // TODO(crbug.com/987479): Hide the notification. +} + +void CastMediaNotificationItem::OnMediaStatusUpdated( + media_router::mojom::MediaStatusPtr status) { + // TODO(crbug.com/987479): Update |session_info_| with the data from |status|, + // and notify |view_|. +}
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_item.h b/chrome/browser/ui/global_media_controls/cast_media_notification_item.h new file mode 100644 index 0000000..a5252aa --- /dev/null +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_item.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 CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_ITEM_H_ +#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_ITEM_H_ + +#include "base/memory/weak_ptr.h" +#include "chrome/common/media_router/media_route.h" +#include "chrome/common/media_router/mojom/media_status.mojom.h" +#include "components/media_message_center/media_notification_item.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/media_session/public/cpp/media_metadata.h" + +namespace media_message_center { +class MediaNotificationController; +} // namespace media_message_center + +// Represents the media notification shown in the Global Media Controls dialog +// for a Cast session. It is responsible for showing/hiding a +// MediaNotificationView. +class CastMediaNotificationItem + : public media_message_center::MediaNotificationItem, + public media_router::mojom::MediaStatusObserver { + public: + CastMediaNotificationItem(media_message_center::MediaNotificationController* + notification_controller); + CastMediaNotificationItem(const CastMediaNotificationItem&) = delete; + CastMediaNotificationItem& operator=(const CastMediaNotificationItem&) = + delete; + ~CastMediaNotificationItem() override; + + // media_message_center::MediaNotificationItem: + void SetView(media_message_center::MediaNotificationView* view) override; + void OnMediaSessionActionButtonPressed( + media_session::mojom::MediaSessionAction action) override; + void Dismiss() override; + + // media_router::mojom::MediaStatusObserver: + void OnMediaStatusUpdated( + media_router::mojom::MediaStatusPtr status) override; + + base::WeakPtr<media_message_center::MediaNotificationItem> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + private: + media_message_center::MediaNotificationView* view_ = nullptr; + media_session::mojom::MediaSessionInfoPtr session_info_; + base::WeakPtrFactory<CastMediaNotificationItem> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_ITEM_H_
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_provider.cc b/chrome/browser/ui/global_media_controls/cast_media_notification_provider.cc new file mode 100644 index 0000000..96e9334 --- /dev/null +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_provider.cc
@@ -0,0 +1,72 @@ +// 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/global_media_controls/cast_media_notification_provider.h" + +#include "chrome/browser/media/router/media_router.h" +#include "chrome/browser/media/router/media_router_factory.h" +#include "chrome/browser/profiles/profile.h" + +CastMediaNotificationProvider::CastMediaNotificationProvider( + Profile* profile, + media_message_center::MediaNotificationController* notification_controller, + base::RepeatingClosure items_changed_callback) + : CastMediaNotificationProvider( + media_router::MediaRouterFactory::GetApiForBrowserContext(profile), + notification_controller, + std::move(items_changed_callback)) {} + +CastMediaNotificationProvider::CastMediaNotificationProvider( + media_router::MediaRouter* router, + media_message_center::MediaNotificationController* notification_controller, + base::RepeatingClosure items_changed_callback) + : media_router::MediaRoutesObserver(router), + notification_controller_(notification_controller), + items_changed_callback_(std::move(items_changed_callback)) {} + +CastMediaNotificationProvider::~CastMediaNotificationProvider() = default; + +void CastMediaNotificationProvider::OnRoutesUpdated( + const std::vector<media_router::MediaRoute>& routes, + const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { + const bool had_items = HasItems(); + + base::EraseIf(items_, [&routes](const auto& item) { + return std::find_if(routes.begin(), routes.end(), + [&item](const media_router::MediaRoute& route) { + return item.first == route.media_route_id(); + }) == routes.end(); + }); + + for (const auto& route : routes) { + if (!route.for_display() || + route.controller_type() != + media_router::RouteControllerType::kGeneric) { + continue; + } + if (std::find_if(items_.begin(), items_.end(), [&route](const auto& item) { + return item.first == route.media_route_id(); + }) == items_.end()) { + items_.emplace(std::piecewise_construct, + std::forward_as_tuple(route.media_route_id()), + std::forward_as_tuple(notification_controller_)); + // TODO(crbug.com/987479): Connect the CastMediaNotificationItem to a + // controller through MediaRouter::GetMediaController(). + } + } + if (HasItems() != had_items) + items_changed_callback_.Run(); +} + +base::WeakPtr<media_message_center::MediaNotificationItem> +CastMediaNotificationProvider::GetNotificationItem(const std::string& id) { + const auto item_it = items_.find(id); + if (item_it == items_.end()) + return nullptr; + return item_it->second.GetWeakPtr(); +} + +bool CastMediaNotificationProvider::HasItems() const { + return !items_.empty(); +}
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_provider.h b/chrome/browser/ui/global_media_controls/cast_media_notification_provider.h new file mode 100644 index 0000000..6005b1a3 --- /dev/null +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_provider.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 CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_PROVIDER_H_ +#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_PROVIDER_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/media/router/media_routes_observer.h" +#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h" + +class Profile; + +namespace media_message_center { +class MediaNotificationController; +} // namespace media_message_center + +namespace media_router { +class MediaRouter; +} // namespace media_router + +// Manages media notifications shown in the Global Media Controls dialog for +// active Cast sessions. +class CastMediaNotificationProvider : public media_router::MediaRoutesObserver { + public: + CastMediaNotificationProvider( + Profile* profile, + media_message_center::MediaNotificationController* + notification_controller, + base::RepeatingClosure items_changed_callback); + CastMediaNotificationProvider( + media_router::MediaRouter* router, + media_message_center::MediaNotificationController* + notification_controller, + base::RepeatingClosure items_changed_callback_); + CastMediaNotificationProvider(const CastMediaNotificationProvider&) = delete; + CastMediaNotificationProvider& operator=( + const CastMediaNotificationProvider&) = delete; + ~CastMediaNotificationProvider() override; + + // media_router::MediaRoutesObserver: + void OnRoutesUpdated(const std::vector<media_router::MediaRoute>& routes, + const std::vector<media_router::MediaRoute::Id>& + joinable_route_ids) override; + + base::WeakPtr<media_message_center::MediaNotificationItem> + GetNotificationItem(const std::string& id); + + virtual bool HasItems() const; + + private: + media_message_center::MediaNotificationController* const + notification_controller_; + + // Maps from notification item IDs to items. + std::map<std::string, CastMediaNotificationItem> items_; + + // Called when the number of items changes from zero to positive or vice + // versa. + base::RepeatingClosure items_changed_callback_; +}; + +#endif // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_CAST_MEDIA_NOTIFICATION_PROVIDER_H_
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_provider_unittest.cc b/chrome/browser/ui/global_media_controls/cast_media_notification_provider_unittest.cc new file mode 100644 index 0000000..032eb0c --- /dev/null +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_provider_unittest.cc
@@ -0,0 +1,73 @@ +// 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/global_media_controls/cast_media_notification_provider.h" + +#include "chrome/browser/media/router/test/mock_media_router.h" +#include "components/media_message_center/media_notification_controller.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class MockMediaNotificationController + : public media_message_center::MediaNotificationController { + public: + MockMediaNotificationController() = default; + ~MockMediaNotificationController() = default; + + MOCK_METHOD1(ShowNotification, void(const std::string& id)); + MOCK_METHOD1(HideNotification, void(const std::string& id)); + MOCK_METHOD1(RemoveItem, void(const std::string& id)); + scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override { + return nullptr; + } + MOCK_METHOD1(LogMediaSessionActionButtonPressed, void(const std::string& id)); +}; + +class MockClosure { + public: + MOCK_METHOD0(Run, void()); +}; + +} // namespace + +class CastMediaNotificationProviderTest : public testing::Test { + public: + void SetUp() override { + notification_provider_ = std::make_unique<CastMediaNotificationProvider>( + &router_, ¬ification_controller_, + base::BindRepeating(&MockClosure::Run, + base::Unretained(&items_changed_callback_))); + } + + void TearDown() override { notification_provider_.reset(); } + + protected: + content::BrowserTaskEnvironment task_environment_; + std::unique_ptr<CastMediaNotificationProvider> notification_provider_; + MockMediaNotificationController notification_controller_; + media_router::MockMediaRouter router_; + MockClosure items_changed_callback_; +}; + +TEST_F(CastMediaNotificationProviderTest, AddAndRemoveRoute) { + const std::string route_id = "route-id-1"; + media_router::MediaRoute route(route_id, + media_router::MediaSource("source_id"), + "sink_id", "description", true, true); + route.set_controller_type(media_router::RouteControllerType::kGeneric); + + EXPECT_CALL(items_changed_callback_, Run()); + notification_provider_->OnRoutesUpdated({route}, {}); + testing::Mock::VerifyAndClearExpectations(&items_changed_callback_); + EXPECT_TRUE(notification_provider_->HasItems()); + EXPECT_NE(nullptr, notification_provider_->GetNotificationItem(route_id)); + + EXPECT_CALL(items_changed_callback_, Run()); + notification_provider_->OnRoutesUpdated({}, {}); + testing::Mock::VerifyAndClearExpectations(&items_changed_callback_); + EXPECT_FALSE(notification_provider_->HasItems()); +}
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc index 499aff61..8ed445c 100644 --- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc +++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.cc
@@ -5,6 +5,8 @@ #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h" #include "base/metrics/histogram_functions.h" +#include "chrome/browser/media/router/media_router_feature.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" @@ -16,6 +18,7 @@ #include "components/media_message_center/media_notification_util.h" #include "components/media_message_center/media_session_notification_item.h" #include "content/public/browser/media_session.h" +#include "media/base/media_switches.h" #include "services/media_session/public/mojom/constants.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -65,45 +68,22 @@ owner_->RemoveItem(id_); } -MediaToolbarButtonController::MediaRoutesObserver::MediaRoutesObserver( - media_router::MediaRouter* router, - base::RepeatingClosure routes_changed_callback) - : media_router::MediaRoutesObserver(router), - routes_changed_callback_(std::move(routes_changed_callback)) {} - -MediaToolbarButtonController::MediaRoutesObserver::~MediaRoutesObserver() = - default; - -void MediaToolbarButtonController::MediaRoutesObserver::OnRoutesUpdated( - const std::vector<media_router::MediaRoute>& routes, - const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) { - bool has_routes_now = - std::find_if(routes.begin(), routes.end(), - [](const media_router::MediaRoute& route) { - return route.for_display() && - route.controller_type() == - media_router::RouteControllerType::kGeneric; - }) != routes.end(); - if (has_routes_ != has_routes_now) { - has_routes_ = has_routes_now; - routes_changed_callback_.Run(); - } -} - MediaToolbarButtonController::MediaToolbarButtonController( const base::UnguessableToken& source_id, service_manager::Connector* connector, MediaToolbarButtonControllerDelegate* delegate, - media_router::MediaRouter* media_router) + Profile* profile) : connector_(connector), delegate_(delegate) { DCHECK(delegate_); - if (media_router) { - media_routes_observer_ = std::make_unique<MediaRoutesObserver>( - media_router, - base::BindRepeating( - &MediaToolbarButtonController::UpdateToolbarButtonState, - base::Unretained(this))); + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsForCast) && + media_router::MediaRouterEnabled(profile)) { + cast_notification_provider_ = + std::make_unique<CastMediaNotificationProvider>( + profile, this, + base::BindRepeating( + &MediaToolbarButtonController::UpdateToolbarButtonState, + base::Unretained(this))); } // |connector| can be null in tests. @@ -195,12 +175,8 @@ if (!dialog_delegate_) return; - base::WeakPtr<media_message_center::MediaNotificationItem> item; - - auto it = sessions_.find(id); - if (it != sessions_.end()) - item = it->second.item()->GetWeakPtr(); - + base::WeakPtr<media_message_center::MediaNotificationItem> item = + GetNotificationItem(id); MediaNotificationContainerImpl* container = dialog_delegate_->ShowMediaSession(id, item); @@ -290,12 +266,8 @@ return; for (const std::string& id : active_controllable_session_ids_) { - base::WeakPtr<media_message_center::MediaNotificationItem> item; - - auto it = sessions_.find(id); - if (it != sessions_.end()) - item = it->second.item()->GetWeakPtr(); - + base::WeakPtr<media_message_center::MediaNotificationItem> item = + GetNotificationItem(id); MediaNotificationContainerImpl* container = dialog_delegate_->ShowMediaSession(id, item); @@ -318,7 +290,8 @@ void MediaToolbarButtonController::UpdateToolbarButtonState() { if (!active_controllable_session_ids_.empty() || - (media_routes_observer_ && media_routes_observer_->has_routes())) { + (cast_notification_provider_ && + cast_notification_provider_->HasItems())) { if (delegate_display_state_ != DisplayState::kShown) { delegate_->Enable(); delegate_->Show(); @@ -340,3 +313,14 @@ delegate_display_state_ = DisplayState::kDisabled; } } + +base::WeakPtr<media_message_center::MediaNotificationItem> +MediaToolbarButtonController::GetNotificationItem(const std::string& id) { + auto it = sessions_.find(id); + if (it != sessions_.end()) { + return it->second.item()->GetWeakPtr(); + } else if (cast_notification_provider_) { + return cast_notification_provider_->GetNotificationItem(id); + } + return nullptr; +}
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h index e95889c..0e379a0 100644 --- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h +++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/media/router/media_routes_observer.h" +#include "chrome/browser/ui/global_media_controls/cast_media_notification_provider.h" #include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h" #include "components/media_message_center/media_notification_controller.h" #include "content/public/browser/web_contents_observer.h" @@ -28,10 +29,6 @@ class MediaSessionNotificationItem; } // namespace media_message_center -namespace media_router { -class MediaRouter; -} // namespace media_router - namespace service_manager { class Connector; } // namespace service_manager @@ -51,7 +48,7 @@ MediaToolbarButtonController(const base::UnguessableToken& source_id, service_manager::Connector* connector, MediaToolbarButtonControllerDelegate* delegate, - media_router::MediaRouter* media_router); + Profile* profile); ~MediaToolbarButtonController() override; // media_session::mojom::AudioFocusObserver implementation. @@ -110,34 +107,14 @@ std::unique_ptr<media_message_center::MediaSessionNotificationItem> item_; }; - class MediaRoutesObserver : public media_router::MediaRoutesObserver { - public: - MediaRoutesObserver(media_router::MediaRouter* router, - base::RepeatingClosure routes_changed_callback); - MediaRoutesObserver(const MediaRoutesObserver&) = delete; - MediaRoutesObserver& operator=(const MediaRoutesObserver&) = delete; - - ~MediaRoutesObserver() override; - - // media_router::MediaRoutesObserver implementation. - void OnRoutesUpdated(const std::vector<media_router::MediaRoute>& routes, - const std::vector<media_router::MediaRoute::Id>& - joinable_route_ids) override; - - bool has_routes() const { return has_routes_; } - - private: - bool has_routes_ = false; - - // Called when the presence of media routes has changed. - base::RepeatingClosure routes_changed_callback_; - }; - void OnReceivedAudioFocusRequests( std::vector<media_session::mojom::AudioFocusRequestStatePtr> sessions); void UpdateToolbarButtonState(); + base::WeakPtr<media_message_center::MediaNotificationItem> + GetNotificationItem(const std::string& id); + service_manager::Connector* const connector_; MediaToolbarButtonControllerDelegate* const delegate_; MediaDialogDelegate* dialog_delegate_ = nullptr; @@ -169,8 +146,7 @@ mojo::Receiver<media_session::mojom::AudioFocusObserver> audio_focus_observer_receiver_{this}; - // Observes for active Cast sessions that can be controlled. - std::unique_ptr<MediaRoutesObserver> media_routes_observer_; + std::unique_ptr<CastMediaNotificationProvider> cast_notification_provider_; base::WeakPtrFactory<MediaToolbarButtonController> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc index aff25a527..5a6e423 100644 --- a/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc +++ b/chrome/browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc
@@ -8,14 +8,19 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/unguessable_token.h" +#include "chrome/browser/media/router/media_router_factory.h" #include "chrome/browser/media/router/test/mock_media_router.h" +#include "chrome/browser/ui/global_media_controls/cast_media_notification_provider.h" #include "chrome/browser/ui/global_media_controls/media_dialog_delegate.h" #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller_delegate.h" +#include "chrome/test/base/testing_profile.h" #include "components/media_message_center/media_notification_item.h" #include "components/media_message_center/media_notification_util.h" #include "components/media_message_center/media_session_notification_item.h" #include "content/public/test/browser_task_environment.h" +#include "media/base/media_switches.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "testing/gmock/include/gmock/gmock.h" @@ -85,10 +90,14 @@ ~MediaToolbarButtonControllerTest() override = default; void SetUp() override { + media_router::MediaRouterFactory::GetInstance()->SetTestingFactory( + &profile_, base::BindRepeating(&media_router::MockMediaRouter::Create)); controller_ = std::make_unique<MediaToolbarButtonController>( - base::UnguessableToken::Create(), nullptr, &delegate_, &media_router_); + base::UnguessableToken::Create(), nullptr, &delegate_, &profile_); } + void TearDown() override { controller_.reset(); } + protected: void AdvanceClockMilliseconds(int milliseconds) { task_environment_.FastForwardBy( @@ -198,7 +207,7 @@ void SimulateMediaRoutesUpdate( const std::vector<media_router::MediaRoute>& routes) { - controller_->media_routes_observer_->OnRoutesUpdated(routes, {}); + controller_->cast_notification_provider_->OnRoutesUpdated(routes, {}); } MockMediaToolbarButtonControllerDelegate& delegate() { return delegate_; } @@ -206,13 +215,27 @@ private: content::BrowserTaskEnvironment task_environment_; MockMediaToolbarButtonControllerDelegate delegate_; - media_router::MockMediaRouter media_router_; std::unique_ptr<MediaToolbarButtonController> controller_; base::HistogramTester histogram_tester_; + TestingProfile profile_; DISALLOW_COPY_AND_ASSIGN(MediaToolbarButtonControllerTest); }; +// TODO(takumif): Remove this class once |kGlobalMediaControlsForCast| is +// enabled by default. +class MediaToolbarButtonControllerCastTest + : public MediaToolbarButtonControllerTest { + public: + void SetUp() override { + feature_list_.InitAndEnableFeature(media::kGlobalMediaControlsForCast); + MediaToolbarButtonControllerTest::SetUp(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + TEST_F(MediaToolbarButtonControllerTest, ShowControllableOnGainAndHideOnLoss) { // Simulate a new active, controllable media session. EXPECT_CALL(delegate(), Show()); @@ -428,7 +451,7 @@ testing::Mock::VerifyAndClearExpectations(&delegate()); } -TEST_F(MediaToolbarButtonControllerTest, ShowButtonForCastSession) { +TEST_F(MediaToolbarButtonControllerCastTest, ShowButtonForCastSession) { media_router::MediaRoute media_route("id", media_router::MediaSource("source_id"), "sink_id", "description", true, true);
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index 834b1a1..084e81a 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -685,7 +685,7 @@ return; } - if (!base::FeatureList::IsEnabled(features::kConfirmNtpSuggestionRemovals)) { + if (!base::FeatureList::IsEnabled(ntp_features::kConfirmSuggestionRemovals)) { // If suggestion transparency is disabled, the UI is also disabled. This // must've come from a keyboard shortcut, which are allowed to remove // without confirmation.
diff --git a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc index 16369b8..e5d3393 100644 --- a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc +++ b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/policy/browser_signin_policy_handler.h" #include "chrome/browser/prefs/browser_prefs.h"
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc index f954684..9adfc23 100644 --- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc +++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -113,6 +113,32 @@ return reference_view; } +std::unique_ptr<views::View> CreateSigninPromoView( + int bubble_options, + Profile* profile, + BubbleSyncPromoDelegate* delegate) { +#if defined(OS_CHROMEOS) + // ChromeOS does not show the signin promo. + return nullptr; +#else + if (!(bubble_options & ExtensionInstalledBubble::SIGN_IN_PROMO)) + return nullptr; + + BubbleSyncPromoViewParams params; + params.link_text_resource_id = IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW; + params.message_text_resource_id = IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW; + params.dice_no_accounts_promo_message_resource_id = + IDS_EXTENSION_INSTALLED_DICE_PROMO_SIGNIN_MESSAGE; + params.dice_accounts_promo_message_resource_id = + IDS_EXTENSION_INSTALLED_DICE_PROMO_SYNC_MESSAGE; + + return CreateBubbleSyncPromoView( + profile, delegate, + signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE, + params); +#endif +} + } // namespace // Provides feedback to the user upon successful installation of an @@ -145,7 +171,6 @@ gfx::ImageSkia GetWindowIcon() override; bool ShouldShowWindowIcon() const override; bool ShouldShowCloseButton() const override; - std::unique_ptr<View> CreateFootnoteView() override; int GetDialogButtons() const override; void Init() override; @@ -181,6 +206,8 @@ bubble_reference_(bubble_reference), manage_shortcut_(nullptr) { chrome::RecordDialogCreation(chrome::DialogIdentifier::EXTENSION_INSTALLED); + DialogDelegate::SetFootnoteView(CreateSigninPromoView( + controller->options(), controller->browser()->profile(), this)); } ExtensionInstalledBubbleView::~ExtensionInstalledBubbleView() {} @@ -227,30 +254,6 @@ return true; } -std::unique_ptr<views::View> -ExtensionInstalledBubbleView::CreateFootnoteView() { -#if defined(OS_CHROMEOS) - // ChromeOS does not show the signin promo. - return nullptr; -#else - if (!(controller_->options() & ExtensionInstalledBubble::SIGN_IN_PROMO)) - return nullptr; - - BubbleSyncPromoViewParams params; - params.link_text_resource_id = IDS_EXTENSION_INSTALLED_SYNC_PROMO_LINK_NEW; - params.message_text_resource_id = IDS_EXTENSION_INSTALLED_SYNC_PROMO_NEW; - params.dice_no_accounts_promo_message_resource_id = - IDS_EXTENSION_INSTALLED_DICE_PROMO_SIGNIN_MESSAGE; - params.dice_accounts_promo_message_resource_id = - IDS_EXTENSION_INSTALLED_DICE_PROMO_SYNC_MESSAGE; - - return CreateBubbleSyncPromoView( - browser()->profile(), this, - signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE, - params); -#endif -} - int ExtensionInstalledBubbleView::GetDialogButtons() const { return ui::DIALOG_BUTTON_NONE; }
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc index 5179d05..7371d0a2 100644 --- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
@@ -6,9 +6,6 @@ #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/media/router/media_router_factory.h" -#include "chrome/browser/media/router/media_router_feature.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h" @@ -28,30 +25,17 @@ #include "ui/views/animation/ink_drop.h" #include "ui/views/controls/button/button_controller.h" -namespace { - -media_router::MediaRouter* GetMediaRouter(Profile* profile) { - bool supports_cast = - base::FeatureList::IsEnabled(media::kGlobalMediaControlsForCast) && - media_router::MediaRouterEnabled(profile); - if (!supports_cast) - return nullptr; - return media_router::MediaRouterFactory::GetApiForBrowserContext(profile); -} - -} // namespace - MediaToolbarButtonView::MediaToolbarButtonView( const base::UnguessableToken& source_id, service_manager::Connector* connector, const Browser* browser) : ToolbarButton(this), connector_(connector), - controller_(std::make_unique<MediaToolbarButtonController>( - source_id, - connector_, - this, - GetMediaRouter(browser->profile()))), + controller_( + std::make_unique<MediaToolbarButtonController>(source_id, + connector_, + this, + browser->profile())), browser_(browser) { GlobalMediaControlsInProductHelp* in_product_help = GlobalMediaControlsInProductHelpFactory::GetForProfile(
diff --git a/chrome/browser/ui/views/omnibox/omnibox_text_view.cc b/chrome/browser/ui/views/omnibox/omnibox_text_view.cc index 7eb8bb3..781a6e8 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_text_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_text_view.cc
@@ -95,10 +95,11 @@ style = {gfx::kGoogleRed600}; break; case SuggestionAnswer::TextStyle::SUPERIOR: - style = {part_color, .baseline = gfx::SUPERIOR}; + style = {.color = part_color, .baseline = gfx::SUPERIOR}; break; case SuggestionAnswer::TextStyle::BOLD: - style = {part_color, .baseline = gfx::NORMAL_BASELINE, + style = {.color = part_color, + .baseline = gfx::NORMAL_BASELINE, .weight = gfx::Font::Weight::BOLD}; break; case SuggestionAnswer::TextStyle::NORMAL:
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc index 9a3f537..ece3fd9 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_browsertest.cc
@@ -644,6 +644,11 @@ scoped_feature_list_.InitAndEnableFeature(features::kProfileMenuRevamp); } + void SetUpInProcessBrowserTestFixture() override { + test_signin_client_factory_ = + secondary_account_helper::SetUpSigninClient(&test_url_loader_factory_); + } + void SetUpOnMainThread() override { SyncTest::SetUpOnMainThread(); @@ -740,6 +745,9 @@ ProfileMenuViewBase::GetBubbleForTesting()); } + secondary_account_helper::ScopedSigninClientFactory + test_signin_client_factory_; + base::test::ScopedFeatureList scoped_feature_list_; base::HistogramTester histogram_tester_; @@ -945,13 +953,10 @@ // there are no other buttons at the end. ProfileMenuViewBase::ActionableItem::kPasswordsButton}; -// TODO(crbug.com/1015429): Failing on Mac 10.12. -PROFILE_MENU_CLICK_TEST( - kActionableItems_WithUnconsentedPrimaryAccount, - DISABLED_ProfileMenuClickTest_WithUnconsentedPrimaryAccount) { - signin::MakeAccountAvailableWithCookies(identity_manager(), - &test_url_loader_factory_, - "user@example.com", "gaia_id"); +PROFILE_MENU_CLICK_TEST(kActionableItems_WithUnconsentedPrimaryAccount, + ProfileMenuClickTest_WithUnconsentedPrimaryAccount) { + secondary_account_helper::SignInSecondaryAccount( + browser()->profile(), &test_url_loader_factory_, "user@example.com"); UnconsentedPrimaryAccountChecker(identity_manager()).Wait(); // Check that the setup was successful. ASSERT_FALSE(identity_manager()->HasPrimaryAccount());
diff --git a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc index 2c19ecda..30420f0 100644 --- a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc +++ b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
@@ -5,10 +5,8 @@ #include "chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h" #include <map> -#include <string> #include "ash/public/cpp/shell_window_ids.h" -#include "base/base64.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -50,13 +48,6 @@ namespace { -constexpr char kKeyInformation[] = "information"; -constexpr char kKeyIcon[] = "icon"; -constexpr char kKeyTitle[] = "title"; -constexpr char kKeyPlatform[] = "platform"; -constexpr char kKeyTimestamp[] = "timestamp"; -constexpr char kKeyDuration[] = "duration"; - constexpr char kLastTracingModelName[] = "last_tracing_model.json"; enum class Action { @@ -200,7 +191,9 @@ std::pair<base::Value, std::string> BuildGraphicsModel( const std::string& data, ArcGraphicsTracingMode mode, - base::DictionaryValue task_information, + const std::string& title, + const std::vector<unsigned char>& icon_png, + base::Time timestamp, std::unique_ptr<arc::ArcSystemStatCollector> system_stat_collector, const base::TimeTicks& time_min, const base::TimeTicks& time_max, @@ -231,12 +224,11 @@ } UpdateThreads(&graphics_model.system_model().thread_map()); - + graphics_model.set_app_title(title); + graphics_model.set_app_icon_png(icon_png); + graphics_model.set_platform(base::GetLinuxDistro()); + graphics_model.set_timestamp(timestamp); std::unique_ptr<base::DictionaryValue> model = graphics_model.Serialize(); - task_information.SetKey( - kKeyDuration, - base::Value(static_cast<double>(graphics_model.duration()))); - model->SetKey(kKeyInformation, std::move(task_information)); std::string json_content; base::JSONWriter::WriteWithOptions( @@ -435,21 +427,14 @@ DCHECK(arc_active_window_); active_task_title_ = base::UTF16ToASCII(arc_active_window_->GetTitle()); - task_information_.SetKey(kKeyTitle, base::Value(active_task_title_)); + active_task_icon_png_.clear(); const gfx::ImageSkia* app_icon = arc_active_window_->GetProperty(aura::client::kAppIconKey); if (app_icon) { - std::vector<unsigned char> png_data; - if (gfx::PNGCodec::EncodeBGRASkBitmap( - app_icon->GetRepresentation(1.0f).GetBitmap(), - false /* discard_transparency */, &png_data)) { - const std::string png_data_as_string( - reinterpret_cast<const char*>(&png_data[0]), png_data.size()); - std::string icon_content; - base::Base64Encode(png_data_as_string, &icon_content); - task_information_.SetKey(kKeyIcon, base::Value(icon_content)); - } + gfx::PNGCodec::EncodeBGRASkBitmap( + app_icon->GetRepresentation(1.0f).GetBitmap(), + false /* discard_transparency */, &active_task_icon_png_); } } @@ -529,10 +514,7 @@ } void ArcGraphicsTracingHandler::OnTracingStarted() { - task_information_.Clear(); - task_information_.SetKey(kKeyPlatform, base::Value(base::GetLinuxDistro())); - task_information_.SetKey(kKeyTimestamp, - base::Value(base::Time::Now().ToJsTime())); + timestamp_ = base::Time::Now(); UpdateActiveArcWindowInfo(); @@ -560,7 +542,7 @@ FROM_HERE, {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::BindOnce(&BuildGraphicsModel, std::move(string_data), mode_, - std::move(task_information_), + active_task_title_, active_task_icon_png_, timestamp_, std::move(system_stat_colletor_), tracing_time_min_, tracing_time_max_, model_path), base::BindOnce(&ArcGraphicsTracingHandler::OnGraphicsModelReady,
diff --git a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h index 6d7aee3..53682da30 100644 --- a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h +++ b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.h
@@ -5,9 +5,10 @@ #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ARC_GRAPHICS_TRACING_ARC_GRAPHICS_TRACING_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ARC_GRAPHICS_TRACING_ARC_GRAPHICS_TRACING_HANDLER_H_ -#include <map> #include <memory> +#include <string> #include <utility> +#include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -124,7 +125,6 @@ // Task id and title for current ARC window. int active_task_id_ = -1; - std::string active_task_title_; // Used to detect janks for the currently active ARC++ window. std::unique_ptr<arc::ArcGraphicsJankDetector> jank_detector_; @@ -133,7 +133,9 @@ std::unique_ptr<arc::ArcSystemStatCollector> system_stat_colletor_; // Information about active task, title and icon. - base::DictionaryValue task_information_; + std::string active_task_title_; + std::vector<unsigned char> active_task_icon_png_; + base::Time timestamp_; base::WeakPtrFactory<ArcGraphicsTracingHandler> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 0484525..446b6e8b 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -3271,18 +3271,18 @@ static constexpr LocalizedString kSecurityKeysStrings[] = { {"securityKeysBioEnrollmentDialogTitle", IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_DIALOG_TITLE}, + {"securityKeysBioEnrollmentEnrollingCompleteLabel", + IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL}, {"securityKeysBioEnrollmentEnrollingLabel", IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL}, {"securityKeysBioEnrollmentLabel", IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_LABEL}, {"securityKeysBioEnrollmentNoEnrollments", IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_NO_ENROLLMENTS}, - {"securityKeysBioEnrollmentPinPrompt", - IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_PIN_PROMPT}, {"securityKeysBioEnrollmentSubpageDescription", IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_SUBPAGE_DESCRIPTION}, - {"securityKeysBioEnrollmentTouch", - IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_TOUCH}, + {"securityKeysBioEnrollmentSubpageLabel", + IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_SUBPAGE_LABEL}, {"securityKeysBioEnrollmentChooseName", IDS_SETTINGS_SECURITY_KEYS_BIO_CHOOSE_NAME}, {"securityKeysBioEnrollmentNameLabel", @@ -3303,10 +3303,6 @@ IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_LABEL}, {"securityKeysCredentialManagementNoCredentials", IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_NO_CREDENTIALS}, - {"securityKeysCredentialManagementPinPrompt", - IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_PIN_PROMPT}, - {"securityKeysCredentialManagementTouch", - IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_TOUCH}, {"securityKeysCredentialUsername", IDS_SETTINGS_SECURITY_KEYS_CREDENTIAL_USERNAME}, {"securityKeysCurrentPIN", IDS_SETTINGS_SECURITY_KEYS_CURRENT_PIN}, @@ -3327,12 +3323,12 @@ IDS_SETTINGS_SECURITY_KEYS_PIN_INCORRECT_RETRIES_SIN}, {"securityKeysPINMismatch", IDS_SETTINGS_SECURITY_KEYS_PIN_ERROR_MISMATCH}, + {"securityKeysPINPrompt", IDS_SETTINGS_SECURITY_KEYS_PIN_PROMPT}, {"securityKeysPINSoftLock", IDS_SETTINGS_SECURITY_KEYS_PIN_SOFT_LOCK}, {"securityKeysPINSuccess", IDS_SETTINGS_SECURITY_KEYS_PIN_SUCCESS}, {"securityKeysPINTooLong", IDS_SETTINGS_SECURITY_KEYS_PIN_ERROR_TOO_LONG}, {"securityKeysPINTooShort", IDS_SETTINGS_SECURITY_KEYS_PIN_ERROR_TOO_SHORT_SMALL}, - {"securityKeysPINTouch", IDS_SETTINGS_SECURITY_KEYS_PIN_TOUCH}, {"securityKeysReset", IDS_SETTINGS_SECURITY_KEYS_RESET}, {"securityKeysResetConfirmTitle", IDS_SETTINGS_SECURITY_KEYS_RESET_CONFIRM_TITLE}, @@ -3355,6 +3351,8 @@ IDS_SETTINGS_SECURITY_KEYS_SET_PIN_INITIAL_TITLE}, {"securityKeysShowPINs", IDS_SETTINGS_SECURITY_KEYS_SHOW_PINS}, {"securityKeysTitle", IDS_SETTINGS_SECURITY_KEYS_TITLE}, + {"securityKeysTouchToContinue", + IDS_SETTINGS_SECURITY_KEYS_TOUCH_TO_CONTINUE}, }; AddLocalizedStringsBulk(html_source, kSecurityKeysStrings, base::size(kSecurityKeysStrings));
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index b3942c23..ccaedfd0 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -255,10 +255,6 @@ #endif // !defined(OS_CHROMEOS) html_source->AddBoolean( - "a11yEnhancements", - base::FeatureList::IsEnabled(features::kWebUIA11yEnhancements)); - - html_source->AddBoolean( "privacySettingsRedesignEnabled", base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign));
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc index bbdebdb..c042414 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
@@ -392,11 +392,10 @@ return; } - if (thumbnail_tracked) { - thumbnail_tracker_.WatchTab(tab); - } else { - // TODO(crbug.com/991393): un-watch tabs when we are done. - } + if (thumbnail_tracked) + thumbnail_tracker_.AddTab(tab); + else + thumbnail_tracker_.RemoveTab(tab); } // Callback passed to |thumbnail_tracker_|. Called when a tab's thumbnail
diff --git a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc index 4ec05c2..161644f9 100644 --- a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc +++ b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc
@@ -68,7 +68,7 @@ ThumbnailTracker::~ThumbnailTracker() = default; -void ThumbnailTracker::WatchTab(content::WebContents* contents) { +void ThumbnailTracker::AddTab(content::WebContents* contents) { auto data_it = contents_data_.find(contents); if (data_it == contents_data_.end()) { data_it = contents_data_.emplace_hint( @@ -78,6 +78,10 @@ data_it->second->RequestThumbnail(); } +void ThumbnailTracker::RemoveTab(content::WebContents* contents) { + contents_data_.erase(contents); +} + void ThumbnailTracker::ThumbnailUpdated(content::WebContents* contents, CompressedThumbnailData image) { callback_.Run(contents, image);
diff --git a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h index feb174d..84c67edd 100644 --- a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h +++ b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h
@@ -43,7 +43,8 @@ // Registers a tab to receive thumbnail updates for. Also immediately requests // the current thumbnail. - void WatchTab(content::WebContents* contents); + void AddTab(content::WebContents* contents); + void RemoveTab(content::WebContents* contents); private: void ThumbnailUpdated(content::WebContents* contents,
diff --git a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc index 71429601..4f772387 100644 --- a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc +++ b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc
@@ -25,10 +25,16 @@ class TestThumbnailImageDelegate : public ThumbnailImage::Delegate { public: TestThumbnailImageDelegate() = default; - ~TestThumbnailImageDelegate() override = default; - void ThumbnailImageBeingObservedChanged(bool is_being_observed) override {} + void ThumbnailImageBeingObservedChanged(bool is_being_observed) override { + is_being_observed_ = is_being_observed; + } + + bool is_being_observed() const { return is_being_observed_; } + + private: + bool is_being_observed_ = false; }; class ThumbnailTrackerTest : public ::testing::Test, @@ -85,7 +91,7 @@ using ::testing::_; -TEST_F(ThumbnailTrackerTest, WatchTabGetsCurrentThumbnail) { +TEST_F(ThumbnailTrackerTest, AddTabGetsCurrentThumbnail) { auto contents = CreateWebContents(); auto thumbnail = GetTestingThumbnail(contents.get()); @@ -96,12 +102,13 @@ thumbnail->AssignSkBitmap(CreateTestingBitmap()); encode_loop.Run(); - // Verify that WatchTab() gets the current image, waiting for the decoding to - // happen. + // Verify that AddTab() gets the current image. This should happen + // immediately. EXPECT_CALL(thumbnail_updated_callback_, Run(contents.get(), _)).Times(1); thumbnail->set_async_operation_finished_callback_for_testing( base::RepeatingClosure()); - thumbnail_tracker_.WatchTab(contents.get()); + thumbnail_tracker_.AddTab(contents.get()); + EXPECT_TRUE(tab_thumbnails_[contents.get()].delegate.is_being_observed()); } TEST_F(ThumbnailTrackerTest, PropagatesThumbnailUpdate) { @@ -111,8 +118,8 @@ auto thumbnail2 = GetTestingThumbnail(contents2.get()); // Since no thumbnail image exists yet, this shouldn't notify our callback. - thumbnail_tracker_.WatchTab(contents1.get()); - thumbnail_tracker_.WatchTab(contents2.get()); + thumbnail_tracker_.AddTab(contents1.get()); + thumbnail_tracker_.AddTab(contents2.get()); { ::testing::InSequence seq; @@ -136,7 +143,7 @@ TEST_F(ThumbnailTrackerTest, StopsObservingOnTabClose) { auto contents = CreateWebContents(); auto thumbnail = GetTestingThumbnail(contents.get()); - thumbnail_tracker_.WatchTab(contents.get()); + thumbnail_tracker_.AddTab(contents.get()); // |thumbnail| is still valid, but |thumbnail_tracker_| should stop watching // it when |contents| goes away. @@ -149,3 +156,11 @@ thumbnail->AssignSkBitmap(CreateTestingBitmap()); update_loop.Run(); } + +TEST_F(ThumbnailTrackerTest, RemoveTabStopsObservingThumbnail) { + auto contents = CreateWebContents(); + auto thumbnail = GetTestingThumbnail(contents.get()); + thumbnail_tracker_.AddTab(contents.get()); + thumbnail_tracker_.RemoveTab(contents.get()); + EXPECT_FALSE(tab_thumbnails_[contents.get()].delegate.is_being_observed()); +}
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index 8192a811..a6e8201f 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -198,7 +198,7 @@ if (use_native_partitions) { # Mark symbols in this library as belonging to the VR partition. Only # exported symbols (module entrypoints) are affected. - cflags = [ "-fsymbol-partition=libvr.so" ] + cflags = [ "-fsymbol-partition=vr_partition" ] } if (is_android) {
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.h b/chrome/browser/web_applications/components/web_app_shortcut_mac.h index 3dff019..3fcee80a 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac.h +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.h
@@ -119,11 +119,16 @@ FRIEND_TEST_ALL_PREFIXES(WebAppShortcutCreatorTest, UpdateBookmarkAppShortcut); + // Return true if the bundle for this app should be profile-agnostic. + bool IsMultiProfile() const; + // Returns the bundle identifier to use for this app bundle. std::string GetBundleIdentifier() const; - // Returns the bundle identifier for the internal copy of the bundle. - std::string GetInternalBundleIdentifier() const; + // Returns the profile-scoped app bundle identifier. For multi-profile apps, + // this will give the bundle identifier for shims that were created before + // multi-profile support was added. + std::string GetProfileScopedBundleIdentifier() const; // Copies the app loader template into a temporary directory and fills in all // relevant information. This works around a Finder bug where the app's icon
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm index b291528..841c345 100644 --- a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm +++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
@@ -16,6 +16,7 @@ #include "base/bind_helpers.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -45,6 +46,7 @@ #include "chrome/browser/shell_integration.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #import "chrome/common/mac/app_mode_common.h" @@ -612,6 +614,29 @@ return shortcut_info; } +base::FilePath GetMultiProfileAppDataDir(base::FilePath app_data_dir) { + // The kCrAppModeUserDataDirKey is expected to be a path in kWebAppDirname, + // and the true user data dir is extracted by going three directories up. + // For profile-agnostic apps, remove this reference to the profile name. + // TODO(https://crbug.com/1021237): Do not specify kCrAppModeUserDataDirKey + // if Chrome is using the default user data dir. + + // Strip the app name directory. + base::FilePath app_name_dir = app_data_dir.BaseName(); + app_data_dir = app_data_dir.DirName(); + + // Strip kWebAppDirname. + base::FilePath web_app_dir = app_data_dir.BaseName(); + app_data_dir = app_data_dir.DirName(); + + // Strip the profile and replace it with kNewProfilePath. + app_data_dir = app_data_dir.DirName(); + const std::string kNewProfilePath("-"); + return app_data_dir.Append(kNewProfilePath) + .Append(web_app_dir) + .Append(app_name_dir); +} + } // namespace namespace web_app { @@ -931,12 +956,19 @@ forKey:app_mode::kCFBundleShortVersionStringKey]; [plist setObject:base::SysUTF8ToNSString(GetBundleIdentifier()) forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]; - [plist setObject:base::mac::FilePathToNSString(app_data_dir_) - forKey:app_mode::kCrAppModeUserDataDirKey]; - [plist setObject:base::mac::FilePathToNSString(info_->profile_path.BaseName()) - forKey:app_mode::kCrAppModeProfileDirKey]; - [plist setObject:base::SysUTF8ToNSString(info_->profile_name) - forKey:app_mode::kCrAppModeProfileNameKey]; + if (IsMultiProfile()) { + base::FilePath data_dir = GetMultiProfileAppDataDir(app_data_dir_); + [plist setObject:base::mac::FilePathToNSString(data_dir) + forKey:app_mode::kCrAppModeUserDataDirKey]; + } else { + [plist setObject:base::mac::FilePathToNSString(app_data_dir_) + forKey:app_mode::kCrAppModeUserDataDirKey]; + [plist + setObject:base::mac::FilePathToNSString(info_->profile_path.BaseName()) + forKey:app_mode::kCrAppModeProfileDirKey]; + [plist setObject:base::SysUTF8ToNSString(info_->profile_name) + forKey:app_mode::kCrAppModeProfileNameKey]; + } [plist setObject:[NSNumber numberWithBool:YES] forKey:app_mode::kLSHasLocalizedDisplayNameKey]; [plist setObject:[NSNumber numberWithBool:YES] @@ -963,7 +995,8 @@ NSString* bundle_name = base::SysUTF16ToNSString(info_->title); NSString* display_name = base::SysUTF16ToNSString(info_->title); - if (HasExistingExtensionShimForDifferentProfile( + if (!IsMultiProfile() && + HasExistingExtensionShimForDifferentProfile( GetChromeAppsFolder(), info_->extension_id, info_->profile_path)) { display_name = [bundle_name stringByAppendingString:base::SysUTF8ToNSString( @@ -1002,13 +1035,27 @@ std::vector<base::FilePath> WebAppShortcutCreator::GetAppBundlesByIdUnsorted() const { - const std::string bundle_id = GetBundleIdentifier(); - base::ScopedCFTypeRef<CFStringRef> bundle_id_cf( - base::SysUTF8ToCFStringRef(bundle_id)); + base::scoped_nsobject<NSMutableArray> urls([[NSMutableArray alloc] init]); - // Retrieve the URLs found by LaunchServices. - base::scoped_nsobject<NSArray> urls(base::mac::CFToNSCast( - LSCopyApplicationURLsForBundleIdentifier(bundle_id_cf.get(), nullptr))); + // If in multi-profile mode, search using the profile-scoped bundle id, in + // case the user has an old shim hanging around. + if (IsMultiProfile()) { + base::ScopedCFTypeRef<CFStringRef> bundle_id_cf( + base::SysUTF8ToCFStringRef(GetProfileScopedBundleIdentifier())); + base::scoped_nsobject<NSArray> bundle_urls(base::mac::CFToNSCast( + LSCopyApplicationURLsForBundleIdentifier(bundle_id_cf.get(), nullptr))); + [urls addObjectsFromArray:bundle_urls]; + } + + // Search using LaunchServices using the default bundle id. + const std::string bundle_id = GetBundleIdentifier(); + { + base::ScopedCFTypeRef<CFStringRef> bundle_id_cf( + base::SysUTF8ToCFStringRef(bundle_id)); + base::scoped_nsobject<NSArray> bundle_urls(base::mac::CFToNSCast( + LSCopyApplicationURLsForBundleIdentifier(bundle_id_cf.get(), nullptr))); + [urls addObjectsFromArray:bundle_urls]; + } // Store only those results corresponding to this user data dir. std::vector<base::FilePath> paths; @@ -1070,7 +1117,23 @@ return paths; } +bool WebAppShortcutCreator::IsMultiProfile() const { + // Only PWAs and bookmark apps are multi-profile capable. + if (!info_->url.is_valid()) + return false; + return base::FeatureList::IsEnabled(features::kAppShimMultiProfile); +} + std::string WebAppShortcutCreator::GetBundleIdentifier() const { + if (IsMultiProfile()) { + std::string bundle_id = + base::mac::BaseBundleID() + std::string(".app.") + info_->extension_id; + return bundle_id; + } + return GetProfileScopedBundleIdentifier(); +} + +std::string WebAppShortcutCreator::GetProfileScopedBundleIdentifier() const { // Replace spaces in the profile path with hyphen. std::string normalized_profile_path; base::ReplaceChars(info_->profile_path.BaseName().value(), " ", "-", @@ -1083,10 +1146,6 @@ return bundle_id; } -std::string WebAppShortcutCreator::GetInternalBundleIdentifier() const { - return GetBundleIdentifier() + "-internal"; -} - void WebAppShortcutCreator::RevealAppShimInFinder() const { // Note that RevealAppShimInFinder is called immediately after requesting to // build the app shim. This almost always happens before the app shim has
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 3dea4ae..af1ef85e 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -847,10 +847,6 @@ // Compress remote-bound WebRTC event logs (if used; see kWebRtcRemoteEventLog). const base::Feature kWebRtcRemoteEventLogGzipped{ "WebRtcRemoteEventLogGzipped", base::FEATURE_ENABLED_BY_DEFAULT}; - -// Enable WebUI accessibility enhancements for review and testing. -const base::Feature kWebUIA11yEnhancements{"WebUIA11yEnhancements", - base::FEATURE_DISABLED_BY_DEFAULT}; #endif // Whether to enable "dark mode" enhancements in Mac Mojave or Windows 10 for
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 6518cff7..6c401e3 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -516,8 +516,6 @@ extern const base::Feature kWebRtcRemoteEventLog; COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kWebRtcRemoteEventLogGzipped; -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::Feature kWebUIA11yEnhancements; #endif COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kWebUIDarkMode;
diff --git a/chrome/services/OWNERS b/chrome/services/OWNERS index 16d9656f..e06924a 100644 --- a/chrome/services/OWNERS +++ b/chrome/services/OWNERS
@@ -1,2 +1 @@ -jcivelli@chromium.org rockot@google.com
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 73f7b757..c890fa0f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1120,6 +1120,7 @@ "../browser/sessions/tab_restore_service_load_waiter.cc", "../browser/sessions/tab_restore_service_load_waiter.h", "../browser/sharing/click_to_call/click_to_call_browsertest.cc", + "../browser/sharing/shared_clipboard/remote_copy_browsertest.cc", "../browser/sharing/shared_clipboard/shared_clipboard_browsertest.cc", "../browser/sharing/sharing_browsertest.cc", "../browser/sharing/sharing_browsertest.h", @@ -3847,6 +3848,7 @@ "../browser/ui/extensions/extension_action_view_controller_unittest.cc", "../browser/ui/extensions/extension_message_bubble_bridge_unittest.cc", "../browser/ui/global_error/global_error_service_unittest.cc", + "../browser/ui/global_media_controls/cast_media_notification_provider_unittest.cc", "../browser/ui/global_media_controls/media_toolbar_button_controller_unittest.cc", "../browser/ui/hid/hid_chooser_controller_unittest.cc", "../browser/ui/in_product_help/active_tab_tracker_unittest.cc",
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index d4108f0..ad716f1 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -1113,8 +1113,13 @@ if (status.IsError()) return status; // An alert may block the pending navigation. - if (dialog_manager_->IsDialogOpen()) - return Status(kUnexpectedAlertOpen); + if (dialog_manager_->IsDialogOpen()) { + std::string alert_text; + status = dialog_manager_->GetDialogMessage(&alert_text); + if (status.IsError()) + return Status(kUnexpectedAlertOpen); + return Status(kUnexpectedAlertOpen, "{Alert text : " + alert_text + "}"); + } *is_not_pending = !is_pending; return Status(kOk);
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index ed17605..69e9e64 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -1358,7 +1358,9 @@ if (action_type == "pause") { GetOptionalInt(action, "duration", &duration); tick_duration = std::max(tick_duration, duration); - } else { + } + + if (type != "none") { bool async_dispatch_event = true; if (j == last_action_index) { async_dispatch_event = false; @@ -1366,28 +1368,30 @@ } if (type == "key") { - std::list<KeyEvent> dispatch_key_events; - KeyEventBuilder builder; - Status status = ConvertKeyActionToKeyEvent(action, input_state, - action_type == "keyDown", - &dispatch_key_events); - if (status.IsError()) - return status; - - if (dispatch_key_events.size() > 0) { - const KeyEvent& event = dispatch_key_events.front(); - if (action_type == "keyDown") { - session->input_cancel_list.emplace_back( - action_input_states[j], nullptr, nullptr, &event); - session->sticky_modifiers |= KeyToKeyModifiers(event.key); - } else if (action_type == "keyUp") { - session->sticky_modifiers &= ~KeyToKeyModifiers(event.key); - } - - Status status = web_view->DispatchKeyEvents(dispatch_key_events, - async_dispatch_event); + if (action_type != "pause") { + std::list<KeyEvent> dispatch_key_events; + KeyEventBuilder builder; + Status status = ConvertKeyActionToKeyEvent( + action, input_state, action_type == "keyDown", + &dispatch_key_events); if (status.IsError()) return status; + + if (dispatch_key_events.size() > 0) { + const KeyEvent& event = dispatch_key_events.front(); + if (action_type == "keyDown") { + session->input_cancel_list.emplace_back( + action_input_states[j], nullptr, nullptr, &event); + session->sticky_modifiers |= KeyToKeyModifiers(event.key); + } else if (action_type == "keyUp") { + session->sticky_modifiers &= ~KeyToKeyModifiers(event.key); + } + + Status status = web_view->DispatchKeyEvents( + dispatch_key_events, async_dispatch_event); + if (status.IsError()) + return status; + } } } else if (type == "pointer") { std::string pointer_type; @@ -1433,54 +1437,57 @@ } if (pointer_type == "mouse" || pointer_type == "pen") { - std::list<MouseEvent> dispatch_mouse_events; - int click_count = 0; - if (action_type == "pointerDown" || action_type == "pointerUp") { - std::string button; - action->GetString("button", &button); - button_type[id] = button; - click_count = 1; - } else if (buttons[id] == 0) { - button_type[id].clear(); + if (action_type != "pause") { + std::list<MouseEvent> dispatch_mouse_events; + int click_count = 0; + if (action_type == "pointerDown" || + action_type == "pointerUp") { + std::string button; + action->GetString("button", &button); + button_type[id] = button; + click_count = 1; + } else if (buttons[id] == 0) { + button_type[id].clear(); + } + MouseEvent event(StringToMouseEventType(action_type), + StringToMouseButton(button_type[id]), + action_locations[id].x(), + action_locations[id].y(), 0, buttons[id], + click_count); + event.pointer_type = StringToPointerType(pointer_type); + event.modifiers = session->sticky_modifiers; + if (event.type == kPressedMouseEventType) { + base::TimeTicks timestamp = base::TimeTicks::Now(); + bool is_repeated_click = IsRepeatedClickEvent( + event.x, event.y, session->mouse_position.x, + session->mouse_position.y, session->click_count, + timestamp, session->mouse_click_timestamp); + event.click_count = is_repeated_click ? 2 : 1; + buttons[id] |= StringToModifierMouseButton(button_type[id]); + session->mouse_position = WebPoint(event.x, event.y); + session->click_count = event.click_count; + session->mouse_click_timestamp = timestamp; + session->input_cancel_list.emplace_back( + action_input_states[j], &event, nullptr, nullptr); + action_input_states[j]->SetInteger( + "pressed", + action_input_states[j]->FindKey("pressed")->GetInt() | + (1 << event.button)); + } else if (event.type == kReleasedMouseEventType) { + event.click_count = session->click_count; + buttons[id] &= ~StringToModifierMouseButton(button_type[id]); + action_input_states[j]->SetInteger( + "pressed", + action_input_states[j]->FindKey("pressed")->GetInt() & + ~(1 << event.button)); + } + dispatch_mouse_events.push_back(event); + Status status = web_view->DispatchMouseEvents( + dispatch_mouse_events, session->GetCurrentFrameId(), + async_dispatch_event); + if (status.IsError()) + return status; } - MouseEvent event(StringToMouseEventType(action_type), - StringToMouseButton(button_type[id]), - action_locations[id].x(), - action_locations[id].y(), 0, buttons[id], - click_count); - event.pointer_type = StringToPointerType(pointer_type); - event.modifiers = session->sticky_modifiers; - if (event.type == kPressedMouseEventType) { - base::TimeTicks timestamp = base::TimeTicks::Now(); - bool is_repeated_click = IsRepeatedClickEvent( - event.x, event.y, session->mouse_position.x, - session->mouse_position.y, session->click_count, timestamp, - session->mouse_click_timestamp); - event.click_count = is_repeated_click ? 2 : 1; - buttons[id] |= StringToModifierMouseButton(button_type[id]); - session->mouse_position = WebPoint(event.x, event.y); - session->click_count = event.click_count; - session->mouse_click_timestamp = timestamp; - session->input_cancel_list.emplace_back( - action_input_states[j], &event, nullptr, nullptr); - action_input_states[j]->SetInteger( - "pressed", - action_input_states[j]->FindKey("pressed")->GetInt() | - (1 << event.button)); - } else if (event.type == kReleasedMouseEventType) { - event.click_count = session->click_count; - buttons[id] &= ~StringToModifierMouseButton(button_type[id]); - action_input_states[j]->SetInteger( - "pressed", - action_input_states[j]->FindKey("pressed")->GetInt() & - ~(1 << event.button)); - } - dispatch_mouse_events.push_back(event); - Status status = web_view->DispatchMouseEvents( - dispatch_mouse_events, session->GetCurrentFrameId(), - async_dispatch_event); - if (status.IsError()) - return status; } else if (pointer_type == "touch") { if (action_type == "pointerDown") has_touch_start[id] = true; @@ -1497,12 +1504,12 @@ if (has_touch_start[id]) { event.id = dispatch_touch_events.size(); dispatch_touch_events.push_back(event); - if (j == last_touch_index) { - Status status = web_view->DispatchTouchEventWithMultiPoints( - dispatch_touch_events, async_dispatch_event); - if (status.IsError()) - return status; - } + } + if (j == last_touch_index) { + Status status = web_view->DispatchTouchEventWithMultiPoints( + dispatch_touch_events, async_dispatch_event); + if (status.IsError()) + return status; } if (action_type == "pointerUp") has_touch_start[id] = false;
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-iconrow_three_icons.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-iconrow_three_icons.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..680787b --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-iconrow_three_icons.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +3d24f985df143ce89ea302499e04c4fcfc1c5009 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..52b5ca3 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +a4201a720f7bd86bd2d2ee430c5d474a46045c49 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard_with_icon.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard_with_icon.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..21ab5b0f --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-standard_with_icon.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +44984e4a09254091ca2ac3952771ad23fd16d649 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_checked.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_checked.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..6b26c6f --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_checked.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +4ff7987d03f4de39eb9d2a6061a4a4a6248880b5 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..5fbfc8f --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +5c2314ad7f5c94b41e68643918d6964922868281 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_icon.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_icon.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..d2634e10 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Disabled-title_button_icon.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +b3af4981e29bd780534a3b878ed573e962775197 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_five_icons.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_five_icons.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..a0b854f5 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_five_icons.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +67229cbe52704eb08a204ca4dabfc10f755f00ab \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_four_icons.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_four_icons.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..b2b00f5 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_four_icons.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +fd8c57b066236bfae0828a0817e10f24b1c7daa4 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_three_icons.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_three_icons.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..8c6da34 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-iconrow_three_icons.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +79ebf03db99fec18e683c1c2ce89574f0bd26dbd \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..49e5de1 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +aee3b1f0f4ebedc3f638a67a1ac10e8a1f3ad26f \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard_with_icon.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard_with_icon.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..566be68 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-standard_with_icon.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +0e97b9dadad0f6eea64a632a6d68fea31f4a210a \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_checked.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_checked.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..c26c987 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_checked.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +549f55ccbd398fa52b9d189fd3d8fd02f7f5ef47 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..8c92610 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_checkbox_unchecked.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +2dcf682967bd4c02f2907d4e2802ec68f6b0c078 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_icon.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_icon.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..b3b4d5c7 --- /dev/null +++ b/chrome/test/data/android/render_tests/AppMenuAdapterRenderTest.Enabled-title_button_icon.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +cdd099bbe651bac77d857e67ba1a9ac5c011b2af \ No newline at end of file
diff --git a/chrome/test/data/arc_graphics_tracing/gm_good.json b/chrome/test/data/arc_graphics_tracing/gm_good.json index 126e6005..5198ee3 100644 --- a/chrome/test/data/arc_graphics_tracing/gm_good.json +++ b/chrome/test/data/arc_graphics_tracing/gm_good.json
@@ -5,7 +5,13 @@ "chrome": { "buffers": [ [ [ 500, 1667.0 ], [ 501, 1808.0 ] ] ], "global_events": [ ] }, "system": { "threads": {}, "cpu": [], "memory": []}, - "duration": 1053800.0, + "information": { + "duration": 1000.0, + "icon": "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAALL0lEQVRogb2ae4wdV33HP7+ZuXcfXq/tLcTeuEmTFFBlnEZAIMUJqeIKi7gS9I+SphaP2qAGRGJoJR7FCbitUNUiUlVRSsSjEFMFMG1FhQixokDVEKKUVhYVMgR2N/Y6Thzb9+7e9X3tnTnn2z9m5t7Zu3s3fiwdafbOzplzzud7fr/fmfMYY40OSQEQAAK8makv3bJ0y9L9WtRrl5M5gzYzcyukGVDK/o37BWXPhIAuR8wlCcjAlUNJGgFeB9wE3ABcB0wAI1mWFlAFZoCfAM8AR82sleU30oZYE6usBm4ZfP7/DkkPSprRxR/TWd4dxYbJxPxK4IvgOyUd6QNykuLsTLLTZWf+f57u+vIekbRzpbrWCj7MficlHVoB2knyK5z5sVJaMW9+HJI0WaxzLeFvl3Qyqyjx3ieSvPe+C5hdX8hRFOgLFlJWx+1rIqIA/+FChR1J3vncBL4L7r3XRYhYSUincL3/skQU4A9khSaSEt8tXyqyJt5pjYQUrXHgkkQoCyJJ+7OCYknO+dRTFmJp/+zjetvxz+nByg9Vd21JkvMuFaJLElIUkceHJN1TZLoY+F1FeElKvLzk9MhLXjx5Rlt+9lltnP6wbn7+H/StxtFu9Yl3cn3WuEAhg0TsGiQi6IO39EebgYdJhwX5EEAeTAo460RkryRY+ADjXMfPOcHeucO8Y/6f+FHnOKEFBBiJ0he0meXlv1z7WXaK3rBDwMOSrsjYlrwn+hVZ9na9H9gCJPkzqRJhBoEFKHAkGqN+9k8o+6sZGxKPx9PsXvgSH2j8K9O+QmQhhpHIg6VCJF2IkCJfkrH8fca2sgBJgZl5SW8B9mQZw0IrWH4pQEEIoQM/zuILe0k6WxgreYIg4gudZ7i18RCfaT9BTW0iC0DgLlxIoU7CjGWPpLdkjF3uogXy0g4WrosF9W4FggBkIUQO+XHcyb3Enc2o1GbCxllQm3vbR7il8Y98rfM/CAgJ8BJefolbDRDSX7cytiIrecAGZiZJbwJuA3yh9ZeNTYShQFhRhBuH4/ugPUkS1olUYlMwwi/9Od7bPMyuxpf4DzedxUdAIpfSrR4fef1hxnSbpDdmrEG/BQD2Zr/5qHDlUg0IUhFdS5QcuHE0sxfak/iwQeKNYSuxIRjm+26KtzW+zHub3+Tn/gyRhcsCXRIsF5LfyJn2FRODLLNXOiTend0f2PoAsvTEeiKwEPWJsLCF9wFOnnEbpmwhhzo/5pb65/lU+whVNdNAl5Bc2jBmqYiekKIVAHZLGsmH3kEhIF4PXE3P71aNMALIpjNgyq5Td8KNw8w+1J6EqIkU4uQRMB6M0qDDX7cfZ0f9AR7q/DfzQYAsxMuDXGZiikKKTFeTzj2QFOR9LcDvZA+4IucgC3QFBKAgFbEksJNxmN6HWpMQNkEBkieRJ7CATQzzrNW5b+HLzD27G+aPpHktBJ+kKD0hOYvLGN+cMxZj4IZBwMsE5PKsJ4LAkAnCpTHBdBrYCpugEAwi75gPQ34jbvHkie9w7bnvoV/sJpj5Y2j9FIIoRVOSWXhZW/52fhHQC45relirTzXNlj6prjV6IpbExPT7oDWJohaRM+phmV+P6zw69Qi/1XqBpDRGEJSxyjfg2R3ohY9DchZZhORzNyrWem3KYS7vPo10Dps/uPqrMgfvBjMFl8piol/EzPuJmpuplxO2LjZ47JdfZ1vrJeJwhNDHGELhKFILe+nv0NSNMP/PYAFiiQiAiXxIkbtQBAwvxRt8LGuPfiF9ga2SJ4rXU5/9IFsbG3jsuYfZ1jhLHA0TZb2PBPgEswCFIxCfxE69G2v8AAhQ2t3mXMMZ87L3wAUd3SDO3affIt17qYjIi/qYsbXa4bGP/YJtMy3isZAoUQ9ehWvAgpAkAeeT9B0xgCV7D5AA7UIDr+pClv/J+7ACeBoT6vZOkRz10ZCttQqPffGjbPvpLPHXbiE6NQqjMXJGvmQkQsyEkhbteIz4igewsbciOYIg6nJJaptZQq9Kk6RqQcDqLlS0QN4TdQNa2a8RkcJfuVDhew/8BdtOHmdx4yjhXAm+cCO8OIZGY+RDLAjBteh0RHv9+wlec5ThybsxfLedCw1bJRtad19kkp4rtP7Lj3cLPt/tiawArwL8/Z/ktSdnaI2MEXaELztUG0IPvZHg9EZsuEXcbtEa3oVe/Z+MvPqLlEevSbtRgny81GXLWAGCbgx47//3ZaGLFij4f2qBntuEPoWfrFV49G8PsH12hvrIesLE4QE5Q6MQnCsR/821NM68geRV32B4+xGGNr0ZlCB5zCJg+Wi1yBrlrR3H8dNhGJqZ5WOOga5kKqSmc7hUFEbkHPV1IZOVKo9+5l6un52hNraecpLgDSwICLzHnV2gvnkT/s4/Y+ymP6S0sYzkkYRZtGSYXVhXDSVZHMdP54xRPiiqVCpHr7zyylkzu0qSzGxgD5W/2KVsepMNwqIka/lKle/+1b1sPzHD3Nh6ynGCDwNCA9Xq1IdC3B1vZ/R972Jky+a0LJ+kcUBQBO+1meQtfWnNViqVo1m6j1IQBWbWarfbjw4NDd2VrTbnuVeYD+R3s97DspYfSeG/8+n7uP74DHPr11NyDsIIazZpJTHxrTcyetd72HD9ttR4SQJhiAVRBq4ieK+6lClyzn33qquuauUzyKj45OLi4lfK5fJdZhamplw+COkpyqaWZoSJozEasuVclX8/cB/bj89QGV/PkIR1PIvNBTqvfRVDd+3h1976u4SAnENmWNRzl0HVZR4RSqIVx18pJka5KdJn7L86nc4PSqXSzqyfzeNhacnqtXyYOJrrUvhvf+JTbH/uOaqbNjLc6RCfX2Bx8hWU9r+LiTvfTnloCPl0WG1h2O/nK8Evaf1Oknx/w7p1P85YfVdAAVL1ev3gxo2bduYzPfJdl+JyRu7z3lFbFzJ5rsq/fezTbD9xgvkNGwnPzVNfVyZ49zvY9Kd3MvLKV6SFOQdB0Jt9DQbP6zaywaYkmvV6PifuvhO6AvLZvpk92Wy1HhkZHt4DxKQmNJnlvTCYYd5RHwvZcrbKv3z0L7n+xCzVoISv1uD33sSGu/cwvu01KUniIAyWtPoq4Bmv8iUeB5Ta7fYjExMTT+a+PyiXSbKpqakr4jh+Ub2VY0nysU8XDT83n4gz0tafVfXU7o9o4ZrbNfWbv6+ZP7hb5574UXe93MdJdxX4QlfnCqvdyur2i3H84tTU1BU532rKu8t3lUpll3MuL8TJe8UphR6qO00887yevu1DOjtxm47duk8vfvXb6iwuphCJk0/zXu7SYuKcU6VSGbi0OEhECFCr1e7JCust7nrvT0v+iU9+XrNv2KOZz35VzXPVvPnkk+RSV6lXXBedq9XuKTJd8JFnmJ8/f6BQaJJtZUjOqRXHvdovHbwfPt+a0vz8/KUtr+fH4SzjXK2237l8S0MdL/nuvpBz/mL9fAB4d4PDOefn5ub2Fxku+cjVn6lWb28vLuZbTM57n8hf/BZT8fneLd9t9fbi4skzZ6prs8XUL+LYsWOT9XrzUAHUa5VNvoJFVtvk87mwer1+6NixY2u7yVcQ0e0Bnj99emej1TrilrZ4Lqa7zeq9d977lbZZuxmdc2o0WkeeP336V7fNWih4yUb38VOndtTOn39wsdOZflnf6TsWO53p2vnzDx4/deqyNrov6uFiRdD71OD+w4dH/ujmm183Ojp2U6kc3SDpuiiKlnxqkCRJ1cxm4k7nJ81m85lvPvXU0T+/447/308NVhKyiq/aOw8eLL/z4MEygxaJpfBy3eWSLDAApvi5zbIvULL0fA63Zp/b/B8Ly26Q6snKKAAAAABJRU5ErkJggg==", "platform": "CrOS 12642.0.0 (Official Build) dev-channel eve-arcvm test", + "platform": "CrOS 12642.0.0 (Official Build) dev-channel eve", + "timestamp": 1.572898642036e+12, + "title": "Play Store" + }, "views": [ { "activity": "com.android.vending/com.android.vending.AssetBrowserActivity", "buffers": [ [ [ 200, 0.0 ], [ 201, 149.0 ] ], [ [ 300, 168.0 ], [ 202, 173.0 ] ] ],
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc index 6da9530..aea56c2 100644 --- a/chrome/updater/installer.cc +++ b/chrome/updater/installer.cc
@@ -57,6 +57,21 @@ return component; } +std::vector<std::string> Installer::FindAppIds() { + base::FilePath app_install_dir; + if (!GetProductDirectory(&app_install_dir)) + return {}; + app_install_dir = app_install_dir.AppendASCII(kAppsDir); + std::vector<std::string> app_ids; + base::FileEnumerator file_enumerator(app_install_dir, false, + base::FileEnumerator::DIRECTORIES); + for (auto path = file_enumerator.Next(); !path.value().empty(); + path = file_enumerator.Next()) { + app_ids.push_back(path.BaseName().MaybeAsASCII()); + } + return app_ids; +} + void Installer::FindInstallOfApp() { VLOG(1) << __func__ << " for " << app_id_;
diff --git a/chrome/updater/installer.h b/chrome/updater/installer.h index 8ddc6bd..8333037 100644 --- a/chrome/updater/installer.h +++ b/chrome/updater/installer.h
@@ -40,6 +40,9 @@ const std::string app_id() const { return app_id_; } + // Returns the app ids that are managed by the CRX installer. + static std::vector<std::string> FindAppIds(); + // Finds the highest version install of the app, and updates the install // info for this installer instance. void FindInstallOfApp();
diff --git a/chrome/updater/update_apps.cc b/chrome/updater/update_apps.cc index 331117db..f87a9be 100644 --- a/chrome/updater/update_apps.cc +++ b/chrome/updater/update_apps.cc
@@ -54,9 +54,21 @@ } // namespace int UpdateApps() { - auto installer = base::MakeRefCounted<Installer>(kUpdaterAppId); - installer->FindInstallOfApp(); - const auto component = installer->MakeCrxComponent(); + auto app_ids = Installer::FindAppIds(); + + // Include the app id for the updater if it is not found. This could happen + // before the first update for the updater has been handled. This is a + // temporary workaround until the source of truth for the registered + // version is resolved. + if (!base::Contains(app_ids, kUpdaterAppId)) + app_ids.push_back(kUpdaterAppId); + + std::vector<base::Optional<update_client::CrxComponent>> components; + for (const auto& app_id : app_ids) { + auto installer = base::MakeRefCounted<Installer>(app_id); + installer->FindInstallOfApp(); + components.push_back(installer->MakeCrxComponent()); + } base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI); base::RunLoop runloop; @@ -71,17 +83,16 @@ Observer observer(update_client); update_client->AddObserver(&observer); - const std::vector<std::string> ids = {installer->app_id()}; update_client->Update( - ids, + app_ids, base::BindOnce( - [](const update_client::CrxComponent& component, - const std::vector<std::string>& ids) - -> std::vector<base::Optional<update_client::CrxComponent>> { - DCHECK_EQ(1u, ids.size()); - return {component}; + [](const std::vector<base::Optional<update_client::CrxComponent>>& + components, + const std::vector<std::string>& ids) { + DCHECK_EQ(components.size(), ids.size()); + return components; }, - component), + components), false, base::BindOnce( [](base::OnceClosure closure, update_client::Error error) {
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 387368a4..704abfd7a 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -23,13 +23,16 @@ #include "chrome/updater/win/setup/uninstall.h" #endif -// To install the updater on Windows, run: -// "updater.exe --install --enable-logging --v=1 --vmodule=*/chrome/updater/*" -// from the build directory. The program needs a number of dependencies which -// are available in the |out| directory of the build. -// To uninstall, run "updater.exe --uninstall" from its install directory or -// from the build out directory. Doing this will make the program delete its -// install directory using a shim cmd script. +// To install the updater on Windows, run "updatersetup.exe" from the +// build directory. +// +// To uninstall, run "updater.exe --uninstall" from its install directory, +// which is under %LOCALAPPDATA%\Google\GoogleUpdater, or from the |out| +// directory of the build. +// +// To debug, use the command line arguments: +// --enable-logging --vmodule=*/chrome/updater/*=2. + namespace updater { namespace { @@ -86,8 +89,7 @@ int UpdaterInstallApp() { #if defined(OS_WIN) // TODO(sorin): pick up the app id from the tag. https://crbug.com/1014298 - // For now, use Omaha4 app id, just to get a CRX for testing of the UI. - return InstallApp({kUpdaterAppId}); + return InstallApp({kChromeAppId}); #else NOTREACHED(); return -1;
diff --git a/chrome/updater/updater_constants.cc b/chrome/updater/updater_constants.cc index 98c647f..9582178 100644 --- a/chrome/updater/updater_constants.cc +++ b/chrome/updater/updater_constants.cc
@@ -20,7 +20,6 @@ const char kInitDoneNotifierSwitch[] = "init-done-notifier"; const char kNoRateLimitSwitch[] = "no-rate-limit"; const char kEnableLoggingSwitch[] = "enable-logging"; -const char kLoggingLevelSwitch[] = "v"; const char kLoggingModuleSwitch[] = "vmodule"; // URLs.
diff --git a/chrome/updater/updater_constants.h b/chrome/updater/updater_constants.h index c7d28a0..efc153d 100644 --- a/chrome/updater/updater_constants.h +++ b/chrome/updater/updater_constants.h
@@ -44,9 +44,6 @@ // Enables logging. extern const char kEnableLoggingSwitch[]; -// Specifies the logging level. -extern const char kLoggingLevelSwitch[]; - // Specifies the logging module filter. extern const char kLoggingModuleSwitch[]; @@ -59,7 +56,7 @@ extern const char kCrashUploadURL[]; extern const char kCrashStagingUploadURL[]; -// Paths. +// File system paths. // // The directory name where CRX apps get installed. This is provided for demo // purposes, since products installed by this updater will be installed in
diff --git a/chrome/updater/win/constants.cc b/chrome/updater/win/constants.cc index 64ee4e4..ed41efe 100644 --- a/chrome/updater/win/constants.cc +++ b/chrome/updater/win/constants.cc
@@ -6,7 +6,9 @@ namespace updater { -// The prefix to use for global names in WIN32 API's. const base::char16 kGlobalPrefix[] = L"Global\\G"; +extern const base::char16 kRegistryValuePV[] = L"pv"; +extern const base::char16 kRegistryValueName[] = L"name"; + } // namespace updater
diff --git a/chrome/updater/win/constants.h b/chrome/updater/win/constants.h index 7cd037d..77870b2 100644 --- a/chrome/updater/win/constants.h +++ b/chrome/updater/win/constants.h
@@ -6,6 +6,7 @@ #define CHROME_UPDATER_WIN_CONSTANTS_H_ #include "base/strings/string16.h" +#include "chrome/updater/updater_version.h" namespace updater { @@ -13,6 +14,17 @@ // to avoid collision on kernel object names. extern const base::char16 kGlobalPrefix[]; +// Registry keys and value names. +#define COMPANY_KEY "Software\\" COMPANY_SHORTNAME_STRING "\\" +// Use |Update| instead of PRODUCT_FULLNAME_STRING for the registry key name +// to be backward compatible with Google Update / Omaha. +#define UPDATER_KEY COMPANY_KEY "Update\\" +#define CLIENTS_KEY UPDATER_KEY "Clients\\" +#define CLIENT_STATE_KEY UPDATER_KEY "ClientState\\" + +extern const base::char16 kRegistryValuePV[]; +extern const base::char16 kRegistryValueName[]; + } // namespace updater #endif // CHROME_UPDATER_WIN_CONSTANTS_H_
diff --git a/chrome/updater/win/installer/create_installer_archive.py b/chrome/updater/win/installer/create_installer_archive.py index 3fd6da8..53ac848e 100644 --- a/chrome/updater/win/installer/create_installer_archive.py +++ b/chrome/updater/win/installer/create_installer_archive.py
@@ -256,6 +256,10 @@ g_archive_inputs.append(setup_component_dll) shutil.copy(setup_component_dll, installer_dir) + # Handle the ICU data file dependency. + g_archive_inputs.append("icudtl.dat") + shutil.copy("icudtl.dat", installer_dir) + def main(options): """Main method that reads input file, creates archive file and writes resource input file.
diff --git a/chrome/updater/win/installer/installer.cc b/chrome/updater/win/installer/installer.cc index 8c24319..de29c9b 100644 --- a/chrome/updater/win/installer/installer.cc +++ b/chrome/updater/win/installer/installer.cc
@@ -208,7 +208,8 @@ return ProcessExitResult(COMMAND_STRING_OVERFLOW); } - if (!cmd_line.append(L" --install --enable-logging --v=1")) + if (!cmd_line.append( + L" --install --enable-logging --vmodule=*/chrome/updater/*=2")) return ProcessExitResult(COMMAND_STRING_OVERFLOW); return RunProcessAndWait(setup_exe.get(), cmd_line.get());
diff --git a/chrome/updater/win/net/network_winhttp.cc b/chrome/updater/win/net/network_winhttp.cc index c029453..43923cd9 100644 --- a/chrome/updater/win/net/network_winhttp.cc +++ b/chrome/updater/win/net/network_winhttp.cc
@@ -212,6 +212,9 @@ HRESULT NetworkFetcherWinHTTP::SendRequest(const std::string& data) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + VLOG(2) << data; + const uint32_t bytes_to_send = base::saturated_cast<uint32_t>(data.size()); void* request_body = bytes_to_send ? const_cast<char*>(data.c_str()) : WINHTTP_NO_REQUEST_DATA; @@ -232,7 +235,7 @@ request_handle_.get(), WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, &all); - VLOG(2) << "request headers: " << all; + VLOG(3) << "request headers: " << all; net_error_ = ReceiveResponse(); if (FAILED(net_error_)) @@ -252,7 +255,7 @@ base::string16 all; QueryHeadersString(request_handle_.get(), WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, &all); - VLOG(2) << "response headers: " << all; + VLOG(3) << "response headers: " << all; int response_code = 0; net_error_ = QueryHeadersInt(request_handle_.get(), WINHTTP_QUERY_STATUS_CODE, @@ -518,7 +521,7 @@ base::StringAppendF(&msg, ", info=%s", base::SysWideToUTF8(info_string).c_str()); - VLOG(2) << "WinHttp status callback:" + VLOG(3) << "WinHttp status callback:" << " handle=" << handle << ", " << msg; switch (status) {
diff --git a/chrome/updater/win/setup/setup.cc b/chrome/updater/win/setup/setup.cc index 2848c5c..25054d4a 100644 --- a/chrome/updater/win/setup/setup.cc +++ b/chrome/updater/win/setup/setup.cc
@@ -15,28 +15,33 @@ #include "base/logging.h" #include "base/path_service.h" #include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" #include "base/win/scoped_com_initializer.h" -#include "chrome/installer/util/copy_tree_work_item.h" #include "chrome/installer/util/self_cleaning_temp_dir.h" #include "chrome/installer/util/work_item_list.h" #include "chrome/updater/updater_constants.h" #include "chrome/updater/util.h" +#include "chrome/updater/win/constants.h" #include "chrome/updater/win/setup/setup_util.h" #include "chrome/updater/win/task_scheduler.h" +#include "chrome/updater/win/util.h" namespace updater { namespace { const base::char16* kUpdaterFiles[] = { + L"icudtl.dat", L"updater.exe", L"uninstall.cmd", #if defined(COMPONENT_BUILD) // TODO(sorin): get the list of component dependencies from a build-time // file instead of hardcoding the names of the components here. L"base.dll", + L"base_i18n.dll", L"boringssl.dll", L"crcrypto.dll", + L"icui18n.dll", L"icuuc.dll", L"libc++.dll", L"prefs.dll", @@ -90,18 +95,28 @@ for (const auto* file : kUpdaterFiles) { const base::FilePath target_path = product_dir.Append(file); const base::FilePath source_path = source_dir.Append(file); - install_list->AddWorkItem( - WorkItem::CreateCopyTreeWorkItem(source_path, target_path, temp_dir, - WorkItem::ALWAYS, base::FilePath())); + install_list->AddCopyTreeWorkItem(source_path.value(), target_path.value(), + temp_dir.value(), WorkItem::ALWAYS); + } + + for (const auto& key_path : + {GetRegistryKeyClientsUpdater(), GetRegistryKeyClientStateUpdater()}) { + install_list->AddCreateRegKeyWorkItem(HKEY_CURRENT_USER, key_path, + WorkItem::kWow64Default); + install_list->AddSetRegValueWorkItem( + HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default, kRegistryValuePV, + base::ASCIIToUTF16(UPDATER_VERSION_STRING), true); + install_list->AddSetRegValueWorkItem( + HKEY_CURRENT_USER, key_path, WorkItem::kWow64Default, + kRegistryValueName, base::ASCIIToUTF16(PRODUCT_FULLNAME_STRING), true); } base::CommandLine run_updater_ua_command(product_dir.Append(L"updater.exe")); run_updater_ua_command.AppendSwitch(kUpdateAppsSwitch); #if !defined(NDEBUG) run_updater_ua_command.AppendSwitch(kEnableLoggingSwitch); - run_updater_ua_command.AppendSwitchASCII(kLoggingLevelSwitch, "1"); run_updater_ua_command.AppendSwitchASCII(kLoggingModuleSwitch, - "*/chrome/updater/*"); + "*/chrome/updater/*=2"); #endif if (!install_list->Do() || !RegisterUpdateAppsTask(run_updater_ua_command)) { LOG(ERROR) << "Install failed, rolling back...";
diff --git a/chrome/updater/win/setup/uninstall.cc b/chrome/updater/win/setup/uninstall.cc index 8767e26..744f900 100644 --- a/chrome/updater/win/setup/uninstall.cc +++ b/chrome/updater/win/setup/uninstall.cc
@@ -16,17 +16,21 @@ #include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "base/win/scoped_com_initializer.h" +#include "chrome/installer/util/work_item_list.h" #include "chrome/updater/updater_constants.h" #include "chrome/updater/util.h" +#include "chrome/updater/win/constants.h" #include "chrome/updater/win/setup/setup_util.h" #include "chrome/updater/win/task_scheduler.h" namespace updater { // Reverses the changes made by setup. This is a best effort uninstall: -// 1. deletes the scheduled task. -// 2. runs the uninstall script in the install directory of the updater. +// 1. Deletes the scheduled task. +// 2. Deletes the Clients and ClientState keys. +// 3. Runs the uninstall script in the install directory of the updater. // The execution of this function and the script race each other but the script // loops and waits in between iterations trying to delete the install directory. int Uninstall() { @@ -45,6 +49,16 @@ updater::UnregisterUpdateAppsTask(); + std::unique_ptr<WorkItemList> uninstall_list(WorkItem::CreateWorkItemList()); + uninstall_list->AddDeleteRegKeyWorkItem(HKEY_CURRENT_USER, + base::ASCIIToUTF16(UPDATER_KEY), + WorkItem::kWow64Default); + if (!uninstall_list->Do()) { + LOG(ERROR) << "Failed to delete the registry keys."; + uninstall_list->Rollback(); + return -1; + } + base::FilePath product_dir; if (!GetProductDirectory(&product_dir)) { LOG(ERROR) << "GetProductDirectory failed."; @@ -60,8 +74,7 @@ base::FilePath script_path = product_dir.AppendASCII(kUninstallScript); base::string16 cmdline = cmd_path; - base::StringAppendF(&cmdline, L" /Q /C \"%ls\"", - script_path.AsUTF16Unsafe().c_str()); + base::StringAppendF(&cmdline, L" /Q /C \"%ls\"", script_path.value().c_str()); base::LaunchOptions options; options.start_hidden = true;
diff --git a/chrome/updater/win/util.cc b/chrome/updater/win/util.cc index f5a6446..708f1f85 100644 --- a/chrome/updater/win/util.cc +++ b/chrome/updater/win/util.cc
@@ -13,8 +13,10 @@ #include "base/guid.h" #include "base/logging.h" #include "base/process/process_iterator.h" +#include "base/strings/strcat.h" #include "base/strings/string16.h" -#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/updater/updater_constants.h" #include "chrome/updater/win/constants.h" #include "chrome/updater/win/user_info.h" @@ -168,7 +170,7 @@ HANDLE* unique_event) { DCHECK(unique_event); - const base::string16 event_name = base::SysUTF8ToWide(base::GenerateGUID()); + const base::string16 event_name = base::ASCIIToUTF16(base::GenerateGUID()); NamedObjectAttributes attr; GetNamedObjectAttributes(event_name.c_str(), is_machine, &attr); @@ -301,4 +303,13 @@ GetAdminDaclSecurityDescriptor(&sd, accessmask); sec_attr->Set(sd); } + +base::string16 GetRegistryKeyClientsUpdater() { + return base::ASCIIToUTF16(base::StrCat({CLIENTS_KEY, kUpdaterAppId})); +} + +base::string16 GetRegistryKeyClientStateUpdater() { + return base::ASCIIToUTF16(base::StrCat({CLIENT_STATE_KEY, kUpdaterAppId})); +} + } // namespace updater
diff --git a/chrome/updater/win/util.h b/chrome/updater/win/util.h index 4757365d..7ac0e97 100644 --- a/chrome/updater/win/util.h +++ b/chrome/updater/win/util.h
@@ -90,6 +90,14 @@ // to admins and system. void GetAdminDaclSecurityDescriptor(CSecurityDesc* sd, ACCESS_MASK accessmask); +// Returns the registry path for the Updater app id under the |Clients| subkey. +// The path does not include the registry root hive prefix. +base::string16 GetRegistryKeyClientsUpdater(); + +// Returns the registry path for the Updater app id under the |ClientState| +// subkey. The path does not include the registry root hive prefix. +base::string16 GetRegistryKeyClientStateUpdater(); + } // namespace updater #endif // CHROME_UPDATER_WIN_UTIL_H_
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index c38c7c5..6127ccf 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -4,6 +4,12 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") +static_library("feature_status_change") { + sources = [ + "feature_status_change.h", + ] +} + static_library("device_sync") { sources = [ "async_execution_time_metrics_logger.cc", @@ -135,6 +141,7 @@ ] public_deps = [ + ":feature_status_change", "//chromeos/components/multidevice", "//chromeos/components/multidevice/logging", "//chromeos/services/device_sync/public/mojom", @@ -271,6 +278,7 @@ deps = [ ":device_sync", + ":feature_status_change", ":test_support", "//base", "//base/test:test_support",
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_setter.h b/chromeos/services/device_sync/cryptauth_feature_status_setter.h index ac824d2..643fcdf 100644 --- a/chromeos/services/device_sync/cryptauth_feature_status_setter.h +++ b/chromeos/services/device_sync/cryptauth_feature_status_setter.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" #include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/services/device_sync/feature_status_change.h" #include "chromeos/services/device_sync/network_request_error.h" namespace chromeos { @@ -23,20 +24,6 @@ // with the CryptAuth v1 DeviceSync interface. class CryptAuthFeatureStatusSetter { public: - enum class FeatureStatusChange { - // Enables a feature on a device and disables the feature on all other - // devices associated with the account. - kEnableExclusively, - - // Enables a feature on a device; other devices on the account are - // unaffected. - kEnableNonExclusively, - - // Disables a feature on a device; other devices on the account are - // unaffected. - kDisable - }; - CryptAuthFeatureStatusSetter() = default; virtual ~CryptAuthFeatureStatusSetter() = default;
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.h b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.h index b6c75b8..83b8d18 100644 --- a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.h +++ b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.h
@@ -17,6 +17,7 @@ #include "base/timer/timer.h" #include "chromeos/components/multidevice/software_feature.h" #include "chromeos/services/device_sync/cryptauth_feature_status_setter.h" +#include "chromeos/services/device_sync/feature_status_change.h" #include "chromeos/services/device_sync/network_request_error.h" #include "chromeos/services/device_sync/proto/cryptauth_client_app_metadata.pb.h" #include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h"
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl_unittest.cc index 7ab889f..9820a7b 100644 --- a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl_unittest.cc +++ b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl_unittest.cc
@@ -16,6 +16,7 @@ #include "chromeos/services/device_sync/cryptauth_client.h" #include "chromeos/services/device_sync/cryptauth_key_bundle.h" #include "chromeos/services/device_sync/fake_cryptauth_gcm_manager.h" +#include "chromeos/services/device_sync/feature_status_change.h" #include "chromeos/services/device_sync/mock_cryptauth_client.h" #include "chromeos/services/device_sync/network_request_error.h" #include "chromeos/services/device_sync/proto/cryptauth_client_app_metadata.pb.h" @@ -153,10 +154,9 @@ .WillByDefault(testing::Return(kAccessTokenUsed)); } - void SetFeatureStatus( - const std::string& device_id, - multidevice::SoftwareFeature feature, - CryptAuthFeatureStatusSetter::FeatureStatusChange status_change) { + void SetFeatureStatus(const std::string& device_id, + multidevice::SoftwareFeature feature, + FeatureStatusChange status_change) { feature_status_setter_->SetFeatureStatus( device_id, feature, status_change, base::BindOnce(&DeviceSyncCryptAuthFeatureStatusSetterImplTest:: @@ -286,22 +286,21 @@ // sequentially. SetFeatureStatus("device_id_1", multidevice::SoftwareFeature::kSmartLockClient, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kDisable); - SetFeatureStatus( - "device_id_2", multidevice::SoftwareFeature::kInstantTetheringHost, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kEnableNonExclusively); - SetFeatureStatus( - "device_id_3", multidevice::SoftwareFeature::kSmartLockHost, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kEnableExclusively); + FeatureStatusChange::kDisable); + SetFeatureStatus("device_id_2", + multidevice::SoftwareFeature::kInstantTetheringHost, + FeatureStatusChange::kEnableNonExclusively); + SetFeatureStatus("device_id_3", multidevice::SoftwareFeature::kSmartLockHost, + FeatureStatusChange::kEnableExclusively); SetFeatureStatus("device_id_4", multidevice::SoftwareFeature::kInstantTetheringClient, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kDisable); + FeatureStatusChange::kDisable); SetFeatureStatus("device_id_5", multidevice::SoftwareFeature::kInstantTetheringClient, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kDisable); - SetFeatureStatus( - "device_id_6", multidevice::SoftwareFeature::kBetterTogetherHost, - CryptAuthFeatureStatusSetter::FeatureStatusChange::kEnableNonExclusively); + FeatureStatusChange::kDisable); + SetFeatureStatus("device_id_6", + multidevice::SoftwareFeature::kBetterTogetherHost, + FeatureStatusChange::kEnableNonExclusively); // base::nullopt indicates a success. std::vector<base::Optional<NetworkRequestError>> expected_results;
diff --git a/chromeos/services/device_sync/feature_status_change.h b/chromeos/services/device_sync/feature_status_change.h new file mode 100644 index 0000000..5cb9c35 --- /dev/null +++ b/chromeos/services/device_sync/feature_status_change.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 CHROMEOS_SERVICES_DEVICE_SYNC_FEATURE_STATUS_CHANGE_H_ +#define CHROMEOS_SERVICES_DEVICE_SYNC_FEATURE_STATUS_CHANGE_H_ + +namespace chromeos { + +namespace device_sync { + +// The target status change for a device's SoftwareFeature. +enum class FeatureStatusChange { + // Enables a feature on a device and disables the feature on all other devices + // associated with the account. + kEnableExclusively = 0, + + // Enables a feature on a device; other devices on the account are unaffected. + kEnableNonExclusively = 1, + + // Disables a feature on a device; other devices on the account are + // unaffected. + kDisable = 2 +}; + +} // namespace device_sync + +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_FEATURE_STATUS_CHANGE_H_
diff --git a/chromeos/services/device_sync/public/mojom/BUILD.gn b/chromeos/services/device_sync/public/mojom/BUILD.gn index 0914e33..f1c33c9 100644 --- a/chromeos/services/device_sync/public/mojom/BUILD.gn +++ b/chromeos/services/device_sync/public/mojom/BUILD.gn
@@ -26,6 +26,8 @@ ":mojom", "//base", "//base/test:test_support", + "//chromeos/services/device_sync:feature_status_change", + "//chromeos/services/device_sync/proto", "//mojo/public/cpp/test_support:test_utils", "//testing/gtest", ]
diff --git a/chromeos/services/device_sync/public/mojom/device_sync.mojom b/chromeos/services/device_sync/public/mojom/device_sync.mojom index 434347ca..9b572cd 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync.mojom +++ b/chromeos/services/device_sync/public/mojom/device_sync.mojom
@@ -42,6 +42,20 @@ kUnknown }; +enum FeatureStatusChange { + // Enables a feature on a device and disables the feature on all other + // devices associated with the account. + kEnableExclusively, + + // Enables a feature on a device; other devices on the account are + // unaffected. + kEnableNonExclusively, + + // Disables a feature on a device; other devices on the account are + // unaffected. + kDisable +}; + struct FindEligibleDevicesResponse { array<chromeos.multidevice.mojom.RemoteDevice> eligible_devices; array<chromeos.multidevice.mojom.RemoteDevice> ineligible_devices;
diff --git a/chromeos/services/device_sync/public/mojom/device_sync.typemap b/chromeos/services/device_sync/public/mojom/device_sync.typemap index 0796284..0ea534f 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync.typemap +++ b/chromeos/services/device_sync/public/mojom/device_sync.typemap
@@ -4,8 +4,10 @@ mojom = "//chromeos/services/device_sync/public/mojom/device_sync.mojom" -public_headers = - [ "//chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" ] +public_headers = [ + "//chromeos/services/device_sync/feature_status_change.h", + "//chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h", +] traits_headers = [ "//chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h", @@ -16,4 +18,12 @@ "//chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h", ] -type_mappings = [ "chromeos.device_sync.mojom.ConnectivityStatus=cryptauthv2::ConnectivityStatus" ] +public_deps = [ + "//chromeos/services/device_sync:feature_status_change", + "//chromeos/services/device_sync/proto", +] + +type_mappings = [ + "chromeos.device_sync.mojom.ConnectivityStatus=cryptauthv2::ConnectivityStatus", + "chromeos.device_sync.mojom.FeatureStatusChange=chromeos::device_sync::FeatureStatusChange", +]
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc index df4dc71..1a8a0a1 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc +++ b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc
@@ -43,4 +43,41 @@ return false; } +chromeos::device_sync::mojom::FeatureStatusChange +EnumTraits<chromeos::device_sync::mojom::FeatureStatusChange, + chromeos::device_sync::FeatureStatusChange>:: + ToMojom(chromeos::device_sync::FeatureStatusChange input) { + switch (input) { + case chromeos::device_sync::FeatureStatusChange::kEnableExclusively: + return chromeos::device_sync::mojom::FeatureStatusChange:: + kEnableExclusively; + case chromeos::device_sync::FeatureStatusChange::kEnableNonExclusively: + return chromeos::device_sync::mojom::FeatureStatusChange:: + kEnableNonExclusively; + case chromeos::device_sync::FeatureStatusChange::kDisable: + return chromeos::device_sync::mojom::FeatureStatusChange::kDisable; + } +} + +bool EnumTraits<chromeos::device_sync::mojom::FeatureStatusChange, + chromeos::device_sync::FeatureStatusChange>:: + FromMojom(chromeos::device_sync::mojom::FeatureStatusChange input, + chromeos::device_sync::FeatureStatusChange* out) { + switch (input) { + case chromeos::device_sync::mojom::FeatureStatusChange::kEnableExclusively: + *out = chromeos::device_sync::FeatureStatusChange::kEnableExclusively; + return true; + case chromeos::device_sync::mojom::FeatureStatusChange:: + kEnableNonExclusively: + *out = chromeos::device_sync::FeatureStatusChange::kEnableNonExclusively; + return true; + case chromeos::device_sync::mojom::FeatureStatusChange::kDisable: + *out = chromeos::device_sync::FeatureStatusChange::kDisable; + return true; + } + + NOTREACHED(); + return false; +} + } // namespace mojo
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h index 4dd9d46..c5d7019 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h +++ b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h
@@ -5,11 +5,13 @@ #ifndef CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ #define CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ +#include "chromeos/services/device_sync/feature_status_change.h" #include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" #include "mojo/public/cpp/bindings/enum_traits.h" namespace mojo { + template <> class EnumTraits<chromeos::device_sync::mojom::ConnectivityStatus, cryptauthv2::ConnectivityStatus> { @@ -20,6 +22,16 @@ cryptauthv2::ConnectivityStatus* out); }; +template <> +class EnumTraits<chromeos::device_sync::mojom::FeatureStatusChange, + chromeos::device_sync::FeatureStatusChange> { + public: + static chromeos::device_sync::mojom::FeatureStatusChange ToMojom( + chromeos::device_sync::FeatureStatusChange input); + static bool FromMojom(chromeos::device_sync::mojom::FeatureStatusChange input, + chromeos::device_sync::FeatureStatusChange* out); +}; + } // namespace mojo -#endif // CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ \ No newline at end of file +#endif // CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc index 2fa4983..485c759 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc +++ b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc
@@ -4,6 +4,7 @@ #include "chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h" +#include "chromeos/services/device_sync/feature_status_change.h" #include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" #include "mojo/public/cpp/test_support/test_utils.h" @@ -27,3 +28,25 @@ EXPECT_EQ(status_in, status_out); } } + +TEST(DeviceSyncMojomTraitsTest, FeatureStatusChange) { + static constexpr chromeos::device_sync::FeatureStatusChange + kTestFeatureStatusChanges[] = { + chromeos::device_sync::FeatureStatusChange::kEnableExclusively, + chromeos::device_sync::FeatureStatusChange::kEnableNonExclusively, + chromeos::device_sync::FeatureStatusChange::kDisable}; + + for (auto status_in : kTestFeatureStatusChanges) { + chromeos::device_sync::FeatureStatusChange status_out; + + chromeos::device_sync::mojom::FeatureStatusChange serialized_status = + mojo::EnumTraits< + chromeos::device_sync::mojom::FeatureStatusChange, + chromeos::device_sync::FeatureStatusChange>::ToMojom(status_in); + ASSERT_TRUE( + (mojo::EnumTraits<chromeos::device_sync::mojom::FeatureStatusChange, + chromeos::device_sync::FeatureStatusChange>:: + FromMojom(serialized_status, &status_out))); + EXPECT_EQ(status_in, status_out); + } +}
diff --git a/components/autofill/content/common/mojom/autofill_agent.mojom b/components/autofill/content/common/mojom/autofill_agent.mojom index a1d4dc6..89c14a3 100644 --- a/components/autofill/content/common/mojom/autofill_agent.mojom +++ b/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -85,6 +85,10 @@ // because the browser process will own the popup UI. FillPasswordForm(PasswordFormFillData form_data); + // Lets the renderer know that there are no saved credentials for filling. + // This is the "no results" equivalent of FillPasswordForm. + InformNoSavedCredentials(); + // Fills the given |credential| into the last focused text input. FillIntoFocusedField(bool is_password, mojo_base.mojom.String16 credential);
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index d61f694..71b2dff 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1500,7 +1500,7 @@ if (doc.IsNull()) return false; WebFormControlElement field = - FindFormControlElementsByUniqueRendererId(doc, field_renderer_id); + FindFormControlElementByUniqueRendererId(doc, field_renderer_id); return field.IsNull() ? false : IsWebElementVisible(field); } @@ -2144,7 +2144,7 @@ return WebFormElement(); } -WebFormControlElement FindFormControlElementsByUniqueRendererId( +WebFormControlElement FindFormControlElementByUniqueRendererId( WebDocument doc, uint32_t form_control_renderer_id) { WebElementCollection elements = doc.All();
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h index a87157c..d213d9bd 100644 --- a/components/autofill/content/renderer/form_autofill_util.h +++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -284,7 +284,7 @@ // Returns form control element by unique renderer id. Return null element if // there is no element with given renderer id. -blink::WebFormControlElement FindFormControlElementsByUniqueRendererId( +blink::WebFormControlElement FindFormControlElementByUniqueRendererId( blink::WebDocument doc, uint32_t form_control_renderer_id);
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index 433bfc8..c2326fd 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -503,12 +503,12 @@ auto input2 = doc.GetElementById("i2").To<WebInputElement>(); uint32_t non_existing_id = input2.UniqueRendererFormControlId() + 1000; - EXPECT_EQ(input1, FindFormControlElementsByUniqueRendererId( + EXPECT_EQ(input1, FindFormControlElementByUniqueRendererId( doc, input1.UniqueRendererFormControlId())); - EXPECT_EQ(input2, FindFormControlElementsByUniqueRendererId( + EXPECT_EQ(input2, FindFormControlElementByUniqueRendererId( doc, input2.UniqueRendererFormControlId())); EXPECT_TRUE( - FindFormControlElementsByUniqueRendererId(doc, non_existing_id).IsNull()); + FindFormControlElementByUniqueRendererId(doc, non_existing_id).IsNull()); } TEST_F(FormAutofillUtilsTest, FindFormControlElementsByUniqueIdNoForm) {
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 9ecfb5f..2d8b2737 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -74,6 +74,7 @@ namespace autofill { +using form_util::FindFormControlElementByUniqueRendererId; using form_util::FindFormControlElementsByUniqueRendererId; using form_util::IsFormControlVisible; using form_util::IsFormVisible; @@ -389,7 +390,7 @@ const std::string& text) { if (renderer_id == FormData::kNotSetFormRendererId) return; - auto element = FindFormControlElementsByUniqueRendererId(doc, renderer_id); + auto element = FindFormControlElementByUniqueRendererId(doc, renderer_id); if (element.IsNull()) return; element.SetAttribute( @@ -1280,6 +1281,30 @@ "confirmation_password_element"); } +void PasswordAutofillAgent::InformNoSavedCredentials() { + autofilled_elements_cache_.clear(); + + // Clear the actual field values. + WebDocument doc = render_frame()->GetWebFrame()->GetDocument(); + std::vector<WebFormControlElement> elements = + FindFormControlElementsByUniqueRendererId( + doc, std::vector<uint32_t>(all_autofilled_elements_.begin(), + all_autofilled_elements_.end())); + for (WebFormControlElement& element : elements) { + if (element.IsNull()) + continue; + element.SetSuggestedValue(blink::WebString()); + // Don't clear the actual value of fields that the user has edited manually + // (which changes the autofill state back to kNotFilled). + if (element.GetAutofillState() == WebAutofillState::kAutofilled) + element.SetValue(blink::WebString()); + element.SetAutofillState(WebAutofillState::kNotFilled); + } + all_autofilled_elements_.clear(); + + field_data_manager_.ClearData(); +} + void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) { DCHECK(!node.IsNull()); focused_input_element_.Reset(); @@ -1422,6 +1447,7 @@ username_detector_cache_.clear(); forms_structure_cache_.clear(); autofilled_elements_cache_.clear(); + all_autofilled_elements_.clear(); last_updated_field_renderer_id_ = FormData::kNotSetFormRendererId; last_updated_form_renderer_id_ = FormData::kNotSetFormRendererId; touch_to_fill_state_ = TouchToFillState::kShouldShow; @@ -1834,6 +1860,7 @@ field, value, FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD); autofilled_elements_cache_.emplace(field.UniqueRendererFormControlId(), WebString::FromUTF16(value)); + all_autofilled_elements_.insert(field.UniqueRendererFormControlId()); } void PasswordAutofillAgent::SetLastUpdatedFormAndField(
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index 81b0e38..7530c051 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -7,6 +7,7 @@ #include <map> #include <memory> +#include <set> #include <string> #include <utility> #include <vector> @@ -126,6 +127,7 @@ // mojom::PasswordAutofillAgent: void FillPasswordForm(const PasswordFormFillData& form_data) override; + void InformNoSavedCredentials() override; void FillIntoFocusedField(bool is_password, const base::string16& credential) override; void SetLoggingState(bool active) override; @@ -532,13 +534,13 @@ bool prefilled_username_metrics_logged_ = false; // Keeps autofilled values for the form elements. - std::map<unsigned /*unique renderer element id*/, blink::WebString> + std::map<unsigned /*renderer id*/, blink::WebString> autofilled_elements_cache_; + std::set<unsigned /*renderer id*/> all_autofilled_elements_; // Keeps forms structure (amount of elements, element types etc). // TODO(crbug/898109): It's too expensive to keep the whole FormData // structure. Replace FormData with a smaller structure. - std::map<unsigned /*unique renderer element id*/, FormStructureInfo> - forms_structure_cache_; + std::map<unsigned /*renderer id*/, FormStructureInfo> forms_structure_cache_; // Flag to prevent that multiple PasswordManager.FirstRendererFillingResult // UMA metrics are recorded per page load. This is reset on
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index e5095c1..9ab8098 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -293,7 +293,7 @@ if (doc.IsNull()) return; WebFormControlElement new_password_input = - form_util::FindFormControlElementsByUniqueRendererId( + form_util::FindFormControlElementByUniqueRendererId( doc, form.new_password_renderer_id); if (!new_password_input.IsNull()) { // Mark the input element with renderer id @@ -612,7 +612,7 @@ std::vector<blink::WebInputElement> passwords = {generation_element}; WebFormControlElement confirmation_password = - form_util::FindFormControlElementsByUniqueRendererId( + form_util::FindFormControlElementByUniqueRendererId( generation_element.GetDocument(), confirmation_password_renderer_id); if (!confirmation_password.IsNull()) {
diff --git a/components/autofill_assistant/browser/client_status.cc b/components/autofill_assistant/browser/client_status.cc index 18566c3..710d2d34 100644 --- a/components/autofill_assistant/browser/client_status.cc +++ b/components/autofill_assistant/browser/client_status.cc
@@ -113,6 +113,9 @@ case ProcessedActionStatusProto::AUTOFILL_INFO_NOT_AVAILABLE: out << "AUTOFILL_INFO_NOT_AVAILABLE"; break; + case ProcessedActionStatusProto::FRAME_HOST_NOT_FOUND: + out << "FRAME_HOST_NOT_FOUND"; + break; // Intentionally no default case to make compilation fail if a new value // was added to the enum but not to this list.
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index d1af2238..9e8f5df 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -725,6 +725,9 @@ // The requested autofill info (e.g., Chrome password manager login) was not // available. It might have been recently deleted. AUTOFILL_INFO_NOT_AVAILABLE = 21; + + // An unexpected error occurred during element resolution. + FRAME_HOST_NOT_FOUND = 22; } // The pseudo type values come from
diff --git a/components/autofill_assistant/browser/web/element_finder.cc b/components/autofill_assistant/browser/web/element_finder.cc index 8e2387f..158253d4 100644 --- a/components/autofill_assistant/browser/web/element_finder.cc +++ b/components/autofill_assistant/browser/web/element_finder.cc
@@ -166,11 +166,11 @@ return; } - // The frame gets set again when we encounter an iFrame, even an OOPIF. - // Setting the correct host frame is handled by - // FindCorrespondingRenderFrameHost further down. - element_result_->container_frame_host = web_contents_->GetMainFrame(); element_result_->container_frame_selector_index = index; + if (element_result_->container_frame_host == nullptr) { + // Don't overwrite results from previous OOPIF passes. + element_result_->container_frame_host = web_contents_->GetMainFrame(); + } element_result_->object_id = std::string(); RecursiveFindElement(object_id, index); } @@ -346,38 +346,61 @@ auto* node = result->GetNode(); std::vector<int> backend_ids; + if (node->HasContentDocument()) { + // If the frame has a ContentDocument, it's considered a local frame. + // We need to resolve the RenderFrameHost for autofill. + backend_ids.emplace_back(node->GetContentDocument()->GetBackendNodeId()); element_result_->container_frame_selector_index = index; - // Find out the corresponding render frame host through document url and - // name. - // TODO(crbug.com/806868): Use more attributes to find out the render frame - // host if name and document url are not enough to uniquely identify it. - std::string frame_name; - if (node->HasAttributes()) { - const std::vector<std::string>* attributes = node->GetAttributes(); - for (size_t i = 0; i < attributes->size();) { - if ((*attributes)[i] == "name") { - frame_name = (*attributes)[i + 1]; - break; + if (node->HasFrameId()) { + element_result_->container_frame_host = + FindCorrespondingRenderFrameHost(node->GetFrameId()); + } else { + // TODO(b/143318024): Remove the fallback. + std::string frame_name; + if (node->HasAttributes()) { + const std::vector<std::string>* attributes = node->GetAttributes(); + for (size_t i = 0; i < attributes->size();) { + if ((*attributes)[i] == "name") { + frame_name = (*attributes)[i + 1]; + break; + } + // Jump two positions since attribute name and value are always + // paired. + i = i + 2; } - // Jump two positions since attribute name and value are always paired. - i = i + 2; } + element_result_->container_frame_host = FindCorrespondingRenderFrameHost( + frame_name, node->GetContentDocument()->GetDocumentURL()); } - element_result_->container_frame_host = FindCorrespondingRenderFrameHost( - frame_name, node->GetContentDocument()->GetDocumentURL()); + if (!element_result_->container_frame_host) { DVLOG(1) << __func__ << " Failed to find corresponding owner frame."; - SendResult( - UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__)); + SendResult(ClientStatus(FRAME_HOST_NOT_FOUND)); return; } } else if (node->HasFrameId()) { - element_result_->container_frame_selector_index = index; + // If the frame has no ContentDocument, it's considered an + // OutOfProcessIFrame. + // See https://www.chromium.org/developers/design-documents/oop-iframes for + // full documentation. + // We need to assign the frame id, such that devtools can resolve the + // session calls should be executed on. We also need to resolve the + // RenderFrameHost for autofill. + element_result_->node_frame_id = node->GetFrameId(); + element_result_->container_frame_selector_index = index; + element_result_->container_frame_host = + FindCorrespondingRenderFrameHost(node->GetFrameId()); + + if (!element_result_->container_frame_host) { + DVLOG(1) << __func__ << " Failed to find corresponding owner frame."; + SendResult(ClientStatus(FRAME_HOST_NOT_FOUND)); + return; + } // Kick off another find element chain to walk down the OOP iFrame. devtools_client_->GetRuntime()->Evaluate( @@ -421,6 +444,17 @@ } content::RenderFrameHost* ElementFinder::FindCorrespondingRenderFrameHost( + std::string frame_id) { + for (auto* frame : web_contents_->GetAllFrames()) { + if (frame->GetDevToolsFrameToken().ToString() == frame_id) { + return frame; + } + } + + return nullptr; +} + +content::RenderFrameHost* ElementFinder::FindCorrespondingRenderFrameHost( std::string name, std::string document_url) { content::RenderFrameHost* ret_frame = nullptr;
diff --git a/components/autofill_assistant/browser/web/element_finder.h b/components/autofill_assistant/browser/web/element_finder.h index 3103d6f..880bc86c 100644 --- a/components/autofill_assistant/browser/web/element_finder.h +++ b/components/autofill_assistant/browser/web/element_finder.h
@@ -89,6 +89,8 @@ std::unique_ptr<dom::ResolveNodeResult> result); content::RenderFrameHost* FindCorrespondingRenderFrameHost( + std::string frame_id); + content::RenderFrameHost* FindCorrespondingRenderFrameHost( std::string name, std::string document_url);
diff --git a/components/media_message_center/media_notification_view.cc b/components/media_message_center/media_notification_view.cc index 70e9a42..22d1524 100644 --- a/components/media_message_center/media_notification_view.cc +++ b/components/media_message_center/media_notification_view.cc
@@ -157,12 +157,14 @@ title_label->SetFontList(base_font_list.Derive( 0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM)); title_label->SetLineHeight(kTitleArtistLineHeight); + title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_label_ = title_artist_row_->AddChildView(std::move(title_label)); auto artist_label = std::make_unique<views::Label>( base::string16(), views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY); artist_label->SetLineHeight(kTitleArtistLineHeight); + artist_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); artist_label_ = title_artist_row_->AddChildView(std::move(artist_label)); // |button_row_| contains the buttons for controlling playback.
diff --git a/components/metrics/metrics_service_client.cc b/components/metrics/metrics_service_client.cc index cda7b6c..35f363b 100644 --- a/components/metrics/metrics_service_client.cc +++ b/components/metrics/metrics_service_client.cc
@@ -73,11 +73,11 @@ return false; } -bool MetricsServiceClient::SyncStateAllowsUkm() { +bool MetricsServiceClient::IsUkmAllowedForAllProfiles() { return false; } -bool MetricsServiceClient::SyncStateAllowsExtensionUkm() { +bool MetricsServiceClient::IsUkmAllowedWithExtensionsForAllProfiles() { return false; }
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h index 9dd4e3d..7fb97f2 100644 --- a/components/metrics/metrics_service_client.h +++ b/components/metrics/metrics_service_client.h
@@ -131,19 +131,22 @@ // Returns whether cellular logic is enabled for metrics reporting. virtual bool IsUMACellularUploadLogicEnabled(); - // Returns true iff sync is in a state that allows UKM to be enabled. - // See //components/ukm/observers/sync_disable_observer.h for details. - virtual bool SyncStateAllowsUkm(); + // Returns true iff UKM is allowed for all profiles. + // See //components/ukm/observers/ukm_consent_state_observer.h for details. + virtual bool IsUkmAllowedForAllProfiles(); - // Returns true iff sync is in a state that allows UKM to capture extensions. - // See //components/ukm/observers/sync_disable_observer.h for details. - virtual bool SyncStateAllowsExtensionUkm(); + // Returns true iff UKM is allowed to capture extensions for all profiles. + // See //components/ukm/observers/ukm_consent_state_observer.h for details. + virtual bool IsUkmAllowedWithExtensionsForAllProfiles(); // Returns whether UKM notification listeners were attached to all profiles. virtual bool AreNotificationListenersEnabledOnAllProfiles(); - // Gets Chrome's package name in Android Chrome, or the host app's package - // name in Android WebView, or an empty string on other platforms. + // Gets the app package name (as defined by the embedder). Since package name + // is only meaningful for Android, other platforms should return the empty + // string (this is the same as the default behavior). If the package name + // should not be logged for privacy/fingerprintability reasons, the embedder + // should return the empty string. virtual std::string GetAppPackageName(); // Gets the key used to sign metrics uploads. This will be used to compute an
diff --git a/components/metrics_services_manager/metrics_services_manager.cc b/components/metrics_services_manager/metrics_services_manager.cc index 45b13b13..08f69b2 100644 --- a/components/metrics_services_manager/metrics_services_manager.cc +++ b/components/metrics_services_manager/metrics_services_manager.cc
@@ -146,13 +146,13 @@ metrics_service_client_->AreNotificationListenersEnabledOnAllProfiles(); bool sync_enabled = metrics_service_client_->IsMetricsReportingForceEnabled() || - metrics_service_client_->SyncStateAllowsUkm(); + metrics_service_client_->IsUkmAllowedForAllProfiles(); bool is_incognito = client_->IsIncognitoSessionActive(); if (consent_given_ && listeners_active && sync_enabled && !is_incognito) { // TODO(skare): revise this - merged in a big change ukm->EnableRecording( - metrics_service_client_->SyncStateAllowsExtensionUkm()); + metrics_service_client_->IsUkmAllowedWithExtensionsForAllProfiles()); if (may_upload_) ukm->EnableReporting(); else
diff --git a/components/module_installer/android/module.cc b/components/module_installer/android/module.cc index c20f0b6..0c7f64db7 100644 --- a/components/module_installer/android/module.cc +++ b/components/module_installer/android/module.cc
@@ -41,7 +41,8 @@ typedef bool JniRegistrationFunction(JNIEnv* env); -void* LoadLibrary(const std::string& library_name) { +void* LoadLibrary(const std::string& library_name, + const std::string& module_name) { void* library_handle = nullptr; #if defined(LOAD_FROM_PARTITIONS) @@ -50,7 +51,9 @@ // operation on the Java side, because JNI registration is done explicitly // (hence there is no reason for the Java ClassLoader to be aware of the // library, for lazy JNI registration). - library_handle = BundleUtils::DlOpenModuleLibraryPartition(library_name); + const std::string partition_name = module_name + "_partition"; + library_handle = + BundleUtils::DlOpenModuleLibraryPartition(library_name, partition_name); #elif defined(COMPONENT_BUILD) const std::string lib_name = "lib" + library_name + ".so"; library_handle = dlopen(lib_name.c_str(), RTLD_LOCAL); @@ -58,7 +61,7 @@ #error "Unsupported configuration." #endif // defined(COMPONENT_BUILD) CHECK(library_handle != nullptr) - << "Could not open feature library: " << dlerror(); + << "Could not open feature library " << library_name << ": " << dlerror(); return library_handle; } @@ -94,7 +97,7 @@ if (libraries.size() > 0) { void* library_handle = nullptr; for (const auto& library : libraries) { - library_handle = LoadLibrary(library); + library_handle = LoadLibrary(library, name); } // module libraries are ordered such that the root library will be the last // item in the list. We expect this library to provide the JNI registration
diff --git a/components/os_crypt/key_storage_linux.cc b/components/os_crypt/key_storage_linux.cc index 48810de..c16d6a2 100644 --- a/components/os_crypt/key_storage_linux.cc +++ b/components/os_crypt/key_storage_linux.cc
@@ -34,6 +34,32 @@ const char KeyStorageLinux::kKey[] = "Chromium Safe Storage"; #endif +namespace { + +const char* SelectedLinuxBackendToString( + os_crypt::SelectedLinuxBackend selection) { + switch (selection) { + case os_crypt::SelectedLinuxBackend::DEFER: + return "DEFER"; + case os_crypt::SelectedLinuxBackend::BASIC_TEXT: + return "BASIC_TEXT"; + case os_crypt::SelectedLinuxBackend::GNOME_ANY: + return "GNOME_ANY"; + case os_crypt::SelectedLinuxBackend::GNOME_KEYRING: + return "GNOME_KEYRING"; + case os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET: + return "GNOME_LIBSECRET"; + case os_crypt::SelectedLinuxBackend::KWALLET: + return "KWALLET"; + case os_crypt::SelectedLinuxBackend::KWALLET5: + return "KWALLET5"; + } + NOTREACHED(); + return nullptr; +} + +} // namespace + // static std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateService( const os_crypt::Config& config) { @@ -46,6 +72,8 @@ base::nix::GetDesktopEnvironment(env.get()); os_crypt::SelectedLinuxBackend selected_backend = os_crypt::SelectBackend(config.store, use_backend, desktop_env); + VLOG(1) << "Selected backend for OSCrypt: " + << SelectedLinuxBackendToString(selected_backend); // TODO(crbug.com/782851) Schedule the initialisation on each backend's // favourite thread. @@ -62,6 +90,7 @@ VLOG(1) << "OSCrypt using Libsecret as backend."; return key_storage; } + LOG(WARNING) << "OSCrypt tried Libsecret but couldn't initialise."; } #endif // defined(USE_LIBSECRET) @@ -73,6 +102,7 @@ VLOG(1) << "OSCrypt using Keyring as backend."; return key_storage; } + LOG(WARNING) << "OSCrypt tried Keyring but couldn't initialise."; } #endif // defined(USE_KEYRING) @@ -90,12 +120,14 @@ VLOG(1) << "OSCrypt using KWallet as backend."; return key_storage; } + LOG(WARNING) << "OSCrypt tried KWallet but couldn't initialise."; } #endif // defined(USE_KWALLET) #endif // defined(USE_LIBSECRET) || defined(USE_KEYRING) || // defined(USE_KWALLET) - // The appropriate store was not available. + // Either there are no supported backends on this platform, or we chose to + // use no backend, or the chosen backend failed to initialise. VLOG(1) << "OSCrypt did not initialize a backend."; return nullptr; }
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index 49a3387..de06635 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -109,6 +109,10 @@ autofill::MaybeClearPasswordValues(form_data)); } +void ContentPasswordManagerDriver::InformNoSavedCredentials() { + GetPasswordAutofillAgent()->InformNoSavedCredentials(); +} + void ContentPasswordManagerDriver::FormEligibleForGenerationFound( const autofill::PasswordFormGenerationData& form) { if (GetPasswordGenerationHelper()->IsGenerationEnabled(
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h index b2de32f..ed2ab85 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.h +++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -56,6 +56,7 @@ int GetId() const override; void FillPasswordForm( const autofill::PasswordFormFillData& form_data) override; + void InformNoSavedCredentials() override; void FormEligibleForGenerationFound( const autofill::PasswordFormGenerationData& form) override; void GeneratedPasswordAccepted(const base::string16& password) override;
diff --git a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc index 4c43002..524c78b 100644 --- a/components/password_manager/content/browser/content_password_manager_driver_unittest.cc +++ b/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
@@ -84,6 +84,7 @@ // autofill::mojom::PasswordAutofillAgent: MOCK_METHOD1(FillPasswordForm, void(const PasswordFormFillData&)); + MOCK_METHOD0(InformNoSavedCredentials, void()); MOCK_METHOD2(FillIntoFocusedField, void(bool, const base::string16&)); MOCK_METHOD1(TouchToFillClosed, void(bool)); MOCK_METHOD1(AnnotateFieldsWithParsingResult, void(const ParsingResult&));
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 939ddf80..18146fa 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -469,6 +469,7 @@ "//components/test/data/password_manager/login_db_v22.sql", "//components/test/data/password_manager/login_db_v23.sql", "//components/test/data/password_manager/login_db_v24.sql", + "//components/test/data/password_manager/login_db_v24_broken.sql", "//components/test/data/password_manager/login_db_v25.sql", "//components/test/data/password_manager/login_db_v26.sql", "//components/test/data/password_manager/login_db_v2_broken.sql",
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 6534d99..cada731 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -655,6 +655,13 @@ if (db->DoesColumnExist("logins", "form_data")) *current_version = 4; } + // "date_last_used" columns has been introduced in version 25. if it exists, + // the version should be at least 25. This has been added to address this bug + // (crbug.com/1020320). + if (*current_version < 25) { + if (db->DoesColumnExist("logins", "date_last_used")) + *current_version = 25; + } return true; }
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index e34e6e21..2f8e93f 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -2304,7 +2304,7 @@ testing::Values(9)); INSTANTIATE_TEST_SUITE_P(MigrationToVCurrent, LoginDatabaseMigrationTestBroken, - testing::Range(1, 4)); + testing::Values(1, 2, 3, 24)); class LoginDatabaseUndecryptableLoginsTest : public testing::Test { protected:
diff --git a/components/payments/content/utility/OWNERS b/components/payments/content/utility/OWNERS deleted file mode 100644 index ef1b073..0000000 --- a/components/payments/content/utility/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -per-file payment_manifest_parser.*=jcivelli@chromium.org \ No newline at end of file
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc index 20dcae9..7cb48ed 100644 --- a/components/previews/content/previews_decider_impl_unittest.cc +++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -1536,7 +1536,7 @@ } } -TEST_F(PreviewsDeciderImplTest, DeferAllScriptNotAllowedByDefault) { +TEST_F(PreviewsDeciderImplTest, DeferAllScriptDefaultBehavior) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures( {features::kPreviews, optimization_guide::features::kOptimizationHints}, @@ -1549,8 +1549,15 @@ content::MockNavigationHandle navigation_handle; navigation_handle.set_url(GURL("https://www.google.com")); - EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart( - &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT)); +#if defined(OS_ANDROID) + bool expected = true; +#else // !defined(OS_ANDROID) + bool expected = false; +#endif // defined(OS_ANDROID) + EXPECT_EQ(expected, + previews_decider_impl()->ShouldAllowPreviewAtNavigationStart( + &user_data, &navigation_handle, false, + PreviewsType::DEFER_ALL_SCRIPT)); } TEST_F(PreviewsDeciderImplTest,
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc index 8d4c85e..e6940869 100644 --- a/components/previews/core/previews_features.cc +++ b/components/previews/core/previews_features.cc
@@ -92,7 +92,11 @@ // Support for enabling DeferAllScript previews which includes a base feature // and a UserConsistent-specific experiment feature. const base::FeatureState kDeferAllScriptDefaultFeatureState = +#if defined(OS_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT; +#else // !defined(OS_ANDROID) base::FEATURE_DISABLED_BY_DEFAULT; +#endif // defined(OS_ANDROID) const base::Feature kDeferAllScriptPreviews{"DeferAllScript", kDeferAllScriptDefaultFeatureState}; const base::Feature kDeferAllScriptPreviewsUserConsistentStudy{
diff --git a/components/sync/base/data_type_histogram.h b/components/sync/base/data_type_histogram.h index 1358ae3..6aef5f8 100644 --- a/components/sync/base/data_type_histogram.h +++ b/components/sync/base/data_type_histogram.h
@@ -140,9 +140,6 @@ case ::syncer::DEPRECATED_EXPERIMENTS: \ PER_DATA_TYPE_MACRO("Experiments"); \ break; \ - case ::syncer::MOUNTAIN_SHARES: \ - PER_DATA_TYPE_MACRO("MountainShares"); \ - break; \ case ::syncer::SEND_TAB_TO_SELF: \ PER_DATA_TYPE_MACRO("SendTabToSelf"); \ break; \
diff --git a/components/sync/base/model_type.cc b/components/sync/base/model_type.cc index 8546885..daa05e4 100644 --- a/components/sync/base/model_type.cc +++ b/components/sync/base/model_type.cc
@@ -149,9 +149,6 @@ {USER_EVENTS, "USER_EVENT", "user_events", "User Events", sync_pb::EntitySpecifics::kUserEventFieldNumber, ModelTypeForHistograms::kUserEvents}, - {MOUNTAIN_SHARES, "MOUNTAIN_SHARE", "mountain_shares", "Mountain Shares", - sync_pb::EntitySpecifics::kMountainShareFieldNumber, - ModelTypeForHistograms::kMountainShares}, {USER_CONSENTS, "USER_CONSENT", "user_consent", "User Consents", sync_pb::EntitySpecifics::kUserConsentFieldNumber, ModelTypeForHistograms::kUserConsents}, @@ -189,11 +186,11 @@ static_assert(base::size(kModelTypeInfoMap) == ModelType::NUM_ENTRIES, "kModelTypeInfoMap should have ModelType::NUM_ENTRIES elements"); -static_assert(41 == syncer::ModelType::NUM_ENTRIES, +static_assert(40 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, update enum SyncModelTypes in enums.xml " "and suffix SyncModelType in histograms.xml."); -static_assert(41 == syncer::ModelType::NUM_ENTRIES, +static_assert(40 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, update kAllocatorDumpNameWhitelist in " "base/trace_event/memory_infra_background_whitelist.cc."); @@ -290,9 +287,6 @@ case SECURITY_EVENTS: specifics->mutable_security_event(); break; - case MOUNTAIN_SHARES: - specifics->mutable_mountain_share(); - break; case USER_CONSENTS: specifics->mutable_user_consent(); break; @@ -362,7 +356,7 @@ } ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "When adding new protocol types, the following type lookup " "logic must be updated."); if (specifics.has_bookmark()) @@ -421,8 +415,6 @@ return READING_LIST; if (specifics.has_user_event()) return USER_EVENTS; - if (specifics.has_mountain_share()) - return MOUNTAIN_SHARES; if (specifics.has_user_consent()) return USER_CONSENTS; if (specifics.has_nigori()) @@ -446,7 +438,7 @@ } ModelTypeSet EncryptableUserTypes() { - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "If adding an unencryptable type, remove from " "encryptable_user_types below."); ModelTypeSet encryptable_user_types = UserTypes();
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h index 73d25f124..6e777ce 100644 --- a/components/sync/base/model_type.h +++ b/components/sync/base/model_type.h
@@ -122,8 +122,6 @@ READING_LIST, // Commit only user events. USER_EVENTS, - // Shares in project Mountain. - MOUNTAIN_SHARES, // Commit only user consents. USER_CONSENTS, // Tabs sent between devices. @@ -222,7 +220,7 @@ kPrinters = 37, kReadingList = 38, kUserEvents = 39, - kMountainShares = 40, + // kDeprecatedMountainShares = 40, kUserConsents = 41, kSendTabToSelf = 42, kSecurityEvents = 43, @@ -259,9 +257,8 @@ FAVICON_TRACKING, DEVICE_INFO, PRIORITY_PREFERENCES, SUPERVISED_USER_SETTINGS, APP_LIST, SUPERVISED_USER_WHITELISTS, ARC_PACKAGE, PRINTERS, READING_LIST, USER_EVENTS, NIGORI, - DEPRECATED_EXPERIMENTS, MOUNTAIN_SHARES, USER_CONSENTS, SEND_TAB_TO_SELF, - SECURITY_EVENTS, WEB_APPS, WIFI_CONFIGURATIONS, OS_PREFERENCES, - OS_PRIORITY_PREFERENCES); + DEPRECATED_EXPERIMENTS, USER_CONSENTS, SEND_TAB_TO_SELF, SECURITY_EVENTS, + WEB_APPS, WIFI_CONFIGURATIONS, OS_PREFERENCES, OS_PRIORITY_PREFERENCES); } // These are the normal user-controlled types. This is to distinguish from
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc index 134b6cba..13668be 100644 --- a/components/sync/driver/model_association_manager.cc +++ b/components/sync/driver/model_association_manager.cc
@@ -46,8 +46,8 @@ BOOKMARKS, PREFERENCES, PRIORITY_PREFERENCES, EXTENSIONS, APPS, APP_LIST, ARC_PACKAGE, READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS, DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS, USER_CONSENTS, USER_EVENTS, - SUPERVISED_USER_SETTINGS, SUPERVISED_USER_WHITELISTS, MOUNTAIN_SHARES, - SEND_TAB_TO_SELF, SECURITY_EVENTS, WEB_APPS, WIFI_CONFIGURATIONS}; + SUPERVISED_USER_SETTINGS, SUPERVISED_USER_WHITELISTS, SEND_TAB_TO_SELF, + SECURITY_EVENTS, WEB_APPS, WIFI_CONFIGURATIONS}; static_assert(base::size(kStartOrder) == ModelType::NUM_ENTRIES - FIRST_REAL_MODEL_TYPE,
diff --git a/components/sync/driver/sync_user_settings_impl.cc b/components/sync/driver/sync_user_settings_impl.cc index f13a6c2..76426abb7 100644 --- a/components/sync/driver/sync_user_settings_impl.cc +++ b/components/sync/driver/sync_user_settings_impl.cc
@@ -246,7 +246,7 @@ types.RetainAll(registered_model_types_); } - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "If adding a new sync data type, update the list below below if" " you want to disable the new data type for local sync."); types.PutAll(ControlTypes());
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc index 39a09ca..76640b5 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -374,6 +374,10 @@ strong_consistency_model_enabled_ = true; } +void LoopbackServer::AddNewKeystoreKeyForTesting() { + keystore_keys_.push_back(GenerateNewKeystoreKey()); +} + bool LoopbackServer::HandleGetUpdatesRequest( const sync_pb::GetUpdatesMessage& get_updates, const std::string& store_birthday,
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.h b/components/sync/engine_impl/loopback_server/loopback_server.h index 4b4d928..8edbd4d 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.h +++ b/components/sync/engine_impl/loopback_server/loopback_server.h
@@ -78,6 +78,8 @@ return keystore_keys_; } + void AddNewKeystoreKeyForTesting(); + private: // Allow the FakeServer decorator to inspect the internals of this class. friend class fake_server::FakeServer;
diff --git a/components/sync/nigori/nigori_state.cc b/components/sync/nigori/nigori_state.cc index a5fd52bb..acbee82 100644 --- a/components/sync/nigori/nigori_state.cc +++ b/components/sync/nigori/nigori_state.cc
@@ -61,7 +61,7 @@ void UpdateNigoriSpecificsFromEncryptedTypes( ModelTypeSet encrypted_types, sync_pb::NigoriSpecifics* specifics) { - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "If adding an encryptable type, update handling below."); specifics->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS)); specifics->set_encrypt_preferences(encrypted_types.Has(PREFERENCES)); @@ -87,7 +87,6 @@ specifics->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE)); specifics->set_encrypt_printers(encrypted_types.Has(PRINTERS)); specifics->set_encrypt_reading_list(encrypted_types.Has(READING_LIST)); - specifics->set_encrypt_mountain_shares(encrypted_types.Has(MOUNTAIN_SHARES)); specifics->set_encrypt_send_tab_to_self( encrypted_types.Has(SEND_TAB_TO_SELF)); specifics->set_encrypt_web_apps(encrypted_types.Has(WEB_APPS));
diff --git a/components/sync/protocol/mountain_share_specifics.proto b/components/sync/protocol/mountain_share_specifics.proto deleted file mode 100644 index ea1624c..0000000 --- a/components/sync/protocol/mountain_share_specifics.proto +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (c) 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. -// -// Sync protocol datatype extension for shares of Mountain project. - -// If you change or add any fields in this file, update proto_visitors.h and -// potentially proto_enum_conversions.{h, cc}. - -syntax = "proto2"; - -option java_multiple_files = true; -option java_package = "org.chromium.components.sync.protocol"; - -option optimize_for = LITE_RUNTIME; - -package sync_pb; - -// Properties of share sync objects. -message MountainShareSpecifics { - // Share record GUID. - optional string id = 1; - optional string url = 2; - - // PNG-encoded content of share node favicon. - optional bytes favicon = 3; - optional string title = 4; - - // Time of share node created, as measured by client in milliseconds since - // Windows epoch. - optional int64 creation_time_ms = 5; - optional string icon_url = 6; -}
diff --git a/components/sync/protocol/nigori_specifics.proto b/components/sync/protocol/nigori_specifics.proto index 8ebadf4..d5da76c5 100644 --- a/components/sync/protocol/nigori_specifics.proto +++ b/components/sync/protocol/nigori_specifics.proto
@@ -159,8 +159,8 @@ // Boolean corresponding to whether reading list items should be encrypted. optional bool encrypt_reading_list = 43; - // Boolean corresponding to whether mountain shares should be encrypted. - optional bool encrypt_mountain_shares = 44; + reserved 44; + reserved "encrypt_mountain_shares"; enum KeyDerivationMethod { // This comes from a <= M69 client, who does not know about the field
diff --git a/components/sync/protocol/proto_value_conversions.cc b/components/sync/protocol/proto_value_conversions.cc index b0d82bf5..febc158 100644 --- a/components/sync/protocol/proto_value_conversions.cc +++ b/components/sync/protocol/proto_value_conversions.cc
@@ -327,7 +327,6 @@ IMPLEMENT_PROTO_TO_VALUE(LinkedAppIconInfo) IMPLEMENT_PROTO_TO_VALUE(ManagedUserSettingSpecifics) IMPLEMENT_PROTO_TO_VALUE(ManagedUserWhitelistSpecifics) -IMPLEMENT_PROTO_TO_VALUE(MountainShareSpecifics) IMPLEMENT_PROTO_TO_VALUE(NavigationRedirect) IMPLEMENT_PROTO_TO_VALUE(NigoriSpecifics) IMPLEMENT_PROTO_TO_VALUE(OsPreferenceSpecifics)
diff --git a/components/sync/protocol/proto_value_conversions.h b/components/sync/protocol/proto_value_conversions.h index fb17ecb..c77cf0c 100644 --- a/components/sync/protocol/proto_value_conversions.h +++ b/components/sync/protocol/proto_value_conversions.h
@@ -41,7 +41,6 @@ class LinkedAppIconInfo; class ManagedUserSettingSpecifics; class ManagedUserWhitelistSpecifics; -class MountainShareSpecifics; class NavigationRedirect; class NigoriSpecifics; class OsPreferenceSpecifics; @@ -169,9 +168,6 @@ const sync_pb::ManagedUserWhitelistSpecifics& managed_user_whitelist_specifics); -std::unique_ptr<base::DictionaryValue> MountainShareSpecificsToValue( - const sync_pb::MountainShareSpecifics& mountain_share_specifics); - std::unique_ptr<base::DictionaryValue> NavigationRedirectToValue( const sync_pb::NavigationRedirect& navigation_redirect);
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc index 61cddcc..b818693 100644 --- a/components/sync/protocol/proto_value_conversions_unittest.cc +++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -58,7 +58,7 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(encrypted) -static_assert(41 == syncer::ModelType::NUM_ENTRIES, +static_assert(40 == syncer::ModelType::NUM_ENTRIES, "When adding a new field, add a DEFINE_SPECIFICS_TO_VALUE_TEST " "for your field below, and optionally a test for the specific " "conversions."); @@ -81,7 +81,6 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(history_delete_directive) DEFINE_SPECIFICS_TO_VALUE_TEST(managed_user_setting) DEFINE_SPECIFICS_TO_VALUE_TEST(managed_user_whitelist) -DEFINE_SPECIFICS_TO_VALUE_TEST(mountain_share) DEFINE_SPECIFICS_TO_VALUE_TEST(nigori) DEFINE_SPECIFICS_TO_VALUE_TEST(os_preference) DEFINE_SPECIFICS_TO_VALUE_TEST(os_priority_preference)
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index b57ac25..3bb1ed1 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -22,7 +22,6 @@ #include "components/sync/protocol/favicon_tracking_specifics.pb.h" #include "components/sync/protocol/history_delete_directive_specifics.pb.h" #include "components/sync/protocol/model_type_state.pb.h" -#include "components/sync/protocol/mountain_share_specifics.pb.h" #include "components/sync/protocol/nigori_local_data.pb.h" #include "components/sync/protocol/nigori_specifics.pb.h" #include "components/sync/protocol/os_preference_specifics.pb.h" @@ -366,7 +365,7 @@ } VISIT_PROTO_FIELDS(const sync_pb::EntitySpecifics& proto) { - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "When adding a new protocol type, you will likely need to add " "it here as well."); VISIT(encrypted); @@ -388,7 +387,6 @@ VISIT(history_delete_directive); VISIT(managed_user_setting); VISIT(managed_user_whitelist); - VISIT(mountain_share); VISIT(nigori); VISIT(os_preference); VISIT(os_priority_preference); @@ -570,15 +568,6 @@ VISIT(initial_sync_done); } -VISIT_PROTO_FIELDS(const sync_pb::MountainShareSpecifics& proto) { - VISIT(id); - VISIT(url); - VISIT_BYTES(favicon); - VISIT(title); - VISIT(creation_time_ms); - VISIT(icon_url); -} - VISIT_PROTO_FIELDS(const sync_pb::NavigationRedirect& proto) { VISIT(url); }
diff --git a/components/sync/protocol/protocol_sources.gni b/components/sync/protocol/protocol_sources.gni index 35a494311..981f2f0a 100644 --- a/components/sync/protocol/protocol_sources.gni +++ b/components/sync/protocol/protocol_sources.gni
@@ -35,7 +35,6 @@ "managed_user_whitelist_specifics", "model_type_state", "model_type_store_schema_descriptor", - "mountain_share_specifics", "nigori_local_data", "nigori_specifics", "os_preference_specifics",
diff --git a/components/sync/protocol/sync.proto b/components/sync/protocol/sync.proto index c398dff..bef9fd7 100644 --- a/components/sync/protocol/sync.proto +++ b/components/sync/protocol/sync.proto
@@ -40,7 +40,6 @@ import "managed_user_shared_setting_specifics.proto"; import "managed_user_specifics.proto"; import "managed_user_whitelist_specifics.proto"; -import "mountain_share_specifics.proto"; import "nigori_specifics.proto"; import "os_preference_specifics.proto"; import "os_priority_preference_specifics.proto"; @@ -159,7 +158,6 @@ ReadingListSpecifics reading_list = 411028; UserEventSpecifics user_event = 455206; UserConsentSpecifics user_consent = 556014; - MountainShareSpecifics mountain_share = 545005; SendTabToSelfSpecifics send_tab_to_self = 601980; SecurityEventSpecifics security_event = 600372; WebAppSpecifics web_app = 673225; @@ -171,6 +169,8 @@ reserved "wifi_credential"; reserved 223759; reserved "article"; + reserved 545005; + reserved "mountain_share"; } message SyncEntity {
diff --git a/components/sync/syncable/nigori_util.cc b/components/sync/syncable/nigori_util.cc index 6bbcfecd..2c1ca87 100644 --- a/components/sync/syncable/nigori_util.cc +++ b/components/sync/syncable/nigori_util.cc
@@ -265,7 +265,7 @@ bool encrypt_everything, sync_pb::NigoriSpecifics* nigori) { nigori->set_encrypt_everything(encrypt_everything); - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "If adding an encryptable type, update handling below."); nigori->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS)); nigori->set_encrypt_preferences(encrypted_types.Has(PREFERENCES)); @@ -289,7 +289,6 @@ nigori->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE)); nigori->set_encrypt_printers(encrypted_types.Has(PRINTERS)); nigori->set_encrypt_reading_list(encrypted_types.Has(READING_LIST)); - nigori->set_encrypt_mountain_shares(encrypted_types.Has(MOUNTAIN_SHARES)); nigori->set_encrypt_send_tab_to_self(encrypted_types.Has(SEND_TAB_TO_SELF)); nigori->set_encrypt_web_apps(encrypted_types.Has(WEB_APPS)); nigori->set_encrypt_os_preferences(encrypted_types.Has(OS_PREFERENCES)); @@ -301,7 +300,7 @@ return ModelTypeSet::All(); ModelTypeSet encrypted_types; - static_assert(41 == ModelType::NUM_ENTRIES, + static_assert(40 == ModelType::NUM_ENTRIES, "If adding an encryptable type, update handling below."); if (nigori.encrypt_bookmarks()) encrypted_types.Put(BOOKMARKS); @@ -343,8 +342,6 @@ encrypted_types.Put(PRINTERS); if (nigori.encrypt_reading_list()) encrypted_types.Put(READING_LIST); - if (nigori.encrypt_mountain_shares()) - encrypted_types.Put(MOUNTAIN_SHARES); if (nigori.encrypt_send_tab_to_self()) encrypted_types.Put(SEND_TAB_TO_SELF); if (nigori.encrypt_web_apps())
diff --git a/components/sync/test/fake_server/fake_server.cc b/components/sync/test/fake_server/fake_server.cc index 35d7fce..3e85029 100644 --- a/components/sync/test/fake_server/fake_server.cc +++ b/components/sync/test/fake_server/fake_server.cc
@@ -364,6 +364,20 @@ return loopback_server_->GetKeystoreKeysForTesting(); } +void FakeServer::TriggerKeystoreKeyRotation() { + DCHECK(thread_checker_.CalledOnValidThread()); + loopback_server_->AddNewKeystoreKeyForTesting(); + + std::vector<sync_pb::SyncEntity> nigori_entities = + loopback_server_->GetPermanentSyncEntitiesByModelType(syncer::NIGORI); + + DCHECK_EQ(nigori_entities.size(), 1U); + bool success = ModifyEntitySpecifics( + loopback_server_->GetTopLevelPermanentItemId(syncer::NIGORI), + nigori_entities[0].specifics()); + DCHECK(success); +} + void FakeServer::InjectEntity(std::unique_ptr<LoopbackServerEntity> entity) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(entity->GetModelType() != syncer::AUTOFILL_WALLET_DATA)
diff --git a/components/sync/test/fake_server/fake_server.h b/components/sync/test/fake_server/fake_server.h index cafc4361..5fd49d5 100644 --- a/components/sync/test/fake_server/fake_server.h +++ b/components/sync/test/fake_server/fake_server.h
@@ -100,6 +100,10 @@ // Returns all keystore keys from the server. const std::vector<std::string>& GetKeystoreKeys() const; + // Triggers the keystore key rotation events on the server side: generating + // new keystore key and touching the Nigori node. + void TriggerKeystoreKeyRotation(); + // Adds |entity| to the server's collection of entities. This method makes no // guarantees that the added entity will result in successful server // operations.
diff --git a/components/test/data/password_manager/login_db_v24_broken.sql b/components/test/data/password_manager/login_db_v24_broken.sql new file mode 100644 index 0000000..156604a9 --- /dev/null +++ b/components/test/data/password_manager/login_db_v24_broken.sql
@@ -0,0 +1,127 @@ +-- Version 25 schema with meta.version==24. Tests http://crbug.com/1020320 +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); +INSERT INTO "meta" VALUES('last_compatible_version','19'); +INSERT INTO "meta" VALUES('version','24'); +CREATE TABLE logins ( +origin_url VARCHAR NOT NULL, +action_url VARCHAR, +username_element VARCHAR, +username_value VARCHAR, +password_element VARCHAR, +password_value BLOB, +submit_element VARCHAR, +signon_realm VARCHAR NOT NULL, +preferred INTEGER NOT NULL, +date_created INTEGER NOT NULL, +blacklisted_by_user INTEGER NOT NULL, +scheme INTEGER NOT NULL, +password_type INTEGER, +times_used INTEGER, +form_data BLOB, +date_synced INTEGER, +display_name VARCHAR, +icon_url VARCHAR, +federation_url VARCHAR, +skip_zero_click INTEGER, +generation_upload_status INTEGER, +possible_username_pairs BLOB, +id INTEGER, +date_last_used INTEGER, +UNIQUE (origin_url, username_element, username_value, password_element, signon_realm), +PRIMARY KEY (id)); +INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs,date_last_used) VALUES( +'https://accounts.google.com/ServiceLogin', /* origin_url */ +'https://accounts.google.com/ServiceLoginAuth', /* action_url */ +'Email', /* username_element */ +'theerikchen', /* username_value */ +'Passwd', /* password_element */ +X'', /* password_value */ +'', /* submit_element */ +'https://accounts.google.com/', /* signon_realm */ +1, /* preferred */ +13047429345000000, /* date_created */ +0, /* blacklisted_by_user */ +0, /* scheme */ +0, /* password_type */ +1, /* times_used */ +X'18000000020000000000000000000000000000000000000000000000', /* form_data */ +0, /* date_synced */ +'', /* display_name */ +'', /* icon_url */ +'', /* federation_url */ +1, /* skip_zero_click */ +0, /* generation_upload_status */ +X'00000000', /* possible_username_pairs */ +0 /* date_last_used */ +); +INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs,date_last_used) VALUES( +'https://accounts.google.com/ServiceLogin', /* origin_url */ +'https://accounts.google.com/ServiceLoginAuth', /* action_url */ +'Email', /* username_element */ +'theerikchen2', /* username_value */ +'Passwd', /* password_element */ +X'', /* password_value */ +'non-empty', /* submit_element */ +'https://accounts.google.com/', /* signon_realm */ +1, /* preferred */ +13047423600000000, /* date_created */ +0, /* blacklisted_by_user */ +0, /* scheme */ +0, /* password_type */ +1, /* times_used */ +X'18000000020000000000000000000000000000000000000000000000', /* form_data */ +0, /* date_synced */ +'', /* display_name */ +'https://www.google.com/icon', /* icon_url */ +'', /* federation_url */ +1, /* skip_zero_click */ +0, /* generation_upload_status */ +X'00000000', /* possible_username_pairs */ +0 /* date_last_used */ +); +INSERT INTO "logins" (origin_url,action_url,username_element,username_value,password_element,password_value,submit_element,signon_realm,preferred,date_created,blacklisted_by_user,scheme,password_type,times_used,form_data,date_synced,display_name,icon_url,federation_url,skip_zero_click,generation_upload_status,possible_username_pairs,date_last_used) VALUES( +'http://example.com', /* origin_url */ +'http://example.com/landing', /* action_url */ +'', /* username_element */ +'user', /* username_value */ +'', /* password_element */ +X'', /* password_value */ +'non-empty', /* submit_element */ +'http://example.com', /* signon_realm */ +1, /* preferred */ +13047423600000000, /* date_created */ +0, /* blacklisted_by_user */ +1, /* scheme */ +0, /* password_type */ +1, /* times_used */ +X'18000000020000000000000000000000000000000000000000000000', /* form_data */ +0, /* date_synced */ +'', /* display_name */ +'https://www.google.com/icon', /* icon_url */ +'', /* federation_url */ +1, /* skip_zero_click */ +0, /* generation_upload_status */ +X'00000000', /* possible_username_pairs */ +0 /* date_last_used */ +); +CREATE INDEX logins_signon ON logins (signon_realm); +CREATE TABLE stats ( +origin_domain VARCHAR NOT NULL, +username_value VARCHAR, +dismissal_count INTEGER, +update_time INTEGER NOT NULL, +UNIQUE(origin_domain, username_value)); +CREATE INDEX stats_origin ON stats(origin_domain); +CREATE TABLE sync_entities_metadata ( + storage_key INTEGER, + metadata VARCHAR NOT NULL, + PRIMARY KEY (storage_key) +); +CREATE TABLE sync_model_metadata ( + id INTEGER, + metadata VARCHAR NOT NULL, + PRIMARY KEY (id) +); +COMMIT;
diff --git a/components/test/data/password_manager/login_db_v26.sql b/components/test/data/password_manager/login_db_v26.sql index 5476193..59cee47b 100644 --- a/components/test/data/password_manager/login_db_v26.sql +++ b/components/test/data/password_manager/login_db_v26.sql
@@ -2,7 +2,7 @@ BEGIN TRANSACTION; CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); INSERT INTO "meta" VALUES('last_compatible_version','19'); -INSERT INTO "meta" VALUES('version','25'); +INSERT INTO "meta" VALUES('version','26'); CREATE TABLE logins ( origin_url VARCHAR NOT NULL, action_url VARCHAR,
diff --git a/components/ukm/BUILD.gn b/components/ukm/BUILD.gn index f5de865..9674b5e9 100644 --- a/components/ukm/BUILD.gn +++ b/components/ukm/BUILD.gn
@@ -49,8 +49,8 @@ sources = [ "observers/history_delete_observer.cc", "observers/history_delete_observer.h", - "observers/sync_disable_observer.cc", - "observers/sync_disable_observer.h", + "observers/ukm_consent_state_observer.cc", + "observers/ukm_consent_state_observer.h", ] deps = [ @@ -88,7 +88,7 @@ testonly = true sources = [ "app_source_url_recorder_test.cc", - "observers/sync_disable_observer_unittest.cc", + "observers/ukm_consent_state_observer_unittest.cc", "ukm_recorder_impl_unittest.cc", "ukm_service_unittest.cc", ]
diff --git a/components/ukm/observers/sync_disable_observer.cc b/components/ukm/observers/sync_disable_observer.cc deleted file mode 100644 index 3a19a909..0000000 --- a/components/ukm/observers/sync_disable_observer.cc +++ /dev/null
@@ -1,196 +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 "components/ukm/observers/sync_disable_observer.h" - -#include <memory> -#include <utility> - -#include "base/feature_list.h" -#include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" -#include "components/sync/driver/sync_user_settings.h" -#include "components/unified_consent/url_keyed_data_collection_consent_helper.h" -#include "google_apis/gaia/google_service_auth_error.h" - -using unified_consent::UrlKeyedDataCollectionConsentHelper; - -namespace ukm { - -namespace { - -enum DisableInfo { - DISABLED_BY_NONE, - // All commented values below were deprecated and removed. - // DISABLED_BY_HISTORY, - // DISABLED_BY_INITIALIZED, - // DISABLED_BY_HISTORY_INITIALIZED, - // DISABLED_BY_CONNECTED, - // DISABLED_BY_HISTORY_CONNECTED, - // DISABLED_BY_INITIALIZED_CONNECTED, - // DISABLED_BY_HISTORY_INITIALIZED_CONNECTED, - // DISABLED_BY_PASSPHRASE, - // DISABLED_BY_HISTORY_PASSPHRASE, - // DISABLED_BY_INITIALIZED_PASSPHRASE, - // DISABLED_BY_HISTORY_INITIALIZED_PASSPHRASE, - // DISABLED_BY_CONNECTED_PASSPHRASE, - // DISABLED_BY_HISTORY_CONNECTED_PASSPHRASE, - // DISABLED_BY_INITIALIZED_CONNECTED_PASSPHRASE, - // DISABLED_BY_HISTORY_INITIALIZED_CONNECTED_PASSPHRASE, - DISABLED_BY_ANONYMIZED_DATA_COLLECTION = 16, - MAX_DISABLE_INFO -}; - -void RecordDisableInfo(DisableInfo info) { - UMA_HISTOGRAM_ENUMERATION("UKM.SyncDisable.Info", info, MAX_DISABLE_INFO); -} - -} // namespace - -SyncDisableObserver::SyncDisableObserver() : sync_observer_(this) {} - -SyncDisableObserver::~SyncDisableObserver() { - for (const auto& entry : consent_helpers_) { - entry.second->RemoveObserver(this); - } -} - -bool SyncDisableObserver::SyncState::AllowsUkm() const { - return anonymized_data_collection_enabled; -} - -// static -SyncDisableObserver::SyncState SyncDisableObserver::GetSyncState( - syncer::SyncService* sync_service, - UrlKeyedDataCollectionConsentHelper* consent_helper) { - DCHECK(sync_service); - DCHECK(consent_helper); - SyncState state; - state.anonymized_data_collection_enabled = consent_helper->IsEnabled(); - state.extensions_enabled = - sync_service->GetPreferredDataTypes().Has(syncer::EXTENSIONS) && - sync_service->IsSyncFeatureEnabled(); - return state; -} - -void SyncDisableObserver::ObserveServiceForSyncDisables( - syncer::SyncService* sync_service, - PrefService* prefs) { - std::unique_ptr<UrlKeyedDataCollectionConsentHelper> consent_helper = - UrlKeyedDataCollectionConsentHelper:: - NewAnonymizedDataCollectionConsentHelper(prefs, sync_service); - - SyncState state = GetSyncState(sync_service, consent_helper.get()); - previous_states_[sync_service] = state; - - consent_helper->AddObserver(this); - consent_helpers_[sync_service] = std::move(consent_helper); - sync_observer_.Add(sync_service); - UpdateAllProfileEnabled(false); -} - -void SyncDisableObserver::UpdateAllProfileEnabled(bool must_purge) { - bool all_sync_states_allow_ukm = CheckSyncStateOnAllProfiles(); - bool all_sync_states_allow_extension_ukm = - all_sync_states_allow_ukm && CheckSyncStateForExtensionsOnAllProfiles(); - // Any change in sync settings needs to call OnSyncPrefsChanged so that the - // new settings take effect. - if (must_purge || (all_sync_states_allow_ukm != all_sync_states_allow_ukm_) || - (all_sync_states_allow_extension_ukm != - all_sync_states_allow_extension_ukm_)) { - all_sync_states_allow_ukm_ = all_sync_states_allow_ukm; - all_sync_states_allow_extension_ukm_ = all_sync_states_allow_extension_ukm; - OnSyncPrefsChanged(must_purge); - } -} - -bool SyncDisableObserver::CheckSyncStateOnAllProfiles() { - if (previous_states_.empty()) - return false; - for (const auto& kv : previous_states_) { - const SyncDisableObserver::SyncState& state = kv.second; - - if (state.AllowsUkm()) - continue; - - // Used as output for the disable reason UMA metrics. - DCHECK(!state.anonymized_data_collection_enabled); - RecordDisableInfo(DISABLED_BY_ANONYMIZED_DATA_COLLECTION); - return false; - } - RecordDisableInfo(DISABLED_BY_NONE); - return true; -} - -bool SyncDisableObserver::CheckSyncStateForExtensionsOnAllProfiles() { - if (previous_states_.empty()) - return false; - for (const auto& kv : previous_states_) { - const SyncDisableObserver::SyncState& state = kv.second; - if (!state.extensions_enabled) - return false; - } - return true; -} - -void SyncDisableObserver::OnStateChanged(syncer::SyncService* sync) { - UrlKeyedDataCollectionConsentHelper* consent_helper = nullptr; - auto found = consent_helpers_.find(sync); - if (found != consent_helpers_.end()) - consent_helper = found->second.get(); - UpdateSyncState(sync, consent_helper); -} - -void SyncDisableObserver::OnUrlKeyedDataCollectionConsentStateChanged( - unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) { - DCHECK(consent_helper); - syncer::SyncService* sync_service = nullptr; - for (const auto& entry : consent_helpers_) { - if (consent_helper == entry.second.get()) { - sync_service = entry.first; - break; - } - } - DCHECK(sync_service); - UpdateSyncState(sync_service, consent_helper); -} - -void SyncDisableObserver::UpdateSyncState( - syncer::SyncService* sync, - UrlKeyedDataCollectionConsentHelper* consent_helper) { - DCHECK(base::Contains(previous_states_, sync)); - const SyncDisableObserver::SyncState& previous_state = previous_states_[sync]; - DCHECK(consent_helper); - SyncDisableObserver::SyncState state = GetSyncState(sync, consent_helper); - - // Trigger a purge if the current state no longer allows UKM. - bool must_purge = previous_state.AllowsUkm() && !state.AllowsUkm(); - - UMA_HISTOGRAM_BOOLEAN("UKM.SyncDisable.Purge", must_purge); - - previous_states_[sync] = state; - UpdateAllProfileEnabled(must_purge); -} - -void SyncDisableObserver::OnSyncShutdown(syncer::SyncService* sync) { - DCHECK(base::Contains(previous_states_, sync)); - auto found = consent_helpers_.find(sync); - if (found != consent_helpers_.end()) { - found->second->RemoveObserver(this); - consent_helpers_.erase(found); - } - sync_observer_.Remove(sync); - previous_states_.erase(sync); - UpdateAllProfileEnabled(/*must_purge=*/false); -} - -bool SyncDisableObserver::SyncStateAllowsUkm() { - return all_sync_states_allow_ukm_; -} - -bool SyncDisableObserver::SyncStateAllowsExtensionUkm() { - return all_sync_states_allow_extension_ukm_; -} - -} // namespace ukm
diff --git a/components/ukm/observers/sync_disable_observer.h b/components/ukm/observers/sync_disable_observer.h deleted file mode 100644 index ce19e04d..0000000 --- a/components/ukm/observers/sync_disable_observer.h +++ /dev/null
@@ -1,127 +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 COMPONENTS_UKM_OBSERVERS_SYNC_DISABLE_OBSERVER_H_ -#define COMPONENTS_UKM_OBSERVERS_SYNC_DISABLE_OBSERVER_H_ - -#include <map> - -#include "base/scoped_observer.h" -#include "components/sync/driver/sync_service.h" -#include "components/sync/driver/sync_service_observer.h" -#include "components/unified_consent/url_keyed_data_collection_consent_helper.h" - -class PrefService; - -namespace ukm { - -// Observer that monitors whether UKM is allowed for all profiles. -// -// For one profile, UKM is allowed iff URL-keyed anonymized data collection is -// enabled. -class SyncDisableObserver - : public syncer::SyncServiceObserver, - public unified_consent::UrlKeyedDataCollectionConsentHelper::Observer { - public: - SyncDisableObserver(); - ~SyncDisableObserver() override; - - // Starts observing a service for sync disables. - void ObserveServiceForSyncDisables(syncer::SyncService* sync_service, - PrefService* pref_service); - - // Returns true iff all sync states allow UKM to be enabled. This means that - // URL-keyed anonymized data collection is enabled for all profiles. - virtual bool SyncStateAllowsUkm(); - - // Returns true iff sync is in a state that allows UKM to capture extensions. - // This means that all profiles have EXTENSIONS data type enabled for syncing. - virtual bool SyncStateAllowsExtensionUkm(); - - protected: - // Called after state changes and some profile has sync disabled. - // If |must_purge| is true, sync was disabled for some profile, and - // local data should be purged. - virtual void OnSyncPrefsChanged(bool must_purge) = 0; - - private: - // syncer::SyncServiceObserver: - void OnStateChanged(syncer::SyncService* sync) override; - void OnSyncShutdown(syncer::SyncService* sync) override; - - // unified_consent::UrlKeyedDataCollectionConsentHelper::Observer: - void OnUrlKeyedDataCollectionConsentStateChanged( - unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) - override; - - // Recomputes all_profiles_enabled_ state from previous_states_; - void UpdateAllProfileEnabled(bool must_purge); - - // Returns true iff all sync states in previous_states_ allow UKM. - // If there are no profiles being observed, this returns false. - bool CheckSyncStateOnAllProfiles(); - - // Returns true iff all sync states in previous_states_ allow extension UKM. - // If there are no profiles being observed, this returns false. - bool CheckSyncStateForExtensionsOnAllProfiles(); - - // Tracks observed history services, for cleanup. - ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver> - sync_observer_; - - // State data about sync services that we need to remember. - struct SyncState { - // Returns true if this sync state allows UKM (i.e. URL-keyed anonymized - // data collection is enabled). - bool AllowsUkm() const; - - // Returns true if |AllowUkm| and if sync extensions are enabled. - bool AllowsUkmWithExtension() const; - - // Whether anonymized data collection is enabled. - bool anonymized_data_collection_enabled = false; - - // If the user has extension sync enabled. - bool extensions_enabled = false; - }; - - // Updates the sync state for |sync| service. Updates all profiles if needed. - // |sync| and |consent_helper| must not be null. - void UpdateSyncState( - syncer::SyncService* sync, - unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper); - - // Gets the current state of a SyncService. - // |sync| and |consent_helper| must not be null. - static SyncState GetSyncState( - syncer::SyncService* sync, - unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper); - - // The state of the sync services being observed. - std::map<syncer::SyncService*, SyncState> previous_states_; - - // The list of URL-keyed anonymized data collection consent helpers. - // - // Note: UrlKeyedDataCollectionConsentHelper does not rely on sync but there - // must be exactly one per Chromium profile. As there is a single sync service - // per profile, it is safe to key them by sync service instead of introducing - // an additional map. - std::map< - syncer::SyncService*, - std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>> - consent_helpers_; - - // Tracks if UKM is allowed on all profiles after the last state change. - bool all_sync_states_allow_ukm_ = false; - - // Tracks if extension sync was enabled on all profiles after the last state - // change. - bool all_sync_states_allow_extension_ukm_ = false; - - DISALLOW_COPY_AND_ASSIGN(SyncDisableObserver); -}; - -} // namespace ukm - -#endif // COMPONENTS_UKM_OBSERVERS_SYNC_DISABLE_OBSERVER_H_
diff --git a/components/ukm/observers/ukm_consent_state_observer.cc b/components/ukm/observers/ukm_consent_state_observer.cc new file mode 100644 index 0000000..96bfed06 --- /dev/null +++ b/components/ukm/observers/ukm_consent_state_observer.cc
@@ -0,0 +1,165 @@ +// 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 "components/ukm/observers/ukm_consent_state_observer.h" + +#include <memory> +#include <utility> + +#include "base/feature_list.h" +#include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" +#include "components/sync/driver/sync_user_settings.h" +#include "components/unified_consent/url_keyed_data_collection_consent_helper.h" +#include "google_apis/gaia/google_service_auth_error.h" + +using unified_consent::UrlKeyedDataCollectionConsentHelper; + +namespace ukm { + +UkmConsentStateObserver::UkmConsentStateObserver() : sync_observer_(this) {} + +UkmConsentStateObserver::~UkmConsentStateObserver() { + for (const auto& entry : consent_helpers_) { + entry.second->RemoveObserver(this); + } +} + +bool UkmConsentStateObserver::ProfileState::AllowsUkm() const { + return anonymized_data_collection_enabled; +} + +// static +UkmConsentStateObserver::ProfileState UkmConsentStateObserver::GetProfileState( + syncer::SyncService* sync_service, + UrlKeyedDataCollectionConsentHelper* consent_helper) { + DCHECK(sync_service); + DCHECK(consent_helper); + ProfileState state; + state.anonymized_data_collection_enabled = consent_helper->IsEnabled(); + state.extensions_enabled = + sync_service->GetPreferredDataTypes().Has(syncer::EXTENSIONS) && + sync_service->IsSyncFeatureEnabled(); + return state; +} + +void UkmConsentStateObserver::StartObserving(syncer::SyncService* sync_service, + PrefService* prefs) { + std::unique_ptr<UrlKeyedDataCollectionConsentHelper> consent_helper = + UrlKeyedDataCollectionConsentHelper:: + NewAnonymizedDataCollectionConsentHelper(prefs, sync_service); + + ProfileState state = GetProfileState(sync_service, consent_helper.get()); + previous_states_[sync_service] = state; + + consent_helper->AddObserver(this); + consent_helpers_[sync_service] = std::move(consent_helper); + sync_observer_.Add(sync_service); + UpdateUkmAllowedForAllProfiles(false); +} + +void UkmConsentStateObserver::UpdateUkmAllowedForAllProfiles(bool must_purge) { + bool all_profile_states_allow_ukm = CheckPreviousStatesAllowUkm(); + bool all_profile_states_allow_extension_ukm = + all_profile_states_allow_ukm && CheckPreviousStatesAllowExtensionUkm(); + + UMA_HISTOGRAM_BOOLEAN("UKM.ConsentObserver.AllowedForAllProfiles", + all_profile_states_allow_ukm); + + // Any change in profile states needs to call OnUkmAllowedStateChanged so that + // the new settings take effect. + if (must_purge || + (all_profile_states_allow_ukm != ukm_allowed_for_all_profiles_) || + (all_profile_states_allow_extension_ukm != + ukm_allowed_with_extensions_for_all_profiles_)) { + ukm_allowed_for_all_profiles_ = all_profile_states_allow_ukm; + ukm_allowed_with_extensions_for_all_profiles_ = + all_profile_states_allow_extension_ukm; + OnUkmAllowedStateChanged(must_purge); + } +} + +bool UkmConsentStateObserver::CheckPreviousStatesAllowUkm() { + if (previous_states_.empty()) + return false; + for (const auto& kv : previous_states_) { + const ProfileState& state = kv.second; + if (!state.AllowsUkm()) + return false; + } + + return true; +} + +bool UkmConsentStateObserver::CheckPreviousStatesAllowExtensionUkm() { + if (previous_states_.empty()) + return false; + for (const auto& kv : previous_states_) { + const ProfileState& state = kv.second; + if (!state.extensions_enabled) + return false; + } + return true; +} + +void UkmConsentStateObserver::OnStateChanged(syncer::SyncService* sync) { + UrlKeyedDataCollectionConsentHelper* consent_helper = nullptr; + auto found = consent_helpers_.find(sync); + if (found != consent_helpers_.end()) + consent_helper = found->second.get(); + UpdateProfileState(sync, consent_helper); +} + +void UkmConsentStateObserver::OnUrlKeyedDataCollectionConsentStateChanged( + unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) { + DCHECK(consent_helper); + syncer::SyncService* sync_service = nullptr; + for (const auto& entry : consent_helpers_) { + if (consent_helper == entry.second.get()) { + sync_service = entry.first; + break; + } + } + DCHECK(sync_service); + UpdateProfileState(sync_service, consent_helper); +} + +void UkmConsentStateObserver::UpdateProfileState( + syncer::SyncService* sync, + UrlKeyedDataCollectionConsentHelper* consent_helper) { + DCHECK(base::Contains(previous_states_, sync)); + const ProfileState& previous_state = previous_states_[sync]; + DCHECK(consent_helper); + ProfileState state = GetProfileState(sync, consent_helper); + + // Trigger a purge if the current state no longer allows UKM. + bool must_purge = previous_state.AllowsUkm() && !state.AllowsUkm(); + + UMA_HISTOGRAM_BOOLEAN("UKM.ConsentObserver.Purge", must_purge); + + previous_states_[sync] = state; + UpdateUkmAllowedForAllProfiles(must_purge); +} + +void UkmConsentStateObserver::OnSyncShutdown(syncer::SyncService* sync) { + DCHECK(base::Contains(previous_states_, sync)); + auto found = consent_helpers_.find(sync); + if (found != consent_helpers_.end()) { + found->second->RemoveObserver(this); + consent_helpers_.erase(found); + } + sync_observer_.Remove(sync); + previous_states_.erase(sync); + UpdateUkmAllowedForAllProfiles(/*must_purge=*/false); +} + +bool UkmConsentStateObserver::IsUkmAllowedForAllProfiles() { + return ukm_allowed_for_all_profiles_; +} + +bool UkmConsentStateObserver::IsUkmAllowedWithExtensionsForAllProfiles() { + return ukm_allowed_with_extensions_for_all_profiles_; +} + +} // namespace ukm
diff --git a/components/ukm/observers/ukm_consent_state_observer.h b/components/ukm/observers/ukm_consent_state_observer.h new file mode 100644 index 0000000..4d214765 --- /dev/null +++ b/components/ukm/observers/ukm_consent_state_observer.h
@@ -0,0 +1,134 @@ +// 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 COMPONENTS_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_ +#define COMPONENTS_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_ + +#include <map> + +#include "base/scoped_observer.h" +#include "components/sync/driver/sync_service.h" +#include "components/sync/driver/sync_service_observer.h" +#include "components/unified_consent/url_keyed_data_collection_consent_helper.h" + +class PrefService; + +namespace ukm { + +// Observer that monitors whether UKM is allowed for all profiles. +// +// For one profile, UKM is allowed iff URL-keyed anonymized data collection is +// enabled. +class UkmConsentStateObserver + : public syncer::SyncServiceObserver, + public unified_consent::UrlKeyedDataCollectionConsentHelper::Observer { + public: + UkmConsentStateObserver(); + ~UkmConsentStateObserver() override; + + // Starts observing whether UKM is allowed for a profile. + // |pref_service| is the pref service of a profile. + void StartObserving(syncer::SyncService* sync_service, + PrefService* pref_service); + + // Returns true iff all UKM is allowed for all profile states. This means that + // URL-keyed anonymized data collection is enabled for all profiles. + virtual bool IsUkmAllowedForAllProfiles(); + + // Returns true iff sync is in a state that allows UKM to capture extensions. + // This means that all profiles have EXTENSIONS data type enabled for syncing. + virtual bool IsUkmAllowedWithExtensionsForAllProfiles(); + + protected: + // Called after UKM consent state changed. + // If |must_purge| is true, the UKM is not allowed for some profile, and local + // data must be purged. + virtual void OnUkmAllowedStateChanged(bool must_purge) = 0; + + private: + // syncer::SyncServiceObserver: + void OnStateChanged(syncer::SyncService* sync) override; + void OnSyncShutdown(syncer::SyncService* sync) override; + + // unified_consent::UrlKeyedDataCollectionConsentHelper::Observer: + void OnUrlKeyedDataCollectionConsentStateChanged( + unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) + override; + + // Recomputes |ukm_allowed_for_all_profiles_| and + // |ukm_allowed_with_extensions_for_all_profiles_| from |previous_states_|; + void UpdateUkmAllowedForAllProfiles(bool must_purge); + + // Returns true iff all profile states in |previous_states_| allow UKM. + // If there are no profiles being observed, this returns false. + bool CheckPreviousStatesAllowUkm(); + + // Returns true iff all profile states in |previous_states_| allow extension + // UKM. If there are no profiles are being observed, this returns false. + bool CheckPreviousStatesAllowExtensionUkm(); + + // Tracks observed sync services, for cleanup. + ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver> + sync_observer_; + + // State data about profiles that we need to remember. + struct ProfileState { + // Returns true if this state allows UKM (i.e. URL-keyed anonymized + // data collection is enabled). + bool AllowsUkm() const; + + // Returns true if |AllowsUkm| and if sync extensions are enabled. + bool AllowsUkmWithExtension() const; + + // Whether anonymized data collection is enabled. + bool anonymized_data_collection_enabled = false; + + // If the user has extension sync enabled. + bool extensions_enabled = false; + }; + + // Updates the UKM enabled state for a profile and then triggers an update of + // the state for all profiles. + // |sync| and |consent_helper| must not be null. + void UpdateProfileState( + syncer::SyncService* sync, + unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper); + + // Gets the current state of a profile. + // |sync| and |consent_helper| must not be null. + static ProfileState GetProfileState( + syncer::SyncService* sync, + unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper); + + // The state of the profile being observed. + // + // Note: UKM consent does not rely on sync but there must be exactly one + // sync service per profile, so it is safe to key the profile states by the + // sync service. + std::map<syncer::SyncService*, ProfileState> previous_states_; + + // The list of URL-keyed anonymized data collection consent helpers. + // + // Note: UrlKeyedDataCollectionConsentHelper does not rely on sync but there + // must be exactly one per Chromium profile. As there is a single sync service + // per profile, it is safe to key them by sync service instead of introducing + // an additional map. + std::map< + syncer::SyncService*, + std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>> + consent_helpers_; + + // Tracks if UKM is allowed on all profiles after the last state change. + bool ukm_allowed_for_all_profiles_ = false; + + // Tracks if extension sync was enabled on all profiles after the last state + // change. + bool ukm_allowed_with_extensions_for_all_profiles_ = false; + + DISALLOW_COPY_AND_ASSIGN(UkmConsentStateObserver); +}; + +} // namespace ukm + +#endif // COMPONENTS_UKM_OBSERVERS_UKM_CONSENT_STATE_OBSERVER_H_
diff --git a/components/ukm/observers/sync_disable_observer_unittest.cc b/components/ukm/observers/ukm_consent_state_observer_unittest.cc similarity index 74% rename from components/ukm/observers/sync_disable_observer_unittest.cc rename to components/ukm/observers/ukm_consent_state_observer_unittest.cc index a387cf4..d9faae1e 100644 --- a/components/ukm/observers/sync_disable_observer_unittest.cc +++ b/components/ukm/observers/ukm_consent_state_observer_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/ukm/observers/sync_disable_observer.h" +#include "components/ukm/observers/ukm_consent_state_observer.h" #include "base/observer_list.h" #include "components/sync/driver/sync_token_status.h" @@ -80,10 +80,10 @@ DISALLOW_COPY_AND_ASSIGN(MockSyncService); }; -class TestSyncDisableObserver : public SyncDisableObserver { +class TestUkmConsentStateObserver : public UkmConsentStateObserver { public: - TestSyncDisableObserver() : purged_(false), notified_(false) {} - ~TestSyncDisableObserver() override {} + TestUkmConsentStateObserver() : purged_(false), notified_(false) {} + ~TestUkmConsentStateObserver() override {} bool ResetPurged() { bool was_purged = purged_; @@ -98,19 +98,19 @@ } private: - // SyncDisableObserver: - void OnSyncPrefsChanged(bool must_purge) override { + // UkmConsentStateObserver: + void OnUkmAllowedStateChanged(bool must_purge) override { notified_ = true; purged_ = purged_ || must_purge; } bool purged_; bool notified_; - DISALLOW_COPY_AND_ASSIGN(TestSyncDisableObserver); + DISALLOW_COPY_AND_ASSIGN(TestUkmConsentStateObserver); }; -class SyncDisableObserverTest : public testing::Test { +class UkmConsentStateObserverTest : public testing::Test { public: - SyncDisableObserverTest() {} + UkmConsentStateObserverTest() {} void RegisterUrlKeyedAnonymizedDataCollectionPref( sync_preferences::TestingPrefServiceSyncable& prefs) { unified_consent::UnifiedConsentService::RegisterPrefs(prefs.registry()); @@ -124,114 +124,114 @@ } private: - DISALLOW_COPY_AND_ASSIGN(SyncDisableObserverTest); + DISALLOW_COPY_AND_ASSIGN(UkmConsentStateObserverTest); }; } // namespace -TEST_F(SyncDisableObserverTest, NoProfiles) { - TestSyncDisableObserver observer; - EXPECT_FALSE(observer.SyncStateAllowsUkm()); +TEST_F(UkmConsentStateObserverTest, NoProfiles) { + TestUkmConsentStateObserver observer; + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, NotActive) { +TEST_F(UkmConsentStateObserverTest, NotActive) { MockSyncService sync; sync.SetStatus(false, true, false); sync_preferences::TestingPrefServiceSyncable prefs; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs); - TestSyncDisableObserver observer; - observer.ObserveServiceForSyncDisables(&sync, &prefs); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + TestUkmConsentStateObserver observer; + observer.StartObserving(&sync, &prefs); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, OneEnabled) { +TEST_F(UkmConsentStateObserverTest, OneEnabled) { MockSyncService sync; sync_preferences::TestingPrefServiceSyncable prefs; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs); SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true); - TestSyncDisableObserver observer; - observer.ObserveServiceForSyncDisables(&sync, &prefs); - EXPECT_TRUE(observer.SyncStateAllowsUkm()); + TestUkmConsentStateObserver observer; + observer.StartObserving(&sync, &prefs); + EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles()); EXPECT_TRUE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, MixedProfiles) { +TEST_F(UkmConsentStateObserverTest, MixedProfiles) { sync_preferences::TestingPrefServiceSyncable prefs1; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs1); sync_preferences::TestingPrefServiceSyncable prefs2; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs2); - TestSyncDisableObserver observer; + TestUkmConsentStateObserver observer; MockSyncService sync1; SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs1, false); - observer.ObserveServiceForSyncDisables(&sync1, &prefs1); + observer.StartObserving(&sync1, &prefs1); MockSyncService sync2; SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs2, true); - observer.ObserveServiceForSyncDisables(&sync2, &prefs2); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + observer.StartObserving(&sync2, &prefs2); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, TwoEnabled) { +TEST_F(UkmConsentStateObserverTest, TwoEnabled) { sync_preferences::TestingPrefServiceSyncable prefs1; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs1); sync_preferences::TestingPrefServiceSyncable prefs2; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs2); - TestSyncDisableObserver observer; + TestUkmConsentStateObserver observer; MockSyncService sync1; SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs1, true); - observer.ObserveServiceForSyncDisables(&sync1, &prefs1); + observer.StartObserving(&sync1, &prefs1); EXPECT_TRUE(observer.ResetNotified()); MockSyncService sync2; SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs2, true); - observer.ObserveServiceForSyncDisables(&sync2, &prefs2); - EXPECT_TRUE(observer.SyncStateAllowsUkm()); + observer.StartObserving(&sync2, &prefs2); + EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, OneAddRemove) { +TEST_F(UkmConsentStateObserverTest, OneAddRemove) { sync_preferences::TestingPrefServiceSyncable prefs; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs); - TestSyncDisableObserver observer; + TestUkmConsentStateObserver observer; MockSyncService sync; - observer.ObserveServiceForSyncDisables(&sync, &prefs); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + observer.StartObserving(&sync, &prefs); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true); - EXPECT_TRUE(observer.SyncStateAllowsUkm()); + EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles()); EXPECT_TRUE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); sync.Shutdown(); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_TRUE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); } -TEST_F(SyncDisableObserverTest, PurgeOnDisable) { +TEST_F(UkmConsentStateObserverTest, PurgeOnDisable) { sync_preferences::TestingPrefServiceSyncable prefs; RegisterUrlKeyedAnonymizedDataCollectionPref(prefs); - TestSyncDisableObserver observer; + TestUkmConsentStateObserver observer; MockSyncService sync; SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true); - observer.ObserveServiceForSyncDisables(&sync, &prefs); - EXPECT_TRUE(observer.SyncStateAllowsUkm()); + observer.StartObserving(&sync, &prefs); + EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles()); EXPECT_TRUE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, false); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_TRUE(observer.ResetNotified()); EXPECT_TRUE(observer.ResetPurged()); sync.Shutdown(); - EXPECT_FALSE(observer.SyncStateAllowsUkm()); + EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles()); EXPECT_FALSE(observer.ResetNotified()); EXPECT_FALSE(observer.ResetPurged()); }
diff --git a/components/ukm/ukm_service.h b/components/ukm/ukm_service.h index 0e28dd0..08fea5f 100644 --- a/components/ukm/ukm_service.h +++ b/components/ukm/ukm_service.h
@@ -48,7 +48,7 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. This maps to the enum UkmResetReason. enum class ResetReason { - kOnSyncPrefsChanged = 0, + kOnUkmAllowedStateChanged = 0, kUpdatePermissions = 1, kMaxValue = kUpdatePermissions, };
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index c6fc9606..d110134 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -358,6 +358,54 @@ } } +// Porter-Duff blend mode utility functions, where the final color is +// represented as a weighted sum of the incoming src and existing dst color. +// See [https://skia.org/user/api/SkBlendMode_Reference] + +bool IsPorterDuffBlendMode(SkBlendMode blendMode) { + return blendMode <= SkBlendMode::kLastCoeffMode; +} + +// Returns true if drawing transparent black with |blendMode| would modify the +// destination buffer. If false is returned, the draw would have no discernible +// effect on the pixel color so the entire draw can be skipped. +bool TransparentBlackAffectsOutput(SkBlendMode blendMode) { + SkBlendModeCoeff src, dst; + if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) { + // An advanced blend mode that can't be represented as coefficients, so + // assume it modifies the output. + return true; + } + // True when the dst coefficient is not equal to 1 (when src = (0,0,0,0)) + return dst != SkBlendModeCoeff::kOne && dst != SkBlendModeCoeff::kISA && + dst != SkBlendModeCoeff::kISC; +} + +// Returns true if src content drawn with |blendMode| into a RenderPass would +// produce the exact same image as the original src content. +bool RenderPassPreservesContent(SkBlendMode blendMode) { + SkBlendModeCoeff src, dst; + if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) { + return false; + } + // True when src coefficient is equal to 1 (when dst = (0,0,0,0)) + return src == SkBlendModeCoeff::kOne || src == SkBlendModeCoeff::kIDA || + src == SkBlendModeCoeff::kIDC; +} + +// Returns true if src content draw with |blendMode| into an empty RenderPass +// would produce a transparent black image. +bool RenderPassRemainsTransparent(SkBlendMode blendMode) { + SkBlendModeCoeff src, dst; + if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) { + return false; + } + + // True when src coefficient is equal to 0 (when dst = (0,0,0,0)) + return src == SkBlendModeCoeff::kZero || src == SkBlendModeCoeff::kDA || + src == SkBlendModeCoeff::kDC; +} + } // namespace // chrome style prevents this from going in skia_renderer.h, but since it @@ -485,6 +533,21 @@ } } +enum class SkiaRenderer::BypassMode { + // The RenderPass's contents' blendmode would have made a transparent black + // image + // and the RenderPass's own blend mode has no effect on transparent black. + kSkip, + // The renderPass's contents' creates a transparent image, but the + // RenderPass's + // own blend mode must still process the transparent pixels (e.g. certain + // filters + // affect transparent black). + kDrawTransparentQuad, + // Can draw the bypass quad with the modified parameters + kDrawBypassQuad +}; + // Scoped helper class for building SkImage from resource id. class SkiaRenderer::ScopedSkImageBuilder { public: @@ -1190,7 +1253,7 @@ const gfx::Transform& target_to_device, const gfx::Rect* scissor_rect, const DrawQuad* quad, - const gfx::QuadF* draw_region) { + const gfx::QuadF* draw_region) const { DrawQuadParams params( target_to_device * quad->shared_quad_state->quad_to_target_transform, gfx::RectF(quad->visible_rect), SkCanvas::kNone_QuadAAFlags, @@ -1300,13 +1363,17 @@ if (!quad->shared_quad_state->quad_to_target_transform.IsInvertible()) return nullptr; - // TODO(chrishtr): support could be added for opacity, but care needs - // to be taken to make sure it is correct w.r.t. non-commutative filters etc. - if (quad->shared_quad_state->opacity != 1.0f) + // A renderpass normally draws its content into a transparent destination, + // using the quad's blend mode, then that result is later drawn into the + // real dst with the RP's blend mode. In order to bypass the RP and draw + // correctly, CalculateBypassParams must be able to reason about the quad's + // blend mode. + if (!IsPorterDuffBlendMode(quad->shared_quad_state->blend_mode)) return nullptr; - - if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver) - return nullptr; + // All Porter-Duff blending with transparent black should fall into one of + // these two categories: + DCHECK(RenderPassPreservesContent(quad->shared_quad_state->blend_mode) || + RenderPassRemainsTransparent(quad->shared_quad_state->blend_mode)); // The content must not have any rrect clipping, since skia_renderer applies // the rrect in device space, and in this case, the bypass quad's device space @@ -1322,9 +1389,27 @@ return quad; } -void SkiaRenderer::CalculateBypassParams(const DrawQuad* bypass_quad, - DrawRPDQParams* rpdq_params, - DrawQuadParams* params) { +SkiaRenderer::BypassMode SkiaRenderer::CalculateBypassParams( + const DrawQuad* bypass_quad, + DrawRPDQParams* rpdq_params, + DrawQuadParams* params) const { + // Depending on bypass_quad's blend mode, its content may be irrelevant + if (RenderPassRemainsTransparent( + bypass_quad->shared_quad_state->blend_mode)) { + // NOTE: this uses the pass's blend mode since this refers to the final draw + // of the render pass itself + if (TransparentBlackAffectsOutput(params->blend_mode)) { + return BypassMode::kDrawTransparentQuad; + } else { + return BypassMode::kSkip; + } + } + // If we made it here, the bypass blend mode would have just preserved the + // bypass quad's content, so we can draw it directly using the render pass's + // blend mode instead. + DCHECK( + RenderPassPreservesContent(bypass_quad->shared_quad_state->blend_mode)); + // The bypass quad will be drawn directly, so update |params| and // |rpdq_params| to reflect the change of coordinate system and merge settings // between the inner and outer quads. @@ -1367,6 +1452,11 @@ // is preserved). params->aa_flags &= bypass_params.aa_flags; + // Blending will use the top-level RPDQ blend mode, but factor in the + // content's opacity as well, since that would have normally been baked into + // the RP's buffer. + params->opacity *= bypass_params.opacity; + // Take the highest quality filter, since this single draw will reflect the // filtering decisions made both when drawing into the RP and when drawing the // RP results itself. @@ -1376,11 +1466,13 @@ // Rounded corner bounds are in device space, which gets tricky when bypassing // the device that the RP would have represented DCHECK(!bypass_params.rounded_corner_bounds.has_value()); + return BypassMode::kDrawBypassQuad; } -SkCanvas::ImageSetEntry SkiaRenderer::MakeEntry(const SkImage* image, - int matrix_index, - const DrawQuadParams& params) { +SkCanvas::ImageSetEntry SkiaRenderer::MakeEntry( + const SkImage* image, + int matrix_index, + const DrawQuadParams& params) const { return SkCanvas::ImageSetEntry( {sk_ref_sp(image), gfx::RectFToSkRect(params.vis_tex_coords), gfx::RectFToSkRect(params.visible_rect), matrix_index, params.opacity, @@ -1390,7 +1482,7 @@ SkCanvas::SrcRectConstraint SkiaRenderer::ResolveTextureConstraints( const SkImage* image, const gfx::RectF& valid_texel_bounds, - DrawQuadParams* params) { + DrawQuadParams* params) const { if (params->aa_flags == SkCanvas::kNone_QuadAAFlags && params->filter_quality == kNone_SkFilterQuality) { // Non-AA and no bilinear filtering so rendering won't filter outside the @@ -1432,7 +1524,7 @@ bool SkiaRenderer::MustFlushBatchedQuads(const DrawQuad* new_quad, const DrawRPDQParams* rpdq_params, - const DrawQuadParams& params) { + const DrawQuadParams& params) const { if (batched_quads_.empty()) return false; @@ -2162,8 +2254,13 @@ auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id); // When Render Pass has a single quad inside we would draw that directly. if (bypass != render_pass_bypass_quads_.end()) { - CalculateBypassParams(bypass->second, &rpdq_params, params); - DrawQuadInternal(bypass->second, &rpdq_params, params); + BypassMode mode = + CalculateBypassParams(bypass->second, &rpdq_params, params); + if (mode == BypassMode::kDrawTransparentQuad) { + DrawColoredQuad(SK_ColorTRANSPARENT, &rpdq_params, params); + } else if (mode == BypassMode::kDrawBypassQuad) { + DrawQuadInternal(bypass->second, &rpdq_params, params); + } // else mode == kSkip return; }
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index c4fa782..0379ebd 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -90,6 +90,7 @@ void GenerateMipmap() override; private: + enum class BypassMode; struct DrawQuadParams; struct DrawRPDQParams; class ScopedSkImageBuilder; @@ -126,28 +127,28 @@ DrawQuadParams CalculateDrawQuadParams(const gfx::Transform& target_to_device, const gfx::Rect* scissor_rect, const DrawQuad* quad, - const gfx::QuadF* draw_region); + const gfx::QuadF* draw_region) const; DrawRPDQParams CalculateRPDQParams(const RenderPassDrawQuad* quad, DrawQuadParams* params); // Modifies |params| and |rpdq_params| to apply correctly when drawing the // RenderPass directly via |bypass_quad|. - void CalculateBypassParams(const DrawQuad* bypass_quad, - DrawRPDQParams* rpdq_params, - DrawQuadParams* params); + BypassMode CalculateBypassParams(const DrawQuad* bypass_quad, + DrawRPDQParams* rpdq_params, + DrawQuadParams* params) const; SkCanvas::ImageSetEntry MakeEntry(const SkImage* image, int matrix_index, - const DrawQuadParams& params); + const DrawQuadParams& params) const; // Returns overall constraint to pass to Skia, and modifies |params| to // emulate content area clamping different from the provided texture coords. SkCanvas::SrcRectConstraint ResolveTextureConstraints( const SkImage* image, const gfx::RectF& valid_texel_bounds, - DrawQuadParams* params); + DrawQuadParams* params) const; bool MustFlushBatchedQuads(const DrawQuad* new_quad, const DrawRPDQParams* rpdq_params, - const DrawQuadParams& params); + const DrawQuadParams& params) const; void AddQuadToBatch(const SkImage* image, const gfx::RectF& valid_texel_bounds, DrawQuadParams* params);
diff --git a/content/app/OWNERS b/content/app/OWNERS index 27c4a80..60a5c1d 100644 --- a/content/app/OWNERS +++ b/content/app/OWNERS
@@ -1,3 +1,2 @@ -jcivelli@chromium.org rockot@google.com per-file sandbox_helper_win.cc=file://sandbox/win/OWNERS
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index ee90a2d..342808a9 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1016,6 +1016,8 @@ "indexed_db/indexed_db_internals_ui.h", "indexed_db/indexed_db_leveldb_coding.cc", "indexed_db/indexed_db_leveldb_coding.h", + "indexed_db/indexed_db_leveldb_env.cc", + "indexed_db/indexed_db_leveldb_env.h", "indexed_db/indexed_db_leveldb_operations.cc", "indexed_db/indexed_db_leveldb_operations.h", "indexed_db/indexed_db_metadata_coding.cc", @@ -1044,8 +1046,6 @@ "indexed_db/indexed_db_transaction.h", "indexed_db/indexed_db_value.cc", "indexed_db/indexed_db_value.h", - "indexed_db/leveldb/leveldb_env.cc", - "indexed_db/leveldb/leveldb_env.h", "indexed_db/leveldb/leveldb_write_batch.cc", "indexed_db/leveldb/leveldb_write_batch.h", "indexed_db/leveldb/transactional_leveldb_database.cc",
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 56dafc945..472f115 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1886,8 +1886,9 @@ const base::Optional<std::string>& error_page_content, bool collapse_frame) { DCHECK(state_ == WILL_START_NAVIGATION || state_ == WILL_START_REQUEST || - state_ == WILL_REDIRECT_REQUEST || state_ == RESPONSE_STARTED || - state_ == CANCELING); + state_ == WILL_REDIRECT_REQUEST || state_ == WILL_PROCESS_RESPONSE || + state_ == RESPONSE_STARTED || state_ == CANCELING || + state_ == WILL_FAIL_REQUEST); DCHECK(!(status.error_code == net::ERR_ABORTED && error_page_content.has_value())); @@ -2974,7 +2975,7 @@ void NavigationRequest::OnWillFailRequestProcessed( NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(WILL_FAIL_REQUEST, handle_state_); + DCHECK_EQ(WILL_FAIL_REQUEST, state_); DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); DCHECK(processing_navigation_throttle_); processing_navigation_throttle_ = false; @@ -2989,7 +2990,7 @@ void NavigationRequest::OnWillProcessResponseProcessed( NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(WILL_PROCESS_RESPONSE, handle_state_); + DCHECK_EQ(WILL_PROCESS_RESPONSE, state_); DCHECK_NE(NavigationThrottle::BLOCK_REQUEST, result.action()); DCHECK_NE(NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, result.action()); DCHECK(processing_navigation_throttle_); @@ -3125,7 +3126,7 @@ "WillFailRequest"); complete_callback_ = std::move(callback); - handle_state_ = WILL_FAIL_REQUEST; + state_ = WILL_FAIL_REQUEST; processing_navigation_throttle_ = true; // Notify each throttle of the request. @@ -3141,7 +3142,7 @@ "WillProcessResponse"); complete_callback_ = std::move(callback); - handle_state_ = WILL_PROCESS_RESPONSE; + state_ = WILL_PROCESS_RESPONSE; processing_navigation_throttle_ = true; // Notify each throttle of the response. @@ -3312,6 +3313,7 @@ std::string("RTCN") + (render_frame_host_->GetProcess()->IsReady() ? "1" : "0")); handle_state_ = READY_TO_COMMIT; + state_ = RESPONSE_STARTED; ready_to_commit_time_ = base::TimeTicks::Now(); RestartCommitTimeout(); @@ -3547,7 +3549,7 @@ } net::IPEndPoint NavigationRequest::GetSocketAddress() { - DCHECK_GE(handle_state_, WILL_PROCESS_RESPONSE); + DCHECK_GE(state_, WILL_PROCESS_RESPONSE); return response() ? response()->head.remote_endpoint : net::IPEndPoint(); } @@ -3687,11 +3689,11 @@ // Only allow the RenderFrameHost to be retrieved once it has been set for // this navigation. This will happens either at WillProcessResponse time for // regular navigations or at WillFailRequest time for error pages. - CHECK_GE(handle_state_, WILL_FAIL_REQUEST) + CHECK_GE(state_, WILL_PROCESS_RESPONSE) << "This accessor should only be called after a RenderFrameHost has " "been picked for this navigation."; - static_assert(WILL_FAIL_REQUEST < WILL_PROCESS_RESPONSE, - "WillFailRequest state should come before WillProcessResponse"); + static_assert(WILL_FAIL_REQUEST > WILL_PROCESS_RESPONSE, + "WillFailRequest state should come after WillProcessResponse"); return render_frame_host_; } @@ -3772,7 +3774,7 @@ } const GlobalRequestID& NavigationRequest::GetGlobalRequestID() { - DCHECK_GE(handle_state_, WILL_PROCESS_RESPONSE); + DCHECK_GE(state_, WILL_PROCESS_RESPONSE); return request_id_; }
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 341fdf2..95afdc1 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -105,6 +105,11 @@ // asynchronous. WILL_REDIRECT_REQUEST, + // The response is being processed. Wait for the NavigationThrottles to + // finish running the WillProcessResponse event. This is potentially + // asynchronous. + WILL_PROCESS_RESPONSE, + // The response started on the IO thread and is ready to be committed. This // is one of the two final states for the request. RESPONSE_STARTED, @@ -112,6 +117,10 @@ // The request is being canceled. CANCELING, + // The request is failing. Wait for the NavigationThrottles to finish + // running the WillFailRequest event. This is potentially asynchronous. + WILL_FAIL_REQUEST, + // The request failed on the IO thread and an error page should be // displayed. This is one of the two final states for the request. FAILED, @@ -125,8 +134,6 @@ // the duplicates. enum NavigationHandleState { NOT_CREATED = 0, - WILL_FAIL_REQUEST, - WILL_PROCESS_RESPONSE, READY_TO_COMMIT, DID_COMMIT, DID_COMMIT_ERROR_PAGE,
diff --git a/content/browser/frame_host/navigation_request_unittest.cc b/content/browser/frame_host/navigation_request_unittest.cc index 249ce12..72629b4 100644 --- a/content/browser/frame_host/navigation_request_unittest.cc +++ b/content/browser/frame_host/navigation_request_unittest.cc
@@ -362,7 +362,7 @@ // Simulate WillFailRequest. The request should be deferred. The callback // should not have been called. SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID); - EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state()); + EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, request_state()); EXPECT_FALSE(was_callback_called()); EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0)); @@ -411,7 +411,7 @@ // Simulate WillFailRequest. The request should be deferred. The callback // should not have been called. SimulateWillFailRequest(net::ERR_CERT_DATE_INVALID); - EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, state()); + EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, request_state()); EXPECT_FALSE(was_callback_called()); EXPECT_TRUE(call_counts_match(test_throttle, 1, 0, 1, 0)); @@ -501,9 +501,9 @@ navigation->SetAutoAdvance(false); navigation->Start(); navigation->Fail(net::ERR_CERT_DATE_INVALID); - EXPECT_EQ(NavigationRequest::WILL_FAIL_REQUEST, - NavigationRequest::From(navigation->GetNavigationHandle()) - ->handle_state()); + EXPECT_EQ( + NavigationRequest::WILL_FAIL_REQUEST, + NavigationRequest::From(navigation->GetNavigationHandle())->state()); EXPECT_TRUE(navigation->GetNavigationHandle()->GetRenderFrameHost()); NavigationRequest::From(navigation->GetNavigationHandle()) ->CallResumeForTesting();
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index f81a253..7d7e8fd 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -35,12 +35,12 @@ #include "content/browser/indexed_db/indexed_db_database_error.h" #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/indexed_db_metadata_coding.h" #include "content/browser/indexed_db/indexed_db_reporting.h" #include "content/browser/indexed_db/indexed_db_tracing.h" #include "content/browser/indexed_db/indexed_db_value.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h"
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index a32930e..f0a11b9 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -31,9 +31,9 @@ #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_factory_impl.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_origin_state.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h" #include "content/browser/web_contents/web_contents_impl.h"
diff --git a/content/browser/indexed_db/indexed_db_class_factory.cc b/content/browser/indexed_db/indexed_db_class_factory.cc index 6e8f93dc..efb89f4 100644 --- a/content/browser/indexed_db/indexed_db_class_factory.cc +++ b/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -11,10 +11,10 @@ #include "components/services/storage/indexed_db/leveldb/leveldb_factory.h" #include "components/services/storage/indexed_db/scopes/leveldb_scope.h" #include "content/browser/indexed_db/indexed_db_factory.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" #include "content/browser/indexed_db/indexed_db_metadata_coding.h" #include "content/browser/indexed_db/indexed_db_transaction.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h" #include "third_party/leveldatabase/leveldb_chrome.h" @@ -61,7 +61,7 @@ // For info about the troubles we've run into with this parameter, see: // https://crbug.com/227313#c11 options.max_open_files = 80; - options.env = LevelDBEnv::Get(); + options.env = IndexedDBLevelDBEnv::Get(); options.block_cache = leveldb_chrome::GetSharedWebBlockCache(); return options; }
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc index 62ea1dad4..d6a5f08a5 100644 --- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc +++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -18,7 +18,7 @@ #include "components/services/storage/indexed_db/scopes/leveldb_scopes.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index dd4693b..c8b8aa0 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -23,8 +23,8 @@ #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_database_callbacks.h" #include "content/browser/indexed_db/indexed_db_factory.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_pending_connection.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h" #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h" #include "content/public/browser/browser_task_traits.h"
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc index 8ad5910..85e8234 100644 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -27,10 +27,10 @@ #include "content/browser/indexed_db/indexed_db_data_format_version.h" #include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h" #include "content/browser/indexed_db/indexed_db_factory_impl.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_origin_state.h" #include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h" #include "content/browser/indexed_db/indexed_db_transaction.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc index 4f9f98d5e..7b9da23 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -9,7 +9,7 @@ #include "base/files/file_path.h" #include "base/no_destructor.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h"
diff --git a/content/browser/indexed_db/indexed_db_leveldb_env.cc b/content/browser/indexed_db/indexed_db_leveldb_env.cc new file mode 100644 index 0000000..bf473f56 --- /dev/null +++ b/content/browser/indexed_db/indexed_db_leveldb_env.cc
@@ -0,0 +1,16 @@ +// 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 "content/browser/indexed_db/indexed_db_leveldb_env.h" + +namespace content { + +IndexedDBLevelDBEnv::IndexedDBLevelDBEnv() : ChromiumEnv("LevelDBEnv.IDB") {} + +IndexedDBLevelDBEnv* IndexedDBLevelDBEnv::Get() { + static base::NoDestructor<IndexedDBLevelDBEnv> g_leveldb_env; + return g_leveldb_env.get(); +} + +} // namespace content
diff --git a/content/browser/indexed_db/indexed_db_leveldb_env.h b/content/browser/indexed_db/indexed_db_leveldb_env.h new file mode 100644 index 0000000..4549886c --- /dev/null +++ b/content/browser/indexed_db/indexed_db_leveldb_env.h
@@ -0,0 +1,29 @@ +// 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 CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_ +#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_ + +#include <memory> +#include <tuple> + +#include "base/no_destructor.h" +#include "content/common/content_export.h" +#include "third_party/leveldatabase/env_chromium.h" + +namespace content { + +// The leveldb::Env used by the Indexed DB backend. +class IndexedDBLevelDBEnv : public leveldb_env::ChromiumEnv { + public: + CONTENT_EXPORT static IndexedDBLevelDBEnv* Get(); + + private: + friend class base::NoDestructor<IndexedDBLevelDBEnv>; + IndexedDBLevelDBEnv(); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_LEVELDB_ENV_H_
diff --git a/content/browser/indexed_db/leveldb/leveldb_env_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc similarity index 83% rename from content/browser/indexed_db/leveldb/leveldb_env_unittest.cc rename to content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc index b39d803..30a9caf0 100644 --- a/content/browser/indexed_db/leveldb/leveldb_env_unittest.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_env_unittest.cc
@@ -2,14 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/indexed_db/leveldb/leveldb_env.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include <utility> -#include "base/files/file.h" #include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/optional.h" #include "components/services/storage/indexed_db/leveldb/leveldb_factory.h" #include "components/services/storage/indexed_db/leveldb/leveldb_state.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,7 +18,6 @@ namespace indexed_db { namespace { leveldb_env::Options GetLevelDBOptions() { - static base::NoDestructor<leveldb_env::ChromiumEnv> test_env; static const leveldb::FilterPolicy* kFilterPolicy = leveldb::NewBloomFilterPolicy(10); leveldb_env::Options options; @@ -29,11 +25,11 @@ options.paranoid_checks = true; options.filter_policy = kFilterPolicy; options.compression = leveldb::kSnappyCompression; - options.env = test_env.get(); + options.env = IndexedDBLevelDBEnv::Get(); return options; } -TEST(LevelDBEnvTest, TestInMemory) { +TEST(IndexedDBLevelDBEnvTest, TestInMemory) { DefaultLevelDBFactory default_factory(GetLevelDBOptions(), "test-in-memory-db"); scoped_refptr<LevelDBState> state;
diff --git a/content/browser/indexed_db/indexed_db_leveldb_operations.cc b/content/browser/indexed_db/indexed_db_leveldb_operations.cc index 8152366..f5729ee 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_operations.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_operations.cc
@@ -14,9 +14,9 @@ #include "content/browser/indexed_db/indexed_db_data_format_version.h" #include "content/browser/indexed_db/indexed_db_data_loss_info.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_reporting.h" #include "content/browser/indexed_db/indexed_db_tracing.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_iterator.h"
diff --git a/content/browser/indexed_db/indexed_db_reporting.cc b/content/browser/indexed_db/indexed_db_reporting.cc index 05c015a..40ca445 100644 --- a/content/browser/indexed_db/indexed_db_reporting.cc +++ b/content/browser/indexed_db/indexed_db_reporting.cc
@@ -10,7 +10,7 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "url/origin.h" namespace content {
diff --git a/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc b/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc index 35ac26e..0877f24 100644 --- a/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc +++ b/content/browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc
@@ -18,8 +18,8 @@ #include "components/services/storage/indexed_db/scopes/leveldb_scopes.h" #include "components/services/storage/indexed_db/scopes/varint_coding.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_leveldb_operations.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h" #include "content/public/test/browser_task_environment.h"
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc index fd48a0f..af0da64 100644 --- a/content/browser/indexed_db/indexed_db_unittest.cc +++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -19,8 +19,8 @@ #include "content/browser/indexed_db/indexed_db_execution_context_connection_tracker.h" #include "content/browser/indexed_db/indexed_db_factory_impl.h" #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" +#include "content/browser/indexed_db/indexed_db_leveldb_env.h" #include "content/browser/indexed_db/indexed_db_origin_state.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" @@ -68,7 +68,7 @@ }; std::unique_ptr<LevelDBLock> LockForTesting(const base::FilePath& file_name) { - leveldb::Env* env = LevelDBEnv::Get(); + leveldb::Env* env = IndexedDBLevelDBEnv::Get(); base::FilePath lock_path = file_name.AppendASCII("LOCK"); leveldb::FileLock* lock = nullptr; leveldb::Status status = env->LockFile(lock_path.AsUTF8Unsafe(), &lock);
diff --git a/content/browser/indexed_db/leveldb/leveldb_env.cc b/content/browser/indexed_db/leveldb/leveldb_env.cc deleted file mode 100644 index 24d0591..0000000 --- a/content/browser/indexed_db/leveldb/leveldb_env.cc +++ /dev/null
@@ -1,16 +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 "content/browser/indexed_db/leveldb/leveldb_env.h" - -namespace content { - -LevelDBEnv::LevelDBEnv() : ChromiumEnv("LevelDBEnv.IDB") {} - -LevelDBEnv* LevelDBEnv::Get() { - static base::NoDestructor<LevelDBEnv> g_leveldb_env; - return g_leveldb_env.get(); -} - -} // namespace content
diff --git a/content/browser/indexed_db/leveldb/leveldb_env.h b/content/browser/indexed_db/leveldb/leveldb_env.h deleted file mode 100644 index 98acac75..0000000 --- a/content/browser/indexed_db/leveldb/leveldb_env.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 CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ENV_H_ -#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ENV_H_ - -#include <memory> -#include <tuple> - -#include "base/no_destructor.h" -#include "content/common/content_export.h" -#include "third_party/leveldatabase/env_chromium.h" - -namespace content { - -// The leveldb::Env used by the Indexed DB backend. -class LevelDBEnv : public leveldb_env::ChromiumEnv { - public: - CONTENT_EXPORT static LevelDBEnv* Get(); - - private: - friend class base::NoDestructor<LevelDBEnv>; - LevelDBEnv(); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ENV_H_
diff --git a/content/browser/indexed_db/leveldb/transactional_leveldb_database.h b/content/browser/indexed_db/leveldb/transactional_leveldb_database.h index 92716a42..956eb40 100644 --- a/content/browser/indexed_db/leveldb/transactional_leveldb_database.h +++ b/content/browser/indexed_db/leveldb/transactional_leveldb_database.h
@@ -19,7 +19,6 @@ #include "base/time/clock.h" #include "base/trace_event/memory_dump_provider.h" #include "components/services/storage/indexed_db/leveldb/leveldb_state.h" -#include "content/browser/indexed_db/indexed_db_data_loss_info.h" #include "content/common/content_export.h" #include "third_party/leveldatabase/src/include/leveldb/options.h" #include "third_party/leveldatabase/src/include/leveldb/status.h"
diff --git a/content/browser/indexed_db/leveldb/transactional_leveldb_transaction_unittest.cc b/content/browser/indexed_db/leveldb/transactional_leveldb_transaction_unittest.cc index 1e8a05c5..5679199f 100644 --- a/content/browser/indexed_db/leveldb/transactional_leveldb_transaction_unittest.cc +++ b/content/browser/indexed_db/leveldb/transactional_leveldb_transaction_unittest.cc
@@ -17,11 +17,11 @@ #include "base/no_destructor.h" #include "base/strings/string_piece.h" #include "base/test/bind_test_util.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h" #include "components/services/storage/indexed_db/scopes/leveldb_scope.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_iterator.h"
diff --git a/content/browser/indexed_db/leveldb/transactional_leveldb_unittest.cc b/content/browser/indexed_db/leveldb/transactional_leveldb_unittest.cc index eb5d0d62..4d26acc0c 100644 --- a/content/browser/indexed_db/leveldb/transactional_leveldb_unittest.cc +++ b/content/browser/indexed_db/leveldb/transactional_leveldb_unittest.cc
@@ -23,7 +23,6 @@ #include "components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes_test_utils.h" -#include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_factory.h" @@ -151,10 +150,11 @@ } TEST(LevelDB, Locking) { + static base::NoDestructor<leveldb_env::ChromiumEnv> gTestEnv; base::ScopedTempDir temp_directory; ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); - leveldb::Env* env = LevelDBEnv::Get(); + leveldb::Env* env = gTestEnv.get(); base::FilePath file = temp_directory.GetPath().AppendASCII("LOCK"); leveldb::FileLock* lock; leveldb::Status status = env->LockFile(file.AsUTF8Unsafe(), &lock);
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index 9b3578a..19ec687 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -67,8 +67,7 @@ : WebContentsObserver(web_contents), audible_metrics_(GetAudibleMetrics()), session_controllers_manager_(this), - power_experiment_manager_(MediaPowerExperimentManager::Instance()), - weak_factory_(this) {} + power_experiment_manager_(MediaPowerExperimentManager::Instance()) {} MediaWebContentsObserver::~MediaWebContentsObserver() { // Remove all players so that the experiment manager is notified. @@ -97,6 +96,9 @@ picture_in_picture_allowed_in_fullscreen_.reset(); fullscreen_player_.reset(); } + + // Cancel any pending callbacks for players from this frame. + per_frame_factory_.erase(render_frame_host); } void MediaWebContentsObserver::MaybeUpdateAudibleState() { @@ -364,7 +366,7 @@ power_experiment_manager_->PlayerStarted( id, base::BindRepeating(&MediaWebContentsObserver::OnExperimentStateChanged, - weak_factory_.GetWeakPtr(), id)); + GetWeakPtrForFrame(id.render_frame_host), id)); } } @@ -450,4 +452,17 @@ RemoveAllPlayers(&active_video_players_); } +base::WeakPtr<MediaWebContentsObserver> +MediaWebContentsObserver::GetWeakPtrForFrame( + RenderFrameHost* render_frame_host) { + auto iter = per_frame_factory_.find(render_frame_host); + if (iter != per_frame_factory_.end()) + return iter->second->GetWeakPtr(); + + auto result = per_frame_factory_.emplace(std::make_pair( + render_frame_host, + std::make_unique<base::WeakPtrFactory<MediaWebContentsObserver>>(this))); + return result.first->second->GetWeakPtr(); +} + } // namespace content
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h index 777c487..23d190f4 100644 --- a/content/browser/media/media_web_contents_observer.h +++ b/content/browser/media/media_web_contents_observer.h
@@ -172,6 +172,12 @@ // Remove all players. void RemoveAllPlayers(); + // Return a weak pointer to |this| that's local to |render_frame_host|, in the + // sense that we can cancel all of the ptrs to one frame without cancelling + // pointers for any of the others. + base::WeakPtr<MediaWebContentsObserver> GetWeakPtrForFrame( + RenderFrameHost* render_frame_host); + // Helper class for recording audible metrics. AudibleMetrics* audible_metrics_; @@ -186,7 +192,9 @@ MediaSessionControllersManager session_controllers_manager_; MediaPowerExperimentManager* power_experiment_manager_ = nullptr; - base::WeakPtrFactory<MediaWebContentsObserver> weak_factory_; + std::map<RenderFrameHost*, + std::unique_ptr<base::WeakPtrFactory<MediaWebContentsObserver>>> + per_frame_factory_; DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserver); };
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc index 8ae76f76..0d6ae33 100644 --- a/content/browser/network_service_instance_impl.cc +++ b/content/browser/network_service_instance_impl.cc
@@ -108,8 +108,9 @@ auto registry = std::make_unique<service_manager::BinderRegistry>(); registry->AddInterface(base::BindRepeating( [](mojo::PendingReceiver<network::mojom::NetworkServiceTest>) {})); - g_in_process_instance = - new network::NetworkService(std::move(registry), std::move(receiver)); + g_in_process_instance = new network::NetworkService( + std::move(registry), std::move(receiver), + true /* delay_initialization_until_set_client */); } void CreateInProcessNetworkService(
diff --git a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc index cf501e0..5278b860 100644 --- a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc +++ b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -222,7 +222,7 @@ // If the synthetic wheel event for a touchpad double tap is canceled, we // should not change the page scale. IN_PROC_BROWSER_TEST_P(TouchpadPinchBrowserTest, - WheelListenerPreventingDoubleTap) { + DISABLED_WheelListenerPreventingDoubleTap) { LoadURL(); WebPreferences prefs =
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index cfaf408..a463463 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -207,7 +207,7 @@ class FakeWindowEventDispatcher : public aura::WindowEventDispatcher { public: FakeWindowEventDispatcher(aura::WindowTreeHost* host) - : WindowEventDispatcher(host, true), processed_touch_event_count_(0) {} + : WindowEventDispatcher(host), processed_touch_event_count_(0) {} void ProcessedTouchEvent( uint32_t unique_event_id,
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 64d81c3b..46493ca 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1608,12 +1608,12 @@ "../browser/indexed_db/indexed_db_fake_backing_store.cc", "../browser/indexed_db/indexed_db_fake_backing_store.h", "../browser/indexed_db/indexed_db_leveldb_coding_unittest.cc", + "../browser/indexed_db/indexed_db_leveldb_env_unittest.cc", "../browser/indexed_db/indexed_db_pre_close_task_queue_unittest.cc", "../browser/indexed_db/indexed_db_quota_client_unittest.cc", "../browser/indexed_db/indexed_db_tombstone_sweeper_unittest.cc", "../browser/indexed_db/indexed_db_transaction_unittest.cc", "../browser/indexed_db/indexed_db_unittest.cc", - "../browser/indexed_db/leveldb/leveldb_env_unittest.cc", "../browser/indexed_db/leveldb/transactional_leveldb_transaction_unittest.cc", "../browser/indexed_db/leveldb/transactional_leveldb_unittest.cc", "../browser/indexed_db/list_set_unittest.cc",
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index 983def9..00474fe 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -43,14 +43,14 @@ ```shell git cl try && - git cl try -B luci.chromium.try -b mac_chromium_asan_rel_ng \ + git cl try -B chromium/try -b mac_chromium_asan_rel_ng \ -b linux_chromium_cfi_rel_ng \ -b linux_chromium_chromeos_asan_rel_ng -b linux_chromium_msan_rel_ng \ -b linux_chromium_chromeos_msan_rel_ng -b linux-chromeos-dbg \ -b win-asan -b chromeos-amd64-generic-cfi-thin-lto-rel \ -b linux_chromium_compile_dbg_32_ng -b win7-rel \ -b win-angle-deqp-rel-64 && - git cl try -B luci.chrome.try -b iphone-device -b ipad-device + git cl try -B chrome/try -b iphone-device -b ipad-device ``` 1. Optional: Start Pinpoint perf tryjobs. These are generally too noisy to @@ -96,14 +96,7 @@ If you want to add something to the clang package that doesn't (yet?) meet these criteria, you can make package.py upload it to a separate zip file -and then download it on an opt-in basis by requiring users to run a script -to download the additional zip file. You can structure your script in a way that -it downloads your additional zip automatically if the script detects an -old version on disk, that way users have to run the download script just -once. `tools/clang/scripts/download_lld_mac.py` is an example for this -(It doesn't do the "only download if old version is on disk or if requested" -bit, and hence doesn't run as a default DEPS hook. TODO(thakis): Make -coverage stuff a better example and link to that.) +and then download it on an opt-in basis by using update.py's --package option. If you're adding a new feature that you expect will meet the inclusion criteria eventually but doesn't yet, start by having your things in a separate zip
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 232bce3..64a52bc2 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -693,6 +693,7 @@ std::vector<JsResourceInfo> resources = { {"appView", IDR_APP_VIEW_JS}, {"appViewElement", IDR_APP_VIEW_ELEMENT_JS}, + {"appViewDeny", IDR_APP_VIEW_DENY_JS}, {"entryIdManager", IDR_ENTRY_ID_MANAGER}, {"extensionOptions", IDR_EXTENSION_OPTIONS_JS}, {"extensionOptionsElement", IDR_EXTENSION_OPTIONS_ELEMENT_JS}, @@ -723,6 +724,7 @@ {"webView", IDR_WEB_VIEW_JS}, {"webViewElement", IDR_WEB_VIEW_ELEMENT_JS}, {"extensionsWebViewElement", IDR_EXTENSIONS_WEB_VIEW_ELEMENT_JS}, + {"webViewDeny", IDR_WEB_VIEW_DENY_JS}, {"webViewActionRequests", IDR_WEB_VIEW_ACTION_REQUESTS_JS}, {"webViewApiMethods", IDR_WEB_VIEW_API_METHODS_JS}, {"webViewAttributes", IDR_WEB_VIEW_ATTRIBUTES_JS}, @@ -1385,6 +1387,23 @@ ModuleSystem* module_system = context->module_system(); bool requires_guest_view_module = false; + // This determines whether to register error-providing custom elements for the + // GuestView types that are not available. We only do this in contexts where + // it is possible to gain access to a given GuestView element by declaring the + // necessary permission in a manifest file. We don't want to define + // error-providing elements in other extension contexts as the names could + // collide with names used in the extension. Also, WebUIs may be whitelisted + // to use GuestViews, but we don't define the error-providing elements in this + // case. + const bool is_platform_app = + context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT && + !context->IsForServiceWorker() && context->extension() && + context->extension()->is_platform_app(); + const bool app_view_permission_exists = is_platform_app; + // The webview permission is also available to internal whitelisted + // extensions, but not to extensions in general. + const bool web_view_permission_exists = is_platform_app; + // TODO(fsamuel): Eagerly calling Require on context startup is expensive. // It would be better if there were a light way of detecting when a webview // or appview is created and only then set up the infrastructure. @@ -1393,6 +1412,8 @@ if (context->GetAvailability("appViewEmbedderInternal").is_available()) { requires_guest_view_module = true; module_system->Require("appViewElement"); + } else if (app_view_permission_exists) { + module_system->Require("appViewDeny"); } // Require ExtensionOptions. @@ -1407,6 +1428,8 @@ // The embedder of the extensions layer may define its own implementation // of WebView. delegate_->RequireWebViewModules(context); + } else if (web_view_permission_exists) { + module_system->Require("webViewDeny"); } if (requires_guest_view_module && @@ -1425,15 +1448,6 @@ ->GetSettings() ->SetForceMainWorldInitialization(true); } - - // The "guestViewDeny" module must always be loaded last. It registers - // error-providing custom elements for the GuestView types that are not - // available, and thus all of those types must have been checked and loaded - // (or not loaded) beforehand. - if (context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT && - !context->IsForServiceWorker()) { - module_system->Require("guestViewDeny"); - } } std::unique_ptr<NativeExtensionBindingsSystem> Dispatcher::CreateBindingsSystem(
diff --git a/extensions/renderer/resources/extensions_renderer_resources.grd b/extensions/renderer/resources/extensions_renderer_resources.grd index 7d688ba..ea61498 100644 --- a/extensions/renderer/resources/extensions_renderer_resources.grd +++ b/extensions/renderer/resources/extensions_renderer_resources.grd
@@ -10,6 +10,7 @@ <includes> <!-- Extension libraries. --> <include name="IDR_APP_VIEW_JS" file="guest_view/app_view/app_view.js" type="BINDATA" /> + <include name="IDR_APP_VIEW_DENY_JS" file="guest_view/app_view/app_view_deny.js" type="BINDATA" /> <include name="IDR_APP_VIEW_ELEMENT_JS" file="guest_view/app_view/app_view_element.js" type="BINDATA" /> <include name="IDR_BROWSER_TEST_ENVIRONMENT_SPECIFIC_BINDINGS_JS" file="browser_test_environment_specific_bindings.js" type="BINDATA" /> <include name="IDR_ENTRY_ID_MANAGER" file="entry_id_manager.js" type="BINDATA" /> @@ -45,6 +46,7 @@ <include name="IDR_WEB_VIEW_EVENTS_JS" file="guest_view/web_view/web_view_events.js" type="BINDATA" /> <include name="IDR_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS" file="guest_view/web_view/web_view_internal.js" type="BINDATA" /> <include name="IDR_WEB_VIEW_JS" file="guest_view/web_view/web_view.js" type="BINDATA" /> + <include name="IDR_WEB_VIEW_DENY_JS" file="guest_view/web_view/web_view_deny.js" type="BINDATA" /> <include name="IDR_WEB_VIEW_ELEMENT_JS" file="guest_view/web_view/web_view_element.js" type="BINDATA" /> <!-- Custom bindings for APIs. -->
diff --git a/extensions/renderer/resources/guest_view/app_view/app_view_deny.js b/extensions/renderer/resources/guest_view/app_view/app_view_deny.js new file mode 100644 index 0000000..4802de02 --- /dev/null +++ b/extensions/renderer/resources/guest_view/app_view/app_view_deny.js
@@ -0,0 +1,7 @@ +// 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. + +var registerDeniedElement = require('guestViewDeny').registerDeniedElement; + +registerDeniedElement('AppView', 'appview');
diff --git a/extensions/renderer/resources/guest_view/guest_view_deny.js b/extensions/renderer/resources/guest_view/guest_view_deny.js index 64e353b..b3961b5 100644 --- a/extensions/renderer/resources/guest_view/guest_view_deny.js +++ b/extensions/renderer/resources/guest_view/guest_view_deny.js
@@ -11,48 +11,41 @@ var $EventTarget = require('safeMethods').SafeMethods.$EventTarget; var GuestViewInternalNatives = requireNative('guest_view_internal'); -var ERROR_MESSAGE = 'You do not have permission to use the %1 element.' + - ' Be sure to declare the "%1" permission in your manifest file.'; - -// A list of view types that will have custom elements registered if they are -// not already registered by the time this module is loaded. -var VIEW_TYPES = [ - 'AppView', - 'ExtensionOptions', - 'WebView' -]; - -// Registers a GuestView custom element. -function registerGuestViewElement(viewType) { +function registerDeniedElementInternal(viewType, permissionName) { GuestViewInternalNatives.AllowGuestViewElementDefinition(() => { var DeniedElement = class extends HTMLElement { constructor() { super(); - window.console.error($String.replace( - ERROR_MESSAGE, /%1/g, $String.toLowerCase(viewType))); + window.console.error(`You do not have permission to use the ${ + viewType} element. Be sure to declare the "${ + permissionName}" permission in your manifest file.`); } } $CustomElementRegistry.define( window.customElements, $String.toLowerCase(viewType), DeniedElement); - $Object.defineProperty(window, viewType, { - value: DeniedElement, - }); + // User code that does not have permission for this GuestView could be + // using the same name for another purpose, in which case we won't overwrite + // with the error-providing element. + if (!$Object.hasOwnProperty(window, viewType)) { + $Object.defineProperty(window, viewType, { + value: DeniedElement, + }); + } }); } -var useCapture = true; -window.addEventListener('readystatechange', function listener(event) { - if (document.readyState == 'loading') - return; +// Registers an error-providing GuestView custom element. +function registerDeniedElement(viewType, permissionName) { + let useCapture = true; + window.addEventListener('readystatechange', function listener(event) { + if (document.readyState == 'loading') + return; - for (var viewType of VIEW_TYPES) { - // Register the error-providing custom element only for those view types - // that have not already been registered. Since this module is always loaded - // last, all the view types that are available (i.e. have the proper - // permissions) will have already been registered on |window|. - if (!$Object.hasOwnProperty(window, viewType)) - registerGuestViewElement(viewType); - } + registerDeniedElementInternal(viewType, permissionName); - $EventTarget.removeEventListener(window, event.type, listener, useCapture); -}, useCapture); + $EventTarget.removeEventListener(window, event.type, listener, useCapture); + }, useCapture); +} + +// Exports. +exports.$set('registerDeniedElement', registerDeniedElement);
diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_deny.js b/extensions/renderer/resources/guest_view/web_view/web_view_deny.js new file mode 100644 index 0000000..f37e8211 --- /dev/null +++ b/extensions/renderer/resources/guest_view/web_view/web_view_deny.js
@@ -0,0 +1,7 @@ +// 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. + +var registerDeniedElement = require('guestViewDeny').registerDeniedElement; + +registerDeniedElement('WebView', 'webview');
diff --git a/gpu/command_buffer/service/scheduler.cc b/gpu/command_buffer/service/scheduler.cc index 349cb40..62f2b8b 100644 --- a/gpu/command_buffer/service/scheduler.cc +++ b/gpu/command_buffer/service/scheduler.cc
@@ -525,18 +525,25 @@ { base::AutoUnlock auto_unlock(lock_); order_data->BeginProcessingOrderNumber(order_num); - base::ThreadTicks thread_time_start = base::ThreadTicks::Now(); + + bool supports_thread_time = base::ThreadTicks::IsSupported(); + + // We can't call base::ThreadTicks::Now() if it's not supported + base::ThreadTicks thread_time_start = + supports_thread_time ? base::ThreadTicks::Now() : base::ThreadTicks(); base::TimeTicks wall_time_start = base::TimeTicks::Now(); std::move(closure).Run(); - base::TimeDelta thread_time_elapsed = - base::ThreadTicks::Now() - thread_time_start; - base::TimeDelta wall_time_elapsed = - base::TimeTicks::Now() - wall_time_start; - base::TimeDelta blocked_time = wall_time_elapsed - thread_time_elapsed; + if (supports_thread_time) { + base::TimeDelta thread_time_elapsed = + base::ThreadTicks::Now() - thread_time_start; + base::TimeDelta wall_time_elapsed = + base::TimeTicks::Now() - wall_time_start; + base::TimeDelta blocked_time = wall_time_elapsed - thread_time_elapsed; - total_blocked_time_ += blocked_time; + total_blocked_time_ += blocked_time; + } if (order_data->IsProcessingOrderNumber()) order_data->FinishProcessingOrderNumber(order_num); @@ -559,6 +566,8 @@ } base::TimeDelta Scheduler::TakeTotalBlockingTime() { + if (!base::ThreadTicks::IsSupported()) + return base::TimeDelta::Min(); base::TimeDelta result; std::swap(result, total_blocked_time_); return result;
diff --git a/gpu/command_buffer/service/scheduler.h b/gpu/command_buffer/service/scheduler.h index 9e413ddf..28c7ca4 100644 --- a/gpu/command_buffer/service/scheduler.h +++ b/gpu/command_buffer/service/scheduler.h
@@ -94,7 +94,8 @@ base::WeakPtr<Scheduler> AsWeakPtr(); - // Takes and resets current accumulated blocking time + // Takes and resets current accumulated blocking time. Not available on all + // platforms. Returns TimeDelta::Min() when not available. base::TimeDelta TakeTotalBlockingTime(); private:
diff --git a/gpu/ipc/service/pass_through_image_transport_surface.cc b/gpu/ipc/service/pass_through_image_transport_surface.cc index 34dba89..2459004 100644 --- a/gpu/ipc/service/pass_through_image_transport_surface.cc +++ b/gpu/ipc/service/pass_through_image_transport_surface.cc
@@ -239,7 +239,7 @@ auto blocked_time_since_last_swap = delegate_->GetGpuBlockedTimeSinceLastSwap(); - if (!multiple_surfaces_swapped_) { + if (!blocked_time_since_last_swap.is_min() && !multiple_surfaces_swapped_) { static constexpr base::TimeDelta kTimingMetricsHistogramMin = base::TimeDelta::FromMicroseconds(5); static constexpr base::TimeDelta kTimingMetricsHistogramMax =
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index 46bf69e..944061c 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -311,7 +311,6 @@ "//ios/chrome/browser/crash_report", "//ios/chrome/common", "//ios/testing/perf:startup", - "//third_party/google_toolbox_for_mac", ] }
diff --git a/ios/chrome/app/application_delegate/DEPS b/ios/chrome/app/application_delegate/DEPS index 1ef87f9e..fd7dad12 100644 --- a/ios/chrome/app/application_delegate/DEPS +++ b/ios/chrome/app/application_delegate/DEPS
@@ -1,3 +1,5 @@ -include_rules = [ - "+third_party/google_toolbox_for_mac", -] +specific_include_rules = { + "metrics_mediator\.mm": [ + "+third_party/google_toolbox_for_mac/src/Foundation/GTMTimeUtils.h", + ], +}
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index 690a898..7eec5e5 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -116,7 +116,6 @@ "+services/network/public/cpp", "+third_party/breakpad/breakpad/src/client/ios", "+third_party/breakpad/breakpad/src/common", - "+third_party/google_toolbox_for_mac", "+third_party/libaddressinput", "+third_party/libxml/chromium/xml_writer.h", "+third_party/metrics_proto",
diff --git a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm index d342568b..9ad7f4a4 100644 --- a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm +++ b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
@@ -155,15 +155,28 @@ } TestChromeBrowserState::~TestChromeBrowserState() { + // Allows blocking in this scope for testing. + base::ScopedAllowBlockingForTesting allow_bocking; + // If this TestChromeBrowserState owns an incognito TestChromeBrowserState, // tear it down first. otr_browser_state_.reset(); BrowserStateDependencyManager::GetInstance()->DestroyBrowserStateServices( this); + // The destructor of temp_dir_ will perform IO, so it needs to be deleted + // here while |allow_bocking| is still in scope. Keeps the same logic as + // ScopedTempDir::~ScopedTempDir(). + if (temp_dir_.IsValid()) { + ignore_result(temp_dir_.Delete()); + } } void TestChromeBrowserState::Init() { + // Allows blocking in this scope so directory manipulation can happen in this + // scope for testing. + base::ScopedAllowBlockingForTesting allow_bocking; + // If threads have been initialized, we should be on the UI thread. DCHECK(!web::WebThread::IsThreadInitialized(web::WebThread::UI) || web::WebThread::CurrentlyOn(web::WebThread::UI));
diff --git a/ios/chrome/browser/geolocation/BUILD.gn b/ios/chrome/browser/geolocation/BUILD.gn index 4c4c5d1..93ba05d 100644 --- a/ios/chrome/browser/geolocation/BUILD.gn +++ b/ios/chrome/browser/geolocation/BUILD.gn
@@ -28,7 +28,6 @@ "//ios/chrome/browser", "//ios/chrome/browser/ui/util", "//ios/public/provider/chrome/browser", - "//third_party/google_toolbox_for_mac", "//ui/base", "//url", ]
diff --git a/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm index e7a4299..e3a7fd9 100644 --- a/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm +++ b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm
@@ -6,36 +6,41 @@ #include <stdint.h> -#import "third_party/google_toolbox_for_mac/src/Foundation/GTMStringEncoding.h" +#include "base/base64url.h" +#include "base/strings/stringprintf.h" +#include "base/strings/sys_string_conversions.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -NSString* const kGMOLocationDescriptorFormat = - @"role: CURRENT_LOCATION\n" - @"producer: DEVICE_LOCATION\n" - @"timestamp: %lld\n" - @"radius: %ld\n" - @"latlng <\n" - @" latitude_e7: %.f\n" - @" longitude_e7: %.f\n" - @">"; +namespace { +// Returns the LocationDescriptor as an ASCII proto encoded in web safe base64. +std::string LocationDescriptorAsWebSafeBase64(int64_t timestamp, + long radius, + double latitude, + double longitude) { + const std::string location_descriptor = + base::StringPrintf("role: CURRENT_LOCATION\n" + "producer: DEVICE_LOCATION\n" + "timestamp: %lld\n" + "radius: %ld\n" + "latlng <\n" + " latitude_e7: %.f\n" + " longitude_e7: %.f\n" + ">", + timestamp, radius, latitude, longitude); + + std::string encoded_descriptor; + base::Base64UrlEncode(location_descriptor, + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &encoded_descriptor); + return encoded_descriptor; +} +} // namespace @implementation CLLocation (XGeoHeader) -- (NSString*)cr_serializeStringToWebSafeBase64String:(NSString*)data { - GTMStringEncoding* encoder = - [GTMStringEncoding rfc4648Base64WebsafeStringEncoding]; - NSString* base64 = - [encoder encode:[data dataUsingEncoding:NSUTF8StringEncoding] - error:nullptr]; - if (base64) { - return base64; - } - return @""; -} - // Returns the timestamp of this location in microseconds since the UNIX epoch. // Returns 0 if the timestamp is unavailable or invalid. - (int64_t)cr_timestampInMicroseconds { @@ -58,22 +63,16 @@ return -1L; } -// Returns the LocationDescriptor as an ASCII proto. -- (NSString*)cr_locationDescriptor { - // Construct the location descriptor using its format string. - return [NSString stringWithFormat:kGMOLocationDescriptorFormat, - [self cr_timestampInMicroseconds], - [self cr_accuracyInMillimeters], - floor(self.coordinate.latitude * 1e7), - floor(self.coordinate.longitude * 1e7)]; -} - - (NSString*)cr_xGeoString { - NSString* locationDescriptor = [self cr_locationDescriptor]; + const std::string encoded_location_descriptor = + LocationDescriptorAsWebSafeBase64([self cr_timestampInMicroseconds], + [self cr_accuracyInMillimeters], + floor(self.coordinate.latitude * 1e7), + floor(self.coordinate.longitude * 1e7)); + // The "a" indicates that it is an ASCII proto. - return [NSString - stringWithFormat:@"a %@", [self cr_serializeStringToWebSafeBase64String: - locationDescriptor]]; + return base::SysUTF8ToNSString( + base::StringPrintf("a %s", encoded_location_descriptor.c_str())); } @end
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h index cfe55369..c36306a 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h
@@ -20,7 +20,7 @@ #include "components/metrics/metrics_service_client.h" #include "components/omnibox/browser/omnibox_event_global_tracker.h" #include "components/ukm/observers/history_delete_observer.h" -#include "components/ukm/observers/sync_disable_observer.h" +#include "components/ukm/observers/ukm_consent_state_observer.h" #import "ios/chrome/browser/metrics/incognito_web_state_observer.h" #include "ios/web/public/deprecated/global_web_state_observer.h" @@ -45,7 +45,7 @@ class IOSChromeMetricsServiceClient : public IncognitoWebStateObserver, public metrics::MetricsServiceClient, public ukm::HistoryDeleteObserver, - public ukm::SyncDisableObserver, + public ukm::UkmConsentStateObserver, public web::GlobalWebStateObserver { public: ~IOSChromeMetricsServiceClient() override; @@ -76,15 +76,15 @@ override; base::TimeDelta GetStandardUploadInterval() override; void OnRendererProcessCrash() override; - bool SyncStateAllowsUkm() override; + bool IsUkmAllowedForAllProfiles() override; bool AreNotificationListenersEnabledOnAllProfiles() override; std::string GetUploadSigningKey() override; // ukm::HistoryDeleteObserver: void OnHistoryDeleted() override; - // ukm::SyncDisableObserver: - void OnSyncPrefsChanged(bool must_purge) override; + // ukm::UkmConsentStateObserver: + void OnUkmAllowedStateChanged(bool must_purge) override; // web::GlobalWebStateObserver: void WebStateDidStartLoading(web::WebState* web_state) override;
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm index e4bf9a1a..67c9f1eb 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
@@ -355,7 +355,7 @@ syncer::SyncService* sync = ProfileSyncServiceFactory::GetInstance()->GetForBrowserState( browser_state); - ObserveServiceForSyncDisables(sync, browser_state->GetPrefs()); + StartObserving(sync, browser_state->GetPrefs()); return (history_service != nullptr && sync != nullptr); } @@ -395,12 +395,12 @@ ukm_service_->Purge(); } -void IOSChromeMetricsServiceClient::OnSyncPrefsChanged(bool must_purge) { +void IOSChromeMetricsServiceClient::OnUkmAllowedStateChanged(bool must_purge) { if (!ukm_service_) return; if (must_purge) { ukm_service_->Purge(); - ukm_service_->ResetClientState(ukm::ResetReason::kOnSyncPrefsChanged); + ukm_service_->ResetClientState(ukm::ResetReason::kOnUkmAllowedStateChanged); } // Signal service manager to enable/disable UKM based on new state. UpdateRunningServices(); @@ -416,8 +416,8 @@ UpdateRunningServices(); } -bool IOSChromeMetricsServiceClient::SyncStateAllowsUkm() { - return SyncDisableObserver::SyncStateAllowsUkm(); +bool IOSChromeMetricsServiceClient::IsUkmAllowedForAllProfiles() { + return UkmConsentStateObserver::IsUkmAllowedForAllProfiles(); } bool IOSChromeMetricsServiceClient::
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 9671c20..d9c09a1 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -335,6 +335,8 @@ webState:(web::WebState*)webState completionHandler: (SuggestionsAvailableCompletion)completion { + if (!GetPageURLAndCheckTrustLevel(webState, nullptr)) + return; [self.suggestionHelper checkIfSuggestionsAvailableForForm:formName fieldIdentifier:fieldIdentifier @@ -385,7 +387,8 @@ frameID:(NSString*)frameID webState:(web::WebState*)webState completionHandler:(SuggestionsReadyCompletion)completion { - DCHECK(GetPageURLAndCheckTrustLevel(webState, nullptr)); + if (!GetPageURLAndCheckTrustLevel(webState, nullptr)) + return; NSArray<FormSuggestion*>* rawSuggestions = [self.suggestionHelper retrieveSuggestionsWithFormName:formName fieldIdentifier:fieldIdentifier
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc index c96f36a..3f7a1e44 100644 --- a/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -43,7 +43,7 @@ protected: // Returns the collection of default datatypes. std::vector<syncer::ModelType> DefaultDatatypes() { - static_assert(41 == syncer::ModelType::NUM_ENTRIES, + static_assert(40 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled).");
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h index bcd6a75..1575e8b 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h +++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h
@@ -9,8 +9,6 @@ #include <vector> -#import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h" - @protocol UnifiedConsentViewControllerDelegate; // UnifiedConsentViewController is a sub view controller to ask for the user
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 9a965698a..c1e3bacc 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -174,7 +174,6 @@ "//ios/web/public", "//ios/web/public/deprecated", "//ios/web/public/deprecated:deprecated_web_util", - "//third_party/google_toolbox_for_mac", "//ui/base", "//ui/gfx", "//url",
diff --git a/ios/chrome/browser/ui/commands/command_dispatcher.h b/ios/chrome/browser/ui/commands/command_dispatcher.h index c861c72..f9241719 100644 --- a/ios/chrome/browser/ui/commands/command_dispatcher.h +++ b/ios/chrome/browser/ui/commands/command_dispatcher.h
@@ -18,9 +18,9 @@ // be passed into objects that need to call, but not configure, the dispatcher // (anything other than a coordinator). To create such a pointer in a way that // both compiles and is checked for correctness at runtime, use the provided -// function-like macro CallableDispatcher, defined below. Usage is as follows: +// function-like macro HandlerForProtocol, defined below. Usage is as follows: // -// id<SomeProtocol> callable = CallableDispatcher(dispatcher, SomeProtocol); +// id<SomeProtocol> handler = HandlerForProtocol(dispatcher, SomeProtocol); // // |dispatcher| should be a CommandDispatcher object, and SomeProtocol is // the *name* of a protocol (not a string, not a Protocol* pointer, and not @@ -29,9 +29,9 @@ // This will typecast |dispatcher| to an id<SomeProtocol> (for compile-time // type checking), and verify that |dispatcher| is currently dispatching // for |protocol| (for run-time verification). If |dispatcher| isn't dispatching -// for |protocol|, CallableDispatcher() returns nil and DCHECKs. +// for |protocol|, HandlerForProtocol() returns nil and DCHECKs. // -#define CallableDispatcher(Dispatcher, ProtocolName) \ +#define HandlerForProtocol(Dispatcher, ProtocolName) \ static_cast<id<ProtocolName>>( \ [Dispatcher strictCallableForProtocol:@protocol(ProtocolName)])
diff --git a/ios/chrome/browser/ui/commands/command_dispatcher_unittest.mm b/ios/chrome/browser/ui/commands/command_dispatcher_unittest.mm index 5c67800..cee63cd 100644 --- a/ios/chrome/browser/ui/commands/command_dispatcher_unittest.mm +++ b/ios/chrome/browser/ui/commands/command_dispatcher_unittest.mm
@@ -419,20 +419,20 @@ EXPECT_TRUE([dispatcher dispatchingForProtocol:@protocol(HideProtocol)]); } -TEST_F(CommandDispatcherTest, CallableDispatcher) { +TEST_F(CommandDispatcherTest, HandlerForProtocol) { CommandDispatcher* dispatcher = [[CommandDispatcher alloc] init]; NSObject* target = [[NSObject alloc] init]; [dispatcher startDispatchingToTarget:target forProtocol:@protocol(ShowProtocol)]; - id<ShowProtocol> callable = CallableDispatcher(dispatcher, ShowProtocol); - EXPECT_EQ(callable, dispatcher); + id<ShowProtocol> handler = HandlerForProtocol(dispatcher, ShowProtocol); + EXPECT_EQ(handler, dispatcher); [dispatcher startDispatchingToTarget:target forProtocol:@protocol(HideProtocol)]; [dispatcher startDispatchingToTarget:target forProtocol:@protocol(CompositeProtocolWithMethods)]; - id<EmptyContainerProtocol> container_callable = - CallableDispatcher(dispatcher, EmptyContainerProtocol); - EXPECT_EQ(container_callable, dispatcher); + id<EmptyContainerProtocol> container_handler = + HandlerForProtocol(dispatcher, EmptyContainerProtocol); + EXPECT_EQ(container_handler, dispatcher); }
diff --git a/ios/chrome/browser/ui/image_util/BUILD.gn b/ios/chrome/browser/ui/image_util/BUILD.gn index 032c38a..c0e484e 100644 --- a/ios/chrome/browser/ui/image_util/BUILD.gn +++ b/ios/chrome/browser/ui/image_util/BUILD.gn
@@ -8,7 +8,6 @@ "image_util.mm", ] deps = [ - "//third_party/google_toolbox_for_mac", "//ui/base", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/chrome/browser/ui/image_util/image_util.mm b/ios/chrome/browser/ui/image_util/image_util.mm index cf00c3f..bcea792 100644 --- a/ios/chrome/browser/ui/image_util/image_util.mm +++ b/ios/chrome/browser/ui/image_util/image_util.mm
@@ -6,8 +6,6 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/image_util/image_util.h" - -#include "third_party/google_toolbox_for_mac/src/iPhone/GTMUIImage+Resize.h" #include "ui/gfx/color_analysis.h" #include "ui/gfx/image/image.h"
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index ac4e4d3..0c4ea20 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -83,7 +83,6 @@ "//ios/web/public:public", "//ios/web/public/security", "//skia", - "//third_party/google_toolbox_for_mac", "//ui/base", "//ui/base", "//ui/gfx",
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index eb8a083e1..9db12404 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -169,7 +169,6 @@ "//ios/web", "//net", "//skia", - "//third_party/google_toolbox_for_mac", "//ui/base", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm index f42a710..a14b043 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -32,7 +32,6 @@ #include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_theme_resources.h" #include "skia/ext/skia_utils_ios.h" -#include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h" #include "ui/base/l10n/l10n_util_mac.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h"
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index 13fe3b67..014a2e6 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -170,6 +170,7 @@ ] testonly = true sources = [ + "tab_grid_egtest.mm", "tab_grid_transition_egtest.mm", ] @@ -180,6 +181,7 @@ "//ios/chrome/test/earl_grey:eg_test_support+eg2", "//ios/testing/earl_grey:eg_test_support+eg2", "//ios/third_party/earl_grey2:test_lib", + "//ios/web/public/test/http_server", "//net:test_support", ] libs = [ "UIKit.framework" ]
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm index 7f80b0b8..e08e9a99 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm
@@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import <EarlGrey/EarlGrey.h> - #include "base/strings/stringprintf.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/testing/earl_grey/earl_grey_test.h" #import "ios/web/public/test/http_server/http_server.h" #import "ios/web/public/test/http_server/http_server_util.h" @@ -37,9 +36,22 @@ @implementation TabGridTestCase +#if defined(CHROME_EARL_GREY_2) ++ (void)setUpForTestCase { + [super setUpForTestCase]; + [self setUpHelper]; +} +#elif defined(CHROME_EARL_GREY_1) // Set up called once for the class. + (void)setUp { [super setUp]; + [self setUpHelper]; +} +#else +#error Not an EarlGrey Test +#endif + ++ (void)setUpHelper { std::map<GURL, std::string> responses; const char kPageFormat[] = "<head><title>%s</title></head><body>%s</body>"; responses[web::test::HttpServer::MakeUrl(kURL1)] =
diff --git a/ios/chrome/browser/ui/tabs/DEPS b/ios/chrome/browser/ui/tabs/DEPS new file mode 100644 index 0000000..c55a5355 --- /dev/null +++ b/ios/chrome/browser/ui/tabs/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "tab_view\.mm": [ + "+third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h", + ], +}
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index 3f03ff77..4a6fbfd8 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -48,7 +48,6 @@ #include "ios/chrome/grit/ios_strings.h" #import "ios/web/public/web_state.h" #import "ios/web/public/web_state_observer_bridge.h" -#include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h" #include "ui/gfx/image/image.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/tabs/tab_view.h b/ios/chrome/browser/ui/tabs/tab_view.h index 0726335..cb1010a 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.h +++ b/ios/chrome/browser/ui/tabs/tab_view.h
@@ -9,14 +9,13 @@ #import "ios/chrome/browser/ui/tabs/tab_view_delegate.h" -@class GTMFadeTruncatingLabel; @protocol TabViewDelegate; // View class that draws a Chrome-style tab. @interface TabView : UIControl @property(nonatomic, weak) id<TabViewDelegate> delegate; -@property(nonatomic, readonly, strong) GTMFadeTruncatingLabel* titleLabel; +@property(nonatomic, readonly, strong) UILabel* titleLabel; @property(nonatomic, strong) UIImage* favicon; @property(nonatomic, assign, getter=isCollapsed) BOOL collapsed; @property(nonatomic, strong) UIImage* background;
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm index 45aa5e7..46d33b14 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.mm +++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -406,17 +406,17 @@ faviconColorName = @"tabstrip_inactive_tab_text_color"; } _faviconView.tintColor = [UIColor colorNamed:faviconColorName]; - self.titleLabel.textColor = _faviconView.tintColor; + _titleLabel.textColor = _faviconView.tintColor; // Update font weight and accessibility label. UIFontWeight fontWeight = selected ? UIFontWeightSemibold : UIFontWeightMedium; - self.titleLabel.font = [UIFont systemFontOfSize:kFontSize weight:fontWeight]; + _titleLabel.font = [UIFont systemFontOfSize:kFontSize weight:fontWeight]; // It would make more sense to set active/inactive on tab_view itself, but // tab_view is not an an accessible element, and making it one would add // several complicated layers to UIA. Instead, simply set active/inactive // here to be used by UIA. - [self.titleLabel setAccessibilityValue:(selected ? @"active" : @"inactive")]; + [_titleLabel setAccessibilityValue:(selected ? @"active" : @"inactive")]; } #pragma mark - DropAndNavigateDelegate @@ -435,4 +435,10 @@ [_delegate tabViewTapped:self]; } +#pragma mark - Properties + +- (UILabel*)titleLabel { + return _titleLabel; +} + @end
diff --git a/ios/chrome/browser/voice/BUILD.gn b/ios/chrome/browser/voice/BUILD.gn index 83497674..d0cbba3 100644 --- a/ios/chrome/browser/voice/BUILD.gn +++ b/ios/chrome/browser/voice/BUILD.gn
@@ -61,7 +61,6 @@ "//ios/web", "//ios/web/public/deprecated", "//net", - "//third_party/google_toolbox_for_mac", "//url", ] } @@ -84,6 +83,5 @@ "//ios/web/common", "//ios/web/public/test", "//testing/gtest", - "//third_party/google_toolbox_for_mac", ] }
diff --git a/ios/chrome/browser/voice/text_to_speech_listener_unittest.mm b/ios/chrome/browser/voice/text_to_speech_listener_unittest.mm index 2c19ecdb..e805f32 100644 --- a/ios/chrome/browser/voice/text_to_speech_listener_unittest.mm +++ b/ios/chrome/browser/voice/text_to_speech_listener_unittest.mm
@@ -7,13 +7,13 @@ #include "ios/web/public/test/web_test_with_web_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" -#import "third_party/google_toolbox_for_mac/src/Foundation/GTMStringEncoding.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif namespace { +const char kExpectedDecodedData[] = "testaudo32oio"; NSString* const kHTMLFormat = @"<html><head><script>%@</script></head><body></body></html>"; NSString* const kValidVoiceSearchScript = @@ -89,14 +89,16 @@ }; TEST_F(TextToSpeechListenerTest, ValidAudioDataTest) { - GTMStringEncoding* encoder = [GTMStringEncoding rfc4648Base64StringEncoding]; - NSString* html = - [NSString stringWithFormat:kHTMLFormat, kValidVoiceSearchScript]; NSData* expected_audio_data = - [encoder decode:@"dGVzdGF1ZG8zMm9pbw==" error:nullptr]; - TestExtraction(html, expected_audio_data); + [NSData dataWithBytes:&kExpectedDecodedData[0] + length:sizeof(kExpectedDecodedData) - 1]; + TestExtraction( + [NSString stringWithFormat:kHTMLFormat, kValidVoiceSearchScript], + expected_audio_data); } TEST_F(TextToSpeechListenerTest, InvalidAudioDataTest) { - TestExtraction([NSString stringWithFormat:kHTMLFormat, @""], nil); + NSData* expected_audio_data = nil; + TestExtraction([NSString stringWithFormat:kHTMLFormat, @""], + expected_audio_data); }
diff --git a/ios/chrome/browser/voice/text_to_speech_parser.mm b/ios/chrome/browser/voice/text_to_speech_parser.mm index 40ea6d2..683f2da 100644 --- a/ios/chrome/browser/voice/text_to_speech_parser.mm +++ b/ios/chrome/browser/voice/text_to_speech_parser.mm
@@ -4,10 +4,11 @@ #import "ios/chrome/browser/voice/text_to_speech_parser.h" +#include "base/base64.h" #include "base/logging.h" +#include "base/strings/sys_string_conversions.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" #import "ios/web/public/web_state.h" -#import "third_party/google_toolbox_for_mac/src/Foundation/GTMStringEncoding.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -88,14 +89,18 @@ NSRange search_range = NSMakeRange(raw_base64_encoded_audio_string.length - search_range_length, search_range_length); - NSString* base64_encoded_audio_string = [raw_base64_encoded_audio_string - stringByReplacingOccurrencesOfString:kTrailingEqualEncoding - withString:@"=" - options:0 - range:search_range]; + const std::string base64_encoded_audio_string = + base::SysNSStringToUTF8([raw_base64_encoded_audio_string + stringByReplacingOccurrencesOfString:kTrailingEqualEncoding + withString:@"=" + options:0 + range:search_range]); - GTMStringEncoding* base64 = [GTMStringEncoding rfc4648Base64StringEncoding]; - return [base64 decode:base64_encoded_audio_string error:nullptr]; + std::string decoded_data; + if (!base::Base64Decode(base64_encoded_audio_string, &decoded_data)) + return nil; + + return [NSData dataWithBytes:decoded_data.c_str() length:decoded_data.size()]; } void ExtractVoiceSearchAudioDataFromWebState(
diff --git a/ios/chrome/browser/voice/text_to_speech_parser_unittest.mm b/ios/chrome/browser/voice/text_to_speech_parser_unittest.mm index 5616cb73..7590542 100644 --- a/ios/chrome/browser/voice/text_to_speech_parser_unittest.mm +++ b/ios/chrome/browser/voice/text_to_speech_parser_unittest.mm
@@ -6,8 +6,8 @@ #import "ios/chrome/browser/voice/text_to_speech_parser.h" #include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" #include "testing/platform_test.h" -#import "third_party/google_toolbox_for_mac/src/Foundation/GTMStringEncoding.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -17,6 +17,7 @@ NSData* ExtractVoiceSearchAudioDataFromPageHTML(NSString* pageHTML); namespace { +const char kExpectedDecodedData[] = "testaudo32oio"; NSString* const kValidVoiceSearchHTML = @"<script>(function(){var _a_tts='dGVzdGF1ZG8zMm9pbw==';var _m_tts= {}}"; NSString* const kInvalidVoiceSearchHTML = @"no TTS data"; @@ -28,15 +29,16 @@ NSData* result = ExtractVoiceSearchAudioDataFromPageHTML(kValidVoiceSearchHTML); - EXPECT_TRUE(result != nil); + EXPECT_NSNE(result, nil); - GTMStringEncoding* base64 = [GTMStringEncoding rfc4648Base64StringEncoding]; - NSData* expectedData = [base64 decode:@"dGVzdGF1ZG8zMm9pbw==" error:nullptr]; - EXPECT_TRUE([expectedData isEqualToData:result]); + NSData* expectedData = + [NSData dataWithBytes:&kExpectedDecodedData[0] + length:sizeof(kExpectedDecodedData) - 1]; + EXPECT_NSEQ(expectedData, result); } TEST_F(TextToSpeechParser, ExtractAudioDataNotFound) { NSData* result = ExtractVoiceSearchAudioDataFromPageHTML(kInvalidVoiceSearchHTML); - EXPECT_TRUE(result == nil); + EXPECT_NSEQ(result, nil); }
diff --git a/ios/chrome/test/DEPS b/ios/chrome/test/DEPS index b31f416..95ffef9 100644 --- a/ios/chrome/test/DEPS +++ b/ios/chrome/test/DEPS
@@ -27,7 +27,6 @@ "+net/url_request", "+services/network/public/cpp", "+third_party/breakpad/breakpad/src/client/ios", - "+third_party/google_toolbox_for_mac", "+ui", # Strings and resources.
diff --git a/ios/testing/DEPS b/ios/testing/DEPS index 616b5038..49528e5 100644 --- a/ios/testing/DEPS +++ b/ios/testing/DEPS
@@ -1,6 +1,11 @@ include_rules = [ "+ios/third_party/earl_grey2/src", "+net", - "+third_party/google_toolbox_for_mac", "+third_party/ocmock", ] + +specific_include_rules = { + "ocmock_complex_type_helper\.h": [ + "+third_party/google_toolbox_for_mac/src/Foundation/GTMLightweightProxy.h", + ], +}
diff --git a/ios/web/public/test/error_test_util.h b/ios/web/public/test/error_test_util.h index c34e169..23d52a4 100644 --- a/ios/web/public/test/error_test_util.h +++ b/ios/web/public/test/error_test_util.h
@@ -27,7 +27,8 @@ const std::string& error_domain, long error_code, bool is_post, - bool is_off_the_record); + bool is_off_the_record, + bool has_ssl_info); } // namespace testing } // namespace web
diff --git a/ios/web/public/test/error_test_util.mm b/ios/web/public/test/error_test_util.mm index 57a13b4a..6de51bf 100644 --- a/ios/web/public/test/error_test_util.mm +++ b/ios/web/public/test/error_test_util.mm
@@ -27,11 +27,13 @@ const std::string& error_domain, long error_code, bool is_post, - bool is_off_the_record) { - return base::StringPrintf( - "web_state: %p url: %s domain: %s code: %ld post: %d otr: %d", web_state, - url.spec().c_str(), error_domain.c_str(), error_code, is_post, - is_off_the_record); + bool is_off_the_record, + bool has_ssl_info) { + return base::StringPrintf("web_state: %p url: %s domain: %s code: %ld post: " + "%d otr: %d ssl_info: %d", + web_state, url.spec().c_str(), error_domain.c_str(), + error_code, is_post, is_off_the_record, + has_ssl_info); } } // namespace testing
diff --git a/ios/web/public/test/fakes/test_web_client.mm b/ios/web/public/test/fakes/test_web_client.mm index 3ae6b8f..d7c6eca 100644 --- a/ios/web/public/test/fakes/test_web_client.mm +++ b/ios/web/public/test/fakes/test_web_client.mm
@@ -109,7 +109,7 @@ base::OnceCallback<void(NSString*)> callback) { std::move(callback).Run(base::SysUTF8ToNSString(testing::GetErrorText( web_state, url, base::SysNSStringToUTF8(error.domain), error.code, - is_post, is_off_the_record))); + is_post, is_off_the_record, info.has_value()))); } UIView* TestWebClient::GetWindowedContainer() {
diff --git a/ios/web/web_state/bad_ssl_response_inttest.mm b/ios/web/web_state/bad_ssl_response_inttest.mm index a9e46438..257d90b 100644 --- a/ios/web/web_state/bad_ssl_response_inttest.mm +++ b/ios/web/web_state/bad_ssl_response_inttest.mm
@@ -248,7 +248,8 @@ web_state(), testing::GetErrorText(web_state(), url, "NSURLErrorDomain", /*error_code=*/NSURLErrorServerCertificateUntrusted, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/true))); ASSERT_TRUE(security_state_info()); ASSERT_TRUE(security_state_info()->visible_ssl_status); EXPECT_EQ(SECURITY_STYLE_AUTHENTICATION_BROKEN,
diff --git a/ios/web/web_state/error_page_inttest.mm b/ios/web/web_state/error_page_inttest.mm index ce77308..0249744f 100644 --- a/ios/web/web_state/error_page_inttest.mm +++ b/ios/web/web_state/error_page_inttest.mm
@@ -48,7 +48,8 @@ web_state, testing::GetErrorText(web_state, url, "NSURLErrorDomain", /*error_code=*/NSURLErrorNetworkConnectionLost, - /*is_post=*/false, /*is_otr=*/false)); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false)); } } // namespace @@ -327,7 +328,8 @@ testing::GetErrorText(web_state.get(), server_.GetURL("/echo-query?foo"), "NSURLErrorDomain", /*error_code=*/NSURLErrorNetworkConnectionLost, - /*is_post=*/false, /*is_otr=*/true))); + /*is_post=*/false, /*is_otr=*/true, + /*has_ssl_info=*/false))); } // Loads the URL with form which fails to submit. @@ -342,10 +344,10 @@ // Error is displayed after the form submission navigation. ASSERT_TRUE(test::WaitForWebViewContainingText( web_state(), - testing::GetErrorText(web_state(), server_.GetURL("/close-socket"), - "NSURLErrorDomain", - /*error_code=*/NSURLErrorNetworkConnectionLost, - /*is_post=*/true, /*is_otr=*/false))); + testing::GetErrorText( + web_state(), server_.GetURL("/close-socket"), "NSURLErrorDomain", + /*error_code=*/NSURLErrorNetworkConnectionLost, + /*is_post=*/true, /*is_otr=*/false, /*has_ssl_info=*/false))); } // Loads an item and checks that virtualURL and URL after displaying the error
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index e91e78e7..02a908a 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -1139,7 +1139,8 @@ ASSERT_TRUE(test::WaitForWebViewContainingText( web_state(), testing::GetErrorText(web_state(), url, "NSURLErrorDomain", /*error_code=*/-1005, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false))); DCHECK_EQ(item->GetTitle(), base::UTF8ToUTF16(kFailedTitle)); } @@ -1280,7 +1281,8 @@ ASSERT_TRUE(test::WaitForWebViewContainingText( web_state(), testing::GetErrorText(web_state(), url, "NSURLErrorDomain", /*error_code=*/-1002, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false))); } // Tests failed navigation because URL with a space is not supported by @@ -1332,7 +1334,8 @@ ASSERT_TRUE(test::WaitForWebViewContainingText( web_state(), testing::GetErrorText(web_state(), url, "WebKitErrorDomain", /*error_code=*/101, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false))); } // Tests failed navigation because URL scheme is not supported by WebState.
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm index cc7035b..70275bb 100644 --- a/ios/web/web_state/web_state_unittest.mm +++ b/ios/web/web_state/web_state_unittest.mm
@@ -608,7 +608,8 @@ web_state(), testing::GetErrorText(web_state(), app_specific_url, "NSURLErrorDomain", /*error_code=*/NSURLErrorUnsupportedURL, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false))); NSString* data_html = @(kTestPageHTML); web_state()->LoadData([data_html dataUsingEncoding:NSUTF8StringEncoding], @"text/html", GURL("https://www.chromium.org")); @@ -643,7 +644,8 @@ web_state(), testing::GetErrorText(web_state(), app_specific_url, "NSURLErrorDomain", /*error_code=*/NSURLErrorUnsupportedURL, - /*is_post=*/false, /*is_otr=*/false))); + /*is_post=*/false, /*is_otr=*/false, + /*has_ssl_info=*/false))); NSString* data_html = @(kTestPageHTML); web_state()->LoadData([data_html dataUsingEncoding:NSUTF8StringEncoding], @"text/html", echo_url);
diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index 85f9ed7a..fe8d3cf8 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc
@@ -23,10 +23,26 @@ MockPipeline::MockPipeline() = default; MockPipeline::~MockPipeline() = default; +void MockPipeline::Start(StartType start_type, + Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, + Client* client, + const PipelineStatusCB& seek_cb) { + Start(start_type, demuxer, &renderer, client, seek_cb); +} + +void MockPipeline::Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta timestamp, + const PipelineStatusCB& seek_cb) { + Resume(&renderer, timestamp, seek_cb); +} + MockMediaResource::MockMediaResource() = default; + MockMediaResource::~MockMediaResource() = default; MockDemuxer::MockDemuxer() = default; + MockDemuxer::~MockDemuxer() = default; std::string MockDemuxer::GetDisplayName() const { @@ -108,10 +124,6 @@ MockRenderer::~MockRenderer() = default; -MockRendererFactory::MockRendererFactory() = default; - -MockRendererFactory::~MockRendererFactory() = default; - MockTimeSource::MockTimeSource() = default; MockTimeSource::~MockTimeSource() = default;
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 3a9a1c8..d645f4b5 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h
@@ -33,7 +33,6 @@ #include "media/base/pipeline_status.h" #include "media/base/renderer.h" #include "media/base/renderer_client.h" -#include "media/base/renderer_factory.h" #include "media/base/stream_parser.h" #include "media/base/text_track.h" #include "media/base/text_track_config.h" @@ -76,12 +75,23 @@ MockPipeline(); ~MockPipeline() override; - MOCK_METHOD4(Start, - void(StartType, Demuxer*, Client*, const PipelineStatusCB&)); + // Note: Start() and Resume() declarations are not actually overrides; they + // take unique_ptr* instead of unique_ptr so that they can be mock methods. + // Private stubs for Start() and Resume() implement the actual Pipeline + // interface by forwarding to these mock methods. + MOCK_METHOD5(Start, + void(StartType start_type, + Demuxer*, + std::unique_ptr<Renderer>*, + Client*, + const PipelineStatusCB&)); MOCK_METHOD0(Stop, void()); MOCK_METHOD2(Seek, void(base::TimeDelta, const PipelineStatusCB&)); MOCK_METHOD1(Suspend, void(const PipelineStatusCB&)); - MOCK_METHOD2(Resume, void(base::TimeDelta, const PipelineStatusCB&)); + MOCK_METHOD3(Resume, + void(std::unique_ptr<Renderer>*, + base::TimeDelta, + const PipelineStatusCB&)); MOCK_METHOD2(OnEnabledAudioTracksChanged, void(const std::vector<MediaTrack::Id>&, base::OnceClosure)); MOCK_METHOD2(OnSelectedVideoTrackChanged, @@ -113,6 +123,16 @@ void(CdmContext* cdm_context, CdmAttachedCB& cdm_attached_cb)); private: + // Forwarding stubs (see comment above). + void Start(StartType start_type, + Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, + Client* client, + const PipelineStatusCB& seek_cb) override; + void Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta timestamp, + const PipelineStatusCB& seek_cb) override; + DISALLOW_COPY_AND_ASSIGN(MockPipeline); }; @@ -363,25 +383,6 @@ DISALLOW_COPY_AND_ASSIGN(MockRenderer); }; -class MockRendererFactory : public RendererFactory { - public: - MockRendererFactory(); - ~MockRendererFactory() override; - - // Renderer implementation. - MOCK_METHOD6(CreateRenderer, - std::unique_ptr<Renderer>( - const scoped_refptr<base::SingleThreadTaskRunner>&, - const scoped_refptr<base::TaskRunner>&, - AudioRendererSink*, - VideoRendererSink*, - const RequestOverlayInfoCB&, - const gfx::ColorSpace&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockRendererFactory); -}; - class MockTimeSource : public TimeSource { public: MockTimeSource();
diff --git a/media/base/pipeline.h b/media/base/pipeline.h index cbeef34..3ceb0e48 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h
@@ -27,6 +27,7 @@ namespace media { class Demuxer; +class Renderer; class MEDIA_EXPORT Pipeline { public: @@ -94,16 +95,17 @@ kSuspendAfterMetadata, // Always suspend after metadata. }; - // Build a pipeline to using the given |demuxer| to construct a filter chain, - // executing |seek_cb| when the initial seek has completed. Methods on - // PipelineClient may be called up until Stop() has completed. It is an error - // to call this method after the pipeline has already started. + // Build a pipeline to using the given |demuxer| and |renderer| to construct + // a filter chain, executing |seek_cb| when the initial seek has completed. + // Methods on PipelineClient may be called up until Stop() has completed. + // It is an error to call this method after the pipeline has already started. // // If a |start_type| is specified which allows suspension, pipeline startup // will halt after metadata has been retrieved and the pipeline will be in a // suspended state. virtual void Start(StartType start_type, Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, Client* client, const PipelineStatusCB& seek_cb) = 0; @@ -173,11 +175,12 @@ // seeking. virtual void Suspend(const PipelineStatusCB& suspend_cb) = 0; - // Resume the pipeline and seek to |timestamp|. + // Resume the pipeline with a new renderer, and initialize it with a seek. // // It is an error to call this method if the pipeline has not finished // suspending. - virtual void Resume(base::TimeDelta timestamp, + virtual void Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta timestamp, const PipelineStatusCB& seek_cb) = 0; // Returns true if the pipeline has been started via Start(). If IsRunning()
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index c126e5d..a237b850 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc
@@ -49,17 +49,17 @@ public: RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - CreateRendererCB create_renderer_cb, MediaLog* media_log); ~RendererWrapper() final; void Start(StartType start_type, Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, base::WeakPtr<PipelineImpl> weak_pipeline); void Stop(); void Seek(base::TimeDelta time); void Suspend(); - void Resume(base::TimeDelta time); + void Resume(std::unique_ptr<Renderer> renderer, base::TimeDelta time); void SetPlaybackRate(double playback_rate); void SetVolume(float volume); base::TimeDelta GetMediaTime() const; @@ -151,16 +151,12 @@ void CompleteSeek(base::TimeDelta seek_time, PipelineStatus status); void CompleteSuspend(PipelineStatus status); void InitializeDemuxer(PipelineStatusCallback done_cb); - void CreateRenderer(PipelineStatusCallback done_cb); - void OnRendererCreated(PipelineStatusCallback done_cb, - std::unique_ptr<Renderer> renderer); void InitializeRenderer(PipelineStatusCallback done_cb); void DestroyRenderer(); void ReportMetadata(StartType start_type); const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - CreateRendererCB create_renderer_cb_; MediaLog* const media_log_; base::WeakPtr<PipelineImpl> weak_pipeline_; @@ -202,11 +198,9 @@ PipelineImpl::RendererWrapper::RendererWrapper( scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - CreateRendererCB create_renderer_cb, MediaLog* media_log) : media_task_runner_(std::move(media_task_runner)), main_task_runner_(std::move(main_task_runner)), - create_renderer_cb_(create_renderer_cb), media_log_(media_log), demuxer_(nullptr), playback_rate_(kDefaultPlaybackRate), @@ -231,16 +225,26 @@ void PipelineImpl::RendererWrapper::Start( StartType start_type, Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, base::WeakPtr<PipelineImpl> weak_pipeline) { DCHECK(media_task_runner_->BelongsToCurrentThread()); DCHECK(state_ == kCreated || state_ == kStopped) << "Received start in unexpected state: " << state_; + + // Tracking down http://crbug.com/827990 + CHECK(renderer); + + SetState(kStarting); + DCHECK(!demuxer_); DCHECK(!renderer_ended_); DCHECK(!text_renderer_ended_); - - SetState(kStarting); demuxer_ = demuxer; + { + base::AutoLock auto_lock(shared_state_lock_); + DCHECK(!shared_state_.renderer); + shared_state_.renderer = std::move(renderer); + } weak_pipeline_ = weak_pipeline; // Setup |error_cb_| on the media thread. @@ -261,10 +265,6 @@ fns.Push(base::BindOnce(&RendererWrapper::ReportMetadata, weak_factory_.GetWeakPtr(), start_type)); - // Create renderer. - fns.Push(base::BindOnce(&RendererWrapper::CreateRenderer, - weak_factory_.GetWeakPtr())); - // Initialize renderer. fns.Push(base::BindOnce(&RendererWrapper::InitializeRenderer, weak_factory_.GetWeakPtr())); @@ -381,9 +381,13 @@ weak_factory_.GetWeakPtr())); } -void PipelineImpl::RendererWrapper::Resume(base::TimeDelta timestamp) { +void PipelineImpl::RendererWrapper::Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta timestamp) { DCHECK(media_task_runner_->BelongsToCurrentThread()); + // Tracking down http://crbug.com/827990 + CHECK(renderer); + // Suppress resuming if we're not suspended. if (state_ != kSuspended) { DCHECK(state_ == kStopping || state_ == kStopped) @@ -398,6 +402,7 @@ { base::AutoLock auto_lock(shared_state_lock_); DCHECK(!shared_state_.renderer); + shared_state_.renderer = std::move(renderer); } renderer_ended_ = false; @@ -411,9 +416,6 @@ fns.Push(base::BindRepeating(&Demuxer::Seek, base::Unretained(demuxer_), start_timestamp)); - fns.Push(base::BindOnce(&RendererWrapper::CreateRenderer, - weak_factory_.GetWeakPtr())); - fns.Push(base::BindOnce(&RendererWrapper::InitializeRenderer, weak_factory_.GetWeakPtr())); @@ -885,37 +887,6 @@ demuxer_->Initialize(this, std::move(done_cb)); } -void PipelineImpl::RendererWrapper::CreateRenderer( - PipelineStatusCallback done_cb) { - DVLOG(1) << __func__; - DCHECK(media_task_runner_->BelongsToCurrentThread()); - - // Use BindToCurrentLoop to make sure OnRendererCreated() is called on the - // media task runner. - create_renderer_cb_.Run(BindToCurrentLoop( - base::BindOnce(&RendererWrapper::OnRendererCreated, - weak_factory_.GetWeakPtr(), std::move(done_cb)))); -} - -void PipelineImpl::RendererWrapper::OnRendererCreated( - PipelineStatusCallback done_cb, - std::unique_ptr<Renderer> renderer) { - DVLOG(1) << __func__ << ": renderer=" << renderer.get(); - DCHECK(media_task_runner_->BelongsToCurrentThread()); - - if (!renderer) { - std::move(done_cb).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); - return; - } - - { - base::AutoLock auto_lock(shared_state_lock_); - DCHECK(!shared_state_.renderer); - shared_state_.renderer = std::move(renderer); - } - std::move(done_cb).Run(PIPELINE_OK); -} - void PipelineImpl::RendererWrapper::InitializeRenderer( PipelineStatusCallback done_cb) { DCHECK(media_task_runner_->BelongsToCurrentThread()); @@ -1019,7 +990,6 @@ PipelineImpl::PipelineImpl( scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - CreateRendererCB create_renderer_cb, MediaLog* media_log) : media_task_runner_(media_task_runner), media_log_(media_log), @@ -1028,9 +998,8 @@ volume_(kDefaultVolume), is_suspended_(false) { DVLOG(2) << __func__; - renderer_wrapper_.reset( - new RendererWrapper(media_task_runner_, std::move(main_task_runner), - std::move(create_renderer_cb), media_log_)); + renderer_wrapper_.reset(new RendererWrapper( + media_task_runner_, std::move(main_task_runner), media_log_)); } PipelineImpl::~PipelineImpl() { @@ -1047,11 +1016,13 @@ void PipelineImpl::Start(StartType start_type, Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, Client* client, const PipelineStatusCB& seek_cb) { DVLOG(2) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(demuxer); + DCHECK(renderer); DCHECK(client); DCHECK(seek_cb); @@ -1063,10 +1034,10 @@ seek_time_ = kNoTimestamp; media_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&RendererWrapper::Start, - base::Unretained(renderer_wrapper_.get()), start_type, - demuxer, weak_factory_.GetWeakPtr())); + FROM_HERE, base::BindOnce(&RendererWrapper::Start, + base::Unretained(renderer_wrapper_.get()), + start_type, demuxer, base::Passed(&renderer), + weak_factory_.GetWeakPtr())); } void PipelineImpl::Stop() { @@ -1133,10 +1104,12 @@ base::Unretained(renderer_wrapper_.get()))); } -void PipelineImpl::Resume(base::TimeDelta time, +void PipelineImpl::Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta time, const PipelineStatusCB& seek_cb) { DVLOG(2) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(renderer); DCHECK(seek_cb); DCHECK(IsRunning()); @@ -1146,9 +1119,9 @@ last_media_time_ = base::TimeDelta(); media_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&RendererWrapper::Resume, - base::Unretained(renderer_wrapper_.get()), time)); + FROM_HERE, base::BindOnce(&RendererWrapper::Resume, + base::Unretained(renderer_wrapper_.get()), + base::Passed(&renderer), time)); } bool PipelineImpl::IsRunning() const {
diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 15c9a67d..7800afc 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h
@@ -13,7 +13,6 @@ #include "base/threading/thread_checker.h" #include "media/base/media_export.h" #include "media/base/pipeline.h" -#include "media/base/renderer.h" namespace base { class SingleThreadTaskRunner; @@ -23,10 +22,6 @@ class MediaLog; -// Callbacks used for Renderer creation. -using RendererCreatedCB = base::OnceCallback<void(std::unique_ptr<Renderer>)>; -using CreateRendererCB = base::RepeatingCallback<void(RendererCreatedCB)>; - // Pipeline runs the media pipeline. Filters are created and called on the // task runner injected into this object. Pipeline works like a state // machine to perform asynchronous initialization, pausing, seeking and playing. @@ -75,22 +70,23 @@ public: // Constructs a media pipeline that will execute media tasks on // |media_task_runner|. - // |create_renderer_cb|: to create renderers when starting and resuming. PipelineImpl(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - CreateRendererCB create_renderer_cb, MediaLog* media_log); ~PipelineImpl() override; // Pipeline implementation. void Start(StartType start_type, Demuxer* demuxer, + std::unique_ptr<Renderer> renderer, Client* client, const PipelineStatusCB& seek_cb) override; void Stop() override; void Seek(base::TimeDelta time, const PipelineStatusCB& seek_cb) override; void Suspend(const PipelineStatusCB& suspend_cb) override; - void Resume(base::TimeDelta time, const PipelineStatusCB& seek_cb) override; + void Resume(std::unique_ptr<Renderer> renderer, + base::TimeDelta time, + const PipelineStatusCB& seek_cb) override; bool IsRunning() const override; bool IsSuspended() const override; double GetPlaybackRate() const override;
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 8a99a09..dcb09b6 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc
@@ -103,18 +103,14 @@ }; PipelineImplTest() - : demuxer_(new StrictMock<MockDemuxer>()), + : pipeline_(new PipelineImpl(task_environment_.GetMainThreadTaskRunner(), + task_environment_.GetMainThreadTaskRunner(), + &media_log_)), + demuxer_(new StrictMock<MockDemuxer>()), demuxer_host_(nullptr), scoped_renderer_(new StrictMock<MockRenderer>()), renderer_(scoped_renderer_.get()), renderer_client_(nullptr) { - pipeline_ = std::make_unique<PipelineImpl>( - task_environment_.GetMainThreadTaskRunner(), - task_environment_.GetMainThreadTaskRunner(), - base::BindRepeating(&PipelineImplTest::CreateRenderer, - base::Unretained(this)), - &media_log_); - // SetDemuxerExpectations() adds overriding expectations for expected // non-NULL streams. std::vector<DemuxerStream*> empty; @@ -186,7 +182,7 @@ Pipeline::StartType start_type = Pipeline::StartType::kNormal) { EXPECT_CALL(callbacks_, OnWaiting(_)).Times(0); pipeline_->Start( - start_type, demuxer_.get(), &callbacks_, + start_type, demuxer_.get(), std::move(scoped_renderer_), &callbacks_, base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); } @@ -277,14 +273,10 @@ pipeline_->Suspend( base::Bind(&CallbackHelper::OnSuspend, base::Unretained(&callbacks_))); base::RunLoop().RunUntilIdle(); - ResetRenderer(); + CreateRenderer(); } - void CreateRenderer(RendererCreatedCB renderer_created_cb) { - std::move(renderer_created_cb).Run(std::move(scoped_renderer_)); - } - - void ResetRenderer() { + void CreateRenderer() { // |renderer_| has been deleted, replace it. scoped_renderer_.reset(new StrictMock<MockRenderer>()); renderer_ = scoped_renderer_.get(); @@ -306,8 +298,9 @@ } void DoResume(const base::TimeDelta& seek_time) { - pipeline_->Resume(seek_time, base::Bind(&CallbackHelper::OnResume, - base::Unretained(&callbacks_))); + pipeline_->Resume( + std::move(scoped_renderer_), seek_time, + base::Bind(&CallbackHelper::OnResume, base::Unretained(&callbacks_))); base::RunLoop().RunUntilIdle(); } @@ -425,7 +418,7 @@ PostStartStatus::kSuspended); ASSERT_TRUE(pipeline_->IsSuspended()); - ResetRenderer(); + CreateRenderer(); base::TimeDelta expected = base::TimeDelta::FromSeconds(2000); ExpectResume(expected); DoResume(expected); @@ -444,7 +437,7 @@ PostStartStatus::kSuspended); ASSERT_TRUE(pipeline_->IsSuspended()); - ResetRenderer(); + CreateRenderer(); base::TimeDelta expected = base::TimeDelta::FromSeconds(2000); ExpectResume(expected); DoResume(expected); @@ -907,7 +900,7 @@ base::RunLoop().RunUntilIdle(); - ResetRenderer(); + CreateRenderer(); SetDemuxerExpectations(&streams); SetRendererExpectations(); StartPipelineAndExpect(PIPELINE_OK);
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 11e2df6..72cc3560 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -338,11 +338,10 @@ weak_this_ = weak_factory_.GetWeakPtr(); pipeline_controller_ = std::make_unique<PipelineController>( - std::make_unique<PipelineImpl>( - media_task_runner_, main_task_runner_, - BindToCurrentLoop(base::BindRepeating( - &WebMediaPlayerImpl::CreateRenderer, weak_this_)), - media_log_.get()), + std::make_unique<PipelineImpl>(media_task_runner_, main_task_runner_, + media_log_.get()), + base::BindRepeating(&WebMediaPlayerImpl::CreateRenderer, + base::Unretained(this)), base::BindRepeating(&WebMediaPlayerImpl::OnPipelineSeeked, weak_this_), base::BindRepeating(&WebMediaPlayerImpl::OnPipelineSuspended, weak_this_), base::BindRepeating(&WebMediaPlayerImpl::OnBeforePipelineResume, @@ -1721,7 +1720,7 @@ } void WebMediaPlayerImpl::OnError(PipelineStatus status) { - DVLOG(1) << __func__ << ": status=" << status; + DVLOG(1) << __func__; DCHECK(main_task_runner_->BelongsToCurrentThread()); DCHECK_NE(status, PIPELINE_OK); @@ -2615,7 +2614,7 @@ } } -void WebMediaPlayerImpl::CreateRenderer(RendererCreatedCB renderer_created_cb) { +std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() { DCHECK(main_task_runner_->BelongsToCurrentThread()); // Make sure that overlays are enabled if they're always allowed. @@ -2628,14 +2627,9 @@ base::Bind(&WebMediaPlayerImpl::OnOverlayInfoRequested, weak_this_)); #endif reported_renderer_type_ = renderer_factory_selector_->GetCurrentFactoryType(); - - auto renderer = - renderer_factory_selector_->GetCurrentFactory()->CreateRenderer( - media_task_runner_, worker_task_runner_, audio_source_provider_.get(), - compositor_.get(), request_overlay_info_cb, - client_->TargetColorSpace()); - - std::move(renderer_created_cb).Run(std::move(renderer)); + return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer( + media_task_runner_, worker_task_runner_, audio_source_provider_.get(), + compositor_.get(), request_overlay_info_cb, client_->TargetColorSpace()); } void WebMediaPlayerImpl::StartPipeline() {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 6e347ea..e82a9b6 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -377,7 +377,7 @@ const ProvideOverlayInfoCB& provide_overlay_info_cb); // Creates a Renderer via the |renderer_factory_selector_|. - void CreateRenderer(RendererCreatedCB renderer_created_cb); + std::unique_ptr<Renderer> CreateRenderer(); // Finishes starting the pipeline due to a call to load(). void StartPipeline();
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc index 76361ac..9f16754 100644 --- a/media/blink/webmediaplayer_impl_unittest.cc +++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -1588,12 +1588,16 @@ // To avoid PreloadMetadataLazyLoad. wmpi_->SetPreload(blink::WebMediaPlayer::kPreloadAuto); - EXPECT_CALL(encrypted_client_, DidBlockPlaybackWaitingForKey()); - EXPECT_CALL(encrypted_client_, DidResumePlaybackBlockedForKey()); - EXPECT_CALL(encrypted_client_, - Encrypted(EmeInitDataType::WEBM, NotNull(), Gt(0u))); - LoadAndWaitForReadyState(kEncryptedVideoOnlyTestFile, - blink::WebMediaPlayer::kReadyStateHaveMetadata); + { + base::RunLoop run_loop; + EXPECT_CALL(encrypted_client_, + Encrypted(EmeInitDataType::WEBM, NotNull(), Gt(0u))); + EXPECT_CALL(encrypted_client_, DidBlockPlaybackWaitingForKey()); + EXPECT_CALL(encrypted_client_, DidResumePlaybackBlockedForKey()) + .WillRepeatedly(RunClosure(run_loop.QuitClosure())); + Load(kEncryptedVideoOnlyTestFile); + run_loop.Run(); + } CreateCdm(); @@ -1603,15 +1607,18 @@ .WillRepeatedly(Return(nullptr)); mock_cdm_context_.set_cdm_id(CdmContext::kInvalidCdmId); - // Wait for kNetworkStateFormatError caused by Renderer initialization error. - base::RunLoop run_loop; - EXPECT_CALL(client_, NetworkStateChanged()).WillOnce(Invoke([&] { - if (wmpi_->GetNetworkState() == - blink::WebMediaPlayer::kNetworkStateFormatError) - run_loop.QuitClosure().Run(); - })); - SetCdm(); - run_loop.Run(); + { + // Wait for kNetworkStateFormatError caused by Renderer initialization + // error. + base::RunLoop run_loop; + EXPECT_CALL(client_, NetworkStateChanged()).WillOnce(Invoke([&] { + if (wmpi_->GetNetworkState() == + blink::WebMediaPlayer::kNetworkStateFormatError) + run_loop.QuitClosure().Run(); + })); + SetCdm(); + run_loop.Run(); + } } TEST_F(WebMediaPlayerImplTest, Waiting_NoDecryptionKey) {
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc index 377977d4..870ef425 100644 --- a/media/filters/fuchsia/fuchsia_video_decoder.cc +++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -315,6 +315,11 @@ } FuchsiaVideoDecoder::~FuchsiaVideoDecoder() { + // Call ReleaseInputBuffers() to make sure the corresponding fields are + // destroyed in the right order. + ReleaseInputBuffers(); + + // Release mailboxes used for output frames. ReleaseOutputBuffers(); }
diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc index 87401c6..6df6e416e 100644 --- a/media/filters/pipeline_controller.cc +++ b/media/filters/pipeline_controller.cc
@@ -11,18 +11,21 @@ PipelineController::PipelineController( std::unique_ptr<Pipeline> pipeline, + const RendererFactoryCB& renderer_factory_cb, const SeekedCB& seeked_cb, const SuspendedCB& suspended_cb, const BeforeResumeCB& before_resume_cb, const ResumedCB& resumed_cb, const PipelineStatusCB& error_cb) : pipeline_(std::move(pipeline)), + renderer_factory_cb_(renderer_factory_cb), seeked_cb_(seeked_cb), suspended_cb_(suspended_cb), before_resume_cb_(before_resume_cb), resumed_cb_(resumed_cb), error_cb_(error_cb) { DCHECK(pipeline_); + DCHECK(renderer_factory_cb_); DCHECK(seeked_cb_); DCHECK(suspended_cb_); DCHECK(before_resume_cb_); @@ -52,7 +55,7 @@ demuxer_ = demuxer; is_streaming_ = is_streaming; is_static_ = is_static; - pipeline_->Start(start_type, demuxer, client, + pipeline_->Start(start_type, demuxer, renderer_factory_cb_.Run(), client, base::Bind(&PipelineController::OnPipelineStatus, weak_factory_.GetWeakPtr(), start_type == Pipeline::StartType::kNormal @@ -254,7 +257,7 @@ pending_resume_ = false; state_ = State::RESUMING; before_resume_cb_.Run(); - pipeline_->Resume(seek_time_, + pipeline_->Resume(renderer_factory_cb_.Run(), seek_time_, base::Bind(&PipelineController::OnPipelineStatus, weak_factory_.GetWeakPtr(), State::PLAYING)); return;
diff --git a/media/filters/pipeline_controller.h b/media/filters/pipeline_controller.h index ff4fbd1..6aad7e3 100644 --- a/media/filters/pipeline_controller.h +++ b/media/filters/pipeline_controller.h
@@ -41,6 +41,7 @@ RESUMING, }; + using RendererFactoryCB = base::Callback<std::unique_ptr<Renderer>(void)>; using SeekedCB = base::Callback<void(bool time_updated)>; using SuspendedCB = base::Callback<void()>; using BeforeResumeCB = base::Callback<void()>; @@ -48,13 +49,16 @@ // Construct a PipelineController wrapping |pipeline_|. // The callbacks are: - // - |seeked_cb| is called upon reaching a stable state if a seek occurred. + // - |renderer_factory_cb| is called by PipelineController to create new + // renderers when starting and resuming. + // - |seeked_cb| is called upon reaching a stable state if a seek occured. // - |suspended_cb| is called immediately after suspending. // - |before_resume_cb| is called immediately before resuming. // - |resumed_cb| is called immediately after resuming. // - |error_cb| is called if any operation on |pipeline_| does not result // in PIPELINE_OK or its error callback is called. PipelineController(std::unique_ptr<Pipeline> pipeline, + const RendererFactoryCB& renderer_factory_cb, const SeekedCB& seeked_cb, const SuspendedCB& suspended_cb, const BeforeResumeCB& before_resume_cb, @@ -155,6 +159,9 @@ // The Pipeline we are managing state for. std::unique_ptr<Pipeline> pipeline_; + // Factory for Renderers, used for Start() and Resume(). + RendererFactoryCB renderer_factory_cb_; + // Called after seeks (which includes Start()) upon reaching a stable state. // Multiple seeks result in only one callback if no stable state occurs // between them.
diff --git a/media/filters/pipeline_controller_unittest.cc b/media/filters/pipeline_controller_unittest.cc index d30b0fa..a0137a8 100644 --- a/media/filters/pipeline_controller_unittest.cc +++ b/media/filters/pipeline_controller_unittest.cc
@@ -37,6 +37,8 @@ PipelineControllerTest() : pipeline_(new StrictMock<MockPipeline>()), pipeline_controller_(std::unique_ptr<Pipeline>(pipeline_), + base::Bind(&PipelineControllerTest::CreateRenderer, + base::Unretained(this)), base::Bind(&PipelineControllerTest::OnSeeked, base::Unretained(this)), base::Bind(&PipelineControllerTest::OnSuspended, @@ -53,7 +55,8 @@ PipelineStatusCB StartPipeline(bool is_streaming, bool is_static) { EXPECT_FALSE(pipeline_controller_.IsStable()); PipelineStatusCB start_cb; - EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb)); + EXPECT_CALL(*pipeline_, Start(_, _, _, _, _)) + .WillOnce(SaveArg<4>(&start_cb)); pipeline_controller_.Start(Pipeline::StartType::kNormal, &demuxer_, this, is_streaming, is_static); Mock::VerifyAndClear(pipeline_); @@ -102,9 +105,9 @@ PipelineStatusCB ResumePipeline() { EXPECT_TRUE(pipeline_controller_.IsPipelineSuspended()); PipelineStatusCB resume_cb; - EXPECT_CALL(*pipeline_, Resume(_, _)) + EXPECT_CALL(*pipeline_, Resume(_, _, _)) .WillOnce( - DoAll(SaveArg<0>(&last_resume_time_), SaveArg<1>(&resume_cb))); + DoAll(SaveArg<1>(&last_resume_time_), SaveArg<2>(&resume_cb))); EXPECT_CALL(*pipeline_, GetMediaTime()) .WillRepeatedly(Return(base::TimeDelta())); pipeline_controller_.Resume(); @@ -124,6 +127,10 @@ } protected: + std::unique_ptr<Renderer> CreateRenderer() { + return std::unique_ptr<Renderer>(); + } + void OnSeeked(bool time_updated) { was_seeked_ = true; last_seeked_time_updated_ = time_updated; @@ -181,7 +188,7 @@ TEST_F(PipelineControllerTest, StartSuspendedSeekAndResume) { EXPECT_FALSE(pipeline_controller_.IsStable()); PipelineStatusCB start_cb; - EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb)); + EXPECT_CALL(*pipeline_, Start(_, _, _, _, _)).WillOnce(SaveArg<4>(&start_cb)); pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata, &demuxer_, this, false, true); Mock::VerifyAndClear(pipeline_); @@ -194,7 +201,8 @@ EXPECT_FALSE(was_seeked_); PipelineStatusCB resume_cb; - EXPECT_CALL(*pipeline_, Resume(_, _)).WillOnce(DoAll(SaveArg<1>(&resume_cb))); + EXPECT_CALL(*pipeline_, Resume(_, _, _)) + .WillOnce(DoAll(SaveArg<2>(&resume_cb))); EXPECT_CALL(*pipeline_, GetMediaTime()) .WillRepeatedly(Return(base::TimeDelta())); @@ -221,7 +229,7 @@ TEST_F(PipelineControllerTest, StartSuspendedAndResume) { EXPECT_FALSE(pipeline_controller_.IsStable()); PipelineStatusCB start_cb; - EXPECT_CALL(*pipeline_, Start(_, _, _, _)).WillOnce(SaveArg<3>(&start_cb)); + EXPECT_CALL(*pipeline_, Start(_, _, _, _, _)).WillOnce(SaveArg<4>(&start_cb)); pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata, &demuxer_, this, false, true); Mock::VerifyAndClear(pipeline_);
diff --git a/media/remoting/integration_test.cc b/media/remoting/integration_test.cc index c24e9e8..6086d81 100644 --- a/media/remoting/integration_test.cc +++ b/media/remoting/integration_test.cc
@@ -24,9 +24,13 @@ ~TestRendererFactory() override = default; // PipelineTestRendererFactory implementation. - std::unique_ptr<Renderer> CreateRenderer() override { - return std::make_unique<End2EndTestRenderer>( - default_renderer_factory_->CreateRenderer()); + std::unique_ptr<Renderer> CreateRenderer( + CreateVideoDecodersCB prepend_video_decoders_cb, + CreateAudioDecodersCB prepend_audio_decoders_cb) override { + std::unique_ptr<Renderer> renderer_impl = + default_renderer_factory_->CreateRenderer(prepend_video_decoders_cb, + prepend_audio_decoders_cb); + return std::make_unique<End2EndTestRenderer>(std::move(renderer_impl)); } private:
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc index f68852bb..1392657 100644 --- a/media/test/pipeline_integration_test_base.cc +++ b/media/test/pipeline_integration_test_base.cc
@@ -114,8 +114,11 @@ ~RendererFactoryImpl() override = default; // PipelineTestRendererFactory implementation. - std::unique_ptr<Renderer> CreateRenderer() override { - return integration_test_->CreateRenderer(); + std::unique_ptr<Renderer> CreateRenderer( + CreateVideoDecodersCB prepend_video_decoders_cb, + CreateAudioDecodersCB prepend_audio_decoders_cb) override { + return integration_test_->CreateRenderer(prepend_video_decoders_cb, + prepend_audio_decoders_cb); } private: @@ -130,18 +133,14 @@ webaudio_attached_(false), mono_output_(false), fuzzing_(false), + pipeline_(new PipelineImpl(task_environment_.GetMainThreadTaskRunner(), + task_environment_.GetMainThreadTaskRunner(), + &media_log_)), ended_(false), pipeline_status_(PIPELINE_OK), last_video_frame_format_(PIXEL_FORMAT_UNKNOWN), current_duration_(kInfiniteDuration), renderer_factory_(new RendererFactoryImpl(this)) { - pipeline_ = std::make_unique<PipelineImpl>( - task_environment_.GetMainThreadTaskRunner(), - task_environment_.GetMainThreadTaskRunner(), - base::BindRepeating(&PipelineIntegrationTestBase::CreateRendererAsync, - base::Unretained(this)), - &media_log_); - ResetVideoHash(); EXPECT_CALL(*this, OnVideoAverageKeyframeDistanceUpdate()).Times(AnyNumber()); } @@ -248,9 +247,6 @@ uint8_t test_type, CreateVideoDecodersCB prepend_video_decoders_cb, CreateAudioDecodersCB prepend_audio_decoders_cb) { - prepend_video_decoders_cb_ = std::move(prepend_video_decoders_cb); - prepend_audio_decoders_cb_ = std::move(prepend_audio_decoders_cb); - ParseTestTypeFlags(test_type); EXPECT_CALL(*this, OnMetadata(_)) @@ -297,7 +293,10 @@ EXPECT_CALL(*this, OnVideoConfigChange(_)).Times(AnyNumber()); base::RunLoop run_loop; - pipeline_->Start(Pipeline::StartType::kNormal, demuxer_.get(), this, + pipeline_->Start(Pipeline::StartType::kNormal, demuxer_.get(), + renderer_factory_->CreateRenderer(prepend_video_decoders_cb, + prepend_audio_decoders_cb), + this, base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, base::Unretained(this), run_loop.QuitClosure())); RunUntilQuitOrEndedOrError(&run_loop); @@ -387,7 +386,9 @@ base::RunLoop run_loop; EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH, _)) .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); - pipeline_->Resume(seek_time, + pipeline_->Resume(renderer_factory_->CreateRenderer(CreateVideoDecodersCB(), + CreateAudioDecodersCB()), + seek_time, base::Bind(&PipelineIntegrationTestBase::OnSeeked, base::Unretained(this), seek_time)); RunUntilQuitOrError(&run_loop); @@ -456,7 +457,9 @@ #endif } -std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer() { +std::unique_ptr<Renderer> PipelineIntegrationTestBase::CreateRenderer( + CreateVideoDecodersCB prepend_video_decoders_cb, + CreateAudioDecodersCB prepend_audio_decoders_cb) { // Simulate a 60Hz rendering sink. video_sink_.reset(new NullVideoSink( clockless_playback_, base::TimeDelta::FromSecondsD(1.0 / 60), @@ -468,7 +471,7 @@ std::unique_ptr<VideoRenderer> video_renderer(new VideoRendererImpl( task_environment_.GetMainThreadTaskRunner(), video_sink_.get(), base::Bind(&CreateVideoDecodersForTest, &media_log_, - prepend_video_decoders_cb_), + prepend_video_decoders_cb), false, &media_log_, nullptr)); if (!clockless_playback_) { @@ -501,7 +504,7 @@ : audio_sink_.get(), base::Bind(&CreateAudioDecodersForTest, &media_log_, task_environment_.GetMainThreadTaskRunner(), - prepend_audio_decoders_cb_), + prepend_audio_decoders_cb), &media_log_)); if (hashing_enabled_) { if (clockless_playback_) @@ -527,11 +530,6 @@ return std::move(renderer_impl); } -void PipelineIntegrationTestBase::CreateRendererAsync( - RendererCreatedCB renderer_created_cb) { - std::move(renderer_created_cb).Run(CreateRenderer()); -} - void PipelineIntegrationTestBase::OnVideoFramePaint( scoped_refptr<VideoFrame> frame) { last_video_frame_format_ = frame->format(); @@ -642,7 +640,10 @@ EXPECT_CALL(*this, OnWaiting(WaitingReason::kNoDecryptionKey)).Times(0); } - pipeline_->Start(Pipeline::StartType::kNormal, demuxer_.get(), this, + pipeline_->Start(Pipeline::StartType::kNormal, demuxer_.get(), + renderer_factory_->CreateRenderer(CreateVideoDecodersCB(), + CreateAudioDecodersCB()), + this, base::Bind(&PipelineIntegrationTestBase::OnStatusCallback, base::Unretained(this), run_loop.QuitClosure()));
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h index 5f1c6089..f517a0b 100644 --- a/media/test/pipeline_integration_test_base.h +++ b/media/test/pipeline_integration_test_base.h
@@ -45,10 +45,11 @@ class PipelineTestRendererFactory { public: - virtual ~PipelineTestRendererFactory() = default; - + virtual ~PipelineTestRendererFactory() {} // Creates and returns a Renderer. - virtual std::unique_ptr<Renderer> CreateRenderer() = 0; + virtual std::unique_ptr<Renderer> CreateRenderer( + CreateVideoDecodersCB prepend_video_decoders_cb, + CreateAudioDecodersCB prepend_audio_decoders_cb) = 0; }; // Integration tests for Pipeline. Real demuxers, real decoders, and @@ -144,8 +145,9 @@ audio_play_delay_cb_ = std::move(cb); } - std::unique_ptr<Renderer> CreateRenderer(); - void CreateRendererAsync(RendererCreatedCB renderer_created_cb); + std::unique_ptr<Renderer> CreateRenderer( + CreateVideoDecodersCB prepend_video_decoders_cb, + CreateAudioDecodersCB prepend_audio_decoders_cb); protected: NiceMock<MockMediaLog> media_log_; @@ -255,9 +257,6 @@ // RunUntilQuitOrError() on it. void RunUntilQuitOrEndedOrError(base::RunLoop* run_loop); - CreateVideoDecodersCB prepend_video_decoders_cb_; - CreateAudioDecodersCB prepend_audio_decoders_cb_; - base::OnceClosure on_ended_closure_; base::OnceClosure on_error_closure_;
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 077292b2..a2a6ca58 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -67,9 +67,11 @@ : public HostResolver::ResolveHostRequest { public: RequestImpl(const HostPortPair& request_host, + const NetworkIsolationKey& network_isolation_key, const base::Optional<ResolveHostParameters>& optional_parameters, base::WeakPtr<MockHostResolverBase> resolver) : request_host_(request_host), + network_isolation_key_(network_isolation_key), parameters_(optional_parameters ? optional_parameters.value() : ResolveHostParameters()), priority_(parameters_.initial_priority), @@ -177,6 +179,10 @@ const HostPortPair& request_host() const { return request_host_; } + const NetworkIsolationKey& network_isolation_key() const { + return network_isolation_key_; + } + const ResolveHostParameters& parameters() const { return parameters_; } int host_resolver_flags() const { return host_resolver_flags_; } @@ -196,6 +202,7 @@ private: const HostPortPair request_host_; + const NetworkIsolationKey network_isolation_key_; const ResolveHostParameters parameters_; RequestPriority priority_; int host_resolver_flags_; @@ -306,7 +313,8 @@ const NetworkIsolationKey& network_isolation_key, const NetLogWithSource& source_net_log, const base::Optional<ResolveHostParameters>& optional_parameters) { - return std::make_unique<RequestImpl>(host, optional_parameters, AsWeakPtr()); + return std::make_unique<RequestImpl>(host, network_isolation_key, + optional_parameters, AsWeakPtr()); } std::unique_ptr<HostResolver::MdnsListener> @@ -321,6 +329,7 @@ int MockHostResolverBase::LoadIntoCache( const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, const base::Optional<ResolveHostParameters>& optional_parameters) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(cache_); @@ -331,7 +340,7 @@ AddressList addresses; base::Optional<HostCache::EntryStaleness> stale_info; int rv = ResolveFromIPLiteralOrCache( - host, parameters.dns_query_type, + host, network_isolation_key, parameters.dns_query_type, ParametersToHostResolverFlags(parameters), parameters.source, parameters.cache_usage, &addresses, &stale_info); if (rv != ERR_DNS_CACHE_MISS) { @@ -344,9 +353,10 @@ if (!IsValidDNSDomain(host.host())) return ERR_NAME_NOT_RESOLVED; - return ResolveProc( - host, DnsQueryTypeToAddressFamily(parameters.dns_query_type), - ParametersToHostResolverFlags(parameters), parameters.source, &addresses); + return ResolveProc(host, network_isolation_key, + DnsQueryTypeToAddressFamily(parameters.dns_query_type), + ParametersToHostResolverFlags(parameters), + parameters.source, &addresses); } void MockHostResolverBase::ResolveAllPending() { @@ -375,7 +385,7 @@ AddressList addresses; int error = ResolveProc( - req->request_host(), + req->request_host(), req->network_isolation_key(), DnsQueryTypeToAddressFamily(req->parameters().dns_query_type), req->host_resolver_flags(), req->parameters().source, &addresses); if (error == OK && !req->parameters().is_speculative) @@ -400,6 +410,12 @@ return request(id)->priority(); } +const NetworkIsolationKey& MockHostResolverBase::request_network_isolation_key( + size_t id) { + DCHECK(request(id)); + return request(id)->network_isolation_key(); +} + void MockHostResolverBase::ResolveOnlyRequestNow() { DCHECK_EQ(1u, requests_.size()); ResolveNow(requests_.begin()->first); @@ -483,9 +499,10 @@ AddressList addresses; base::Optional<HostCache::EntryStaleness> stale_info; int rv = ResolveFromIPLiteralOrCache( - request->request_host(), request->parameters().dns_query_type, - request->host_resolver_flags(), request->parameters().source, - request->parameters().cache_usage, &addresses, &stale_info); + request->request_host(), request->network_isolation_key(), + request->parameters().dns_query_type, request->host_resolver_flags(), + request->parameters().source, request->parameters().cache_usage, + &addresses, &stale_info); if (rv == OK && !request->parameters().is_speculative) request->set_address_results(addresses, std::move(stale_info)); if (rv != ERR_DNS_CACHE_MISS || @@ -500,7 +517,7 @@ if (synchronous_mode_) { int rv = ResolveProc( - request->request_host(), + request->request_host(), request->network_isolation_key(), DnsQueryTypeToAddressFamily(request->parameters().dns_query_type), request->host_resolver_flags(), request->parameters().source, &addresses); @@ -525,6 +542,7 @@ int MockHostResolverBase::ResolveFromIPLiteralOrCache( const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, DnsQueryType dns_query_type, HostResolverFlags flags, HostResolverSource source, @@ -559,7 +577,8 @@ HostResolverSource effective_source = source == HostResolverSource::LOCAL_ONLY ? HostResolverSource::ANY : source; - HostCache::Key key(host.host(), dns_query_type, flags, effective_source); + HostCache::Key key(host.host(), dns_query_type, flags, effective_source, + network_isolation_key); const std::pair<const HostCache::Key, HostCache::Entry>* cache_result; HostCache::EntryStaleness stale_info = HostCache::kNotStale; if (cache_usage == @@ -594,11 +613,13 @@ return rv; } -int MockHostResolverBase::ResolveProc(const HostPortPair& host, - AddressFamily requested_address_family, - HostResolverFlags flags, - HostResolverSource source, - AddressList* addresses) { +int MockHostResolverBase::ResolveProc( + const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, + AddressFamily requested_address_family, + HostResolverFlags flags, + HostResolverSource source, + AddressList* addresses) { DCHECK(rules_map_.find(source) != rules_map_.end()); ++num_non_local_resolves_;
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index 1851b24..41c93e5 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -130,6 +130,7 @@ // with the given parameters. Returns the net error of the cached result. int LoadIntoCache( const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, const base::Optional<ResolveHostParameters>& optional_parameters); // Returns true if there are pending requests that can be resolved by invoking @@ -162,7 +163,7 @@ RequestPriority request_priority(size_t id); // Returns NetworkIsolationKey of the request with the given id. - const NetworkIsolationKey& network_isolation_key(size_t id); + const NetworkIsolationKey& request_network_isolation_key(size_t id); // Like ResolveNow, but doesn't take an ID. DCHECKs if there's more than one // pending request. @@ -234,6 +235,7 @@ // DNS_CACHE_MISS if failed. int ResolveFromIPLiteralOrCache( const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, DnsQueryType dns_query_type, HostResolverFlags flags, HostResolverSource source, @@ -242,6 +244,7 @@ base::Optional<HostCache::EntryStaleness>* stale_info); // Resolve via |proc_|. int ResolveProc(const HostPortPair& host, + const NetworkIsolationKey& network_isolation_key, AddressFamily requested_address_family, HostResolverFlags flags, HostResolverSource source,
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index a648f73..8e96e2b 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -16570,7 +16570,8 @@ // Preload mail.example.com into HostCache. rv = session_deps_.host_resolver->LoadIntoCache( - HostPortPair("mail.example.com", 443), base::nullopt); + HostPortPair("mail.example.com", 443), NetworkIsolationKey(), + base::nullopt); EXPECT_THAT(rv, IsOk()); HttpRequestInfo request2; @@ -16742,7 +16743,8 @@ // Preload mail.example.org into HostCache. int rv = session_deps_.host_resolver->LoadIntoCache( - HostPortPair("mail.example.com", 443), base::nullopt); + HostPortPair("mail.example.com", 443), NetworkIsolationKey(), + base::nullopt); EXPECT_THAT(rv, IsOk()); HttpRequestInfo request1; @@ -16867,7 +16869,8 @@ // Preload mail.example.org into HostCache. int rv = session_deps_.host_resolver->LoadIntoCache( - HostPortPair("mail.example.com", 443), base::nullopt); + HostPortPair("mail.example.com", 443), NetworkIsolationKey(), + base::nullopt); EXPECT_THAT(rv, IsOk()); HttpRequestInfo request1; @@ -16981,7 +16984,8 @@ // Preload cache entries into HostCache. rv = session_deps_.host_resolver->LoadIntoCache( - HostPortPair("mail.example.com", 443), base::nullopt); + HostPortPair("mail.example.com", 443), NetworkIsolationKey(), + base::nullopt); EXPECT_THAT(rv, IsOk()); HttpRequestInfo request2; @@ -20184,7 +20188,8 @@ // Preload mail.example.org into HostCache. int rv = session_deps_.host_resolver->LoadIntoCache( - HostPortPair("mail.example.com", 443), base::nullopt); + HostPortPair("mail.example.com", 443), NetworkIsolationKey(), + base::nullopt); EXPECT_THAT(rv, IsOk()); HttpRequestInfo request1;
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index ec441b7..9822950 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -109,8 +109,8 @@ if (GetParam() != HTTP) return nullptr; return base::MakeRefCounted<TransportSocketParams>( - HostPortPair(kHttpProxyHost, 80), disable_secure_dns, - OnHostResolutionCallback()); + HostPortPair(kHttpProxyHost, 80), NetworkIsolationKey(), + disable_secure_dns, OnHostResolutionCallback()); } scoped_refptr<SSLSocketParams> CreateHttpsProxyParams( @@ -119,8 +119,8 @@ return nullptr; return base::MakeRefCounted<SSLSocketParams>( base::MakeRefCounted<TransportSocketParams>( - HostPortPair(kHttpsProxyHost, 443), disable_secure_dns, - OnHostResolutionCallback()), + HostPortPair(kHttpsProxyHost, 443), NetworkIsolationKey(), + disable_secure_dns, OnHostResolutionCallback()), nullptr, nullptr, HostPortPair(kHttpsProxyHost, 443), SSLConfig(), PRIVACY_MODE_DISABLED, NetworkIsolationKey()); } @@ -886,8 +886,8 @@ TestConnectJobDelegate test_delegate; auto ssl_params = base::MakeRefCounted<SSLSocketParams>( base::MakeRefCounted<TransportSocketParams>( - HostPortPair(kHttpsProxyHost, 443), true /* disable_secure_dns */, - OnHostResolutionCallback()), + HostPortPair(kHttpsProxyHost, 443), NetworkIsolationKey(), + true /* disable_secure_dns */, OnHostResolutionCallback()), nullptr, nullptr, HostPortPair(kHttpsProxyHost, 443), SSLConfig(), PRIVACY_MODE_DISABLED, NetworkIsolationKey()); auto http_proxy_params = base::MakeRefCounted<HttpProxySocketParams>(
diff --git a/net/nqe/network_quality_estimator_util_unittest.cc b/net/nqe/network_quality_estimator_util_unittest.cc index 014f4a6..1b2265c 100644 --- a/net/nqe/network_quality_estimator_util_unittest.cc +++ b/net/nqe/network_quality_estimator_util_unittest.cc
@@ -10,6 +10,7 @@ #include "base/test/task_environment.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" +#include "net/base/network_isolation_key.h" #include "net/base/test_completion_callback.h" #include "net/dns/context_host_resolver.h" #include "net/dns/host_resolver.h" @@ -49,11 +50,11 @@ EXPECT_EQ(0u, mock_host_resolver.num_resolve()); // Load hostnames into HostResolver cache. - int rv = mock_host_resolver.LoadIntoCache(HostPortPair("example1.com", 443), - base::nullopt); + int rv = mock_host_resolver.LoadIntoCache( + HostPortPair("example1.com", 443), NetworkIsolationKey(), base::nullopt); EXPECT_EQ(OK, rv); rv = mock_host_resolver.LoadIntoCache(HostPortPair("example2.com", 443), - base::nullopt); + NetworkIsolationKey(), base::nullopt); EXPECT_EQ(OK, rv); EXPECT_EQ(2u, mock_host_resolver.num_non_local_resolves()); @@ -99,8 +100,8 @@ IsPrivateHost(&mock_host_resolver, HostPortPair("example3.com", 443))); EXPECT_EQ(0u, mock_host_resolver.num_non_local_resolves()); - int rv = mock_host_resolver.LoadIntoCache(HostPortPair("example3.com", 443), - base::nullopt); + int rv = mock_host_resolver.LoadIntoCache( + HostPortPair("example3.com", 443), NetworkIsolationKey(), base::nullopt); EXPECT_EQ(OK, rv); EXPECT_EQ(1u, mock_host_resolver.num_non_local_resolves());
diff --git a/net/socket/connect_job.cc b/net/socket/connect_job.cc index 7aad80e89..a4098c3 100644 --- a/net/socket/connect_job.cc +++ b/net/socket/connect_job.cc
@@ -115,8 +115,13 @@ scoped_refptr<SOCKSSocketParams> socks_params; if (!proxy_server.is_direct()) { + // No need to use a NetworkIsolationKey for looking up the proxy's IP + // address. Cached proxy IP addresses doesn't really expose useful + // information to destination sites, and not caching them has a performance + // cost. auto proxy_tcp_params = base::MakeRefCounted<TransportSocketParams>( - proxy_server.host_port_pair(), disable_secure_dns, resolution_callback); + proxy_server.host_port_pair(), NetworkIsolationKey(), + disable_secure_dns, resolution_callback); if (proxy_server.is_http() || proxy_server.is_https() || proxy_server.is_quic()) { @@ -151,7 +156,8 @@ scoped_refptr<TransportSocketParams> ssl_tcp_params; if (proxy_server.is_direct()) { ssl_tcp_params = base::MakeRefCounted<TransportSocketParams>( - endpoint, disable_secure_dns, resolution_callback); + endpoint, network_isolation_key, disable_secure_dns, + resolution_callback); } auto ssl_params = base::MakeRefCounted<SSLSocketParams>( std::move(ssl_tcp_params), std::move(socks_params), @@ -176,7 +182,7 @@ DCHECK(proxy_server.is_direct()); auto tcp_params = base::MakeRefCounted<TransportSocketParams>( - endpoint, disable_secure_dns, resolution_callback); + endpoint, network_isolation_key, disable_secure_dns, resolution_callback); return TransportConnectJob::CreateTransportConnectJob( std::move(tcp_params), request_priority, socket_tag, common_connect_job_params, delegate, nullptr /* net_log */);
diff --git a/net/socket/socks_connect_job_unittest.cc b/net/socket/socks_connect_job_unittest.cc index 7ad2fc2..474114c 100644 --- a/net/socket/socks_connect_job_unittest.cc +++ b/net/socket/socks_connect_job_unittest.cc
@@ -69,8 +69,8 @@ bool disable_secure_dns = false) { return base::MakeRefCounted<SOCKSSocketParams>( base::MakeRefCounted<TransportSocketParams>( - HostPortPair(kProxyHostName, kProxyPort), disable_secure_dns, - OnHostResolutionCallback()), + HostPortPair(kProxyHostName, kProxyPort), NetworkIsolationKey(), + disable_secure_dns, OnHostResolutionCallback()), socks_version == SOCKSVersion::V5, socks_version == SOCKSVersion::V4 ? HostPortPair(kSOCKS4TestHost, kSOCKS4TestPort)
diff --git a/net/socket/ssl_connect_job_unittest.cc b/net/socket/ssl_connect_job_unittest.cc index 3f2b444..baf32b6 100644 --- a/net/socket/ssl_connect_job_unittest.cc +++ b/net/socket/ssl_connect_job_unittest.cc
@@ -83,10 +83,12 @@ session_(CreateNetworkSession()), direct_transport_socket_params_( new TransportSocketParams(HostPortPair("host", 443), + NetworkIsolationKey(), false /* disable_secure_dns */, OnHostResolutionCallback())), proxy_transport_socket_params_( new TransportSocketParams(HostPortPair("proxy", 443), + NetworkIsolationKey(), false /* disable_secure_dns */, OnHostResolutionCallback())), socks_socket_params_( @@ -416,9 +418,9 @@ for (bool disable_secure_dns : {false, true}) { TestConnectJobDelegate test_delegate; direct_transport_socket_params_ = - base::MakeRefCounted<TransportSocketParams>(HostPortPair("host", 443), - disable_secure_dns, - OnHostResolutionCallback()); + base::MakeRefCounted<TransportSocketParams>( + HostPortPair("host", 443), NetworkIsolationKey(), + disable_secure_dns, OnHostResolutionCallback()); auto common_connect_job_params = session_->CreateCommonConnectJobParams(); std::unique_ptr<ConnectJob> ssl_connect_job = std::make_unique<SSLConnectJob>(DEFAULT_PRIORITY, SocketTag(),
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 507ac4a8..7f20e8b7 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -52,6 +52,8 @@ #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" +#include "url/origin.h" using net::test::IsError; using net::test::IsOk; @@ -1610,6 +1612,209 @@ } } +TEST_F(TransportClientSocketPoolTest, NetworkIsolationKey) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + session_deps_.host_resolver->set_ondemand_mode(true); + + TransportClientSocketPool::GroupId group_id( + HostPortPair("bar.test", 80), ClientSocketPool::SocketType::kHttp, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + ClientSocketHandle handle; + TestCompletionCallback callback; + EXPECT_THAT( + handle.Init(group_id, + base::MakeRefCounted<ClientSocketPool::SocketParams>( + nullptr /* ssl_config_for_origin */, + nullptr /* ssl_config_for_proxy */), + TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), pool_.get(), + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, session_deps_.host_resolver->last_id()); + EXPECT_EQ(kNetworkIsolationKey, + session_deps_.host_resolver->request_network_isolation_key(1)); +} + +TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySsl) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + session_deps_.host_resolver->set_ondemand_mode(true); + + TransportClientSocketPool::GroupId group_id( + HostPortPair("bar.test", 443), ClientSocketPool::SocketType::kSsl, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + ClientSocketHandle handle; + TestCompletionCallback callback; + EXPECT_THAT( + handle.Init(group_id, + base::MakeRefCounted<ClientSocketPool::SocketParams>( + std::make_unique<SSLConfig>() /* ssl_config_for_origin */, + nullptr /* ssl_config_for_proxy */), + TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), pool_.get(), + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, session_deps_.host_resolver->last_id()); + EXPECT_EQ(kNetworkIsolationKey, + session_deps_.host_resolver->request_network_isolation_key(1)); +} + +// Test that, in the case of an HTTP proxy, the NetworkIsolationKey is not used. +TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpProxy) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + session_deps_.host_resolver->set_ondemand_mode(true); + + TransportClientSocketPool proxy_pool( + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + ProxyServer::FromURI("http://proxy.test", + ProxyServer::SCHEME_HTTP /* default_scheme */), + false /* is_for_websockets */, tagging_common_connect_job_params_.get()); + + TransportClientSocketPool::GroupId group_id( + HostPortPair("bar.test", 80), ClientSocketPool::SocketType::kHttp, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + ClientSocketHandle handle; + TestCompletionCallback callback; + EXPECT_THAT( + handle.Init(group_id, + base::MakeRefCounted<ClientSocketPool::SocketParams>( + nullptr /* ssl_config_for_origin */, + nullptr /* ssl_config_for_proxy */), + TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), &proxy_pool, + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, session_deps_.host_resolver->last_id()); + EXPECT_EQ(NetworkIsolationKey(), + session_deps_.host_resolver->request_network_isolation_key(1)); +} + +// Test that, in the case of an HTTPS proxy, the NetworkIsolationKey is not +// used. +TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpsProxy) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + session_deps_.host_resolver->set_ondemand_mode(true); + + TransportClientSocketPool proxy_pool( + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + ProxyServer::FromURI("https://proxy.test", + ProxyServer::SCHEME_HTTP /* default_scheme */), + false /* is_for_websockets */, tagging_common_connect_job_params_.get()); + + TransportClientSocketPool::GroupId group_id( + HostPortPair("bar.test", 80), ClientSocketPool::SocketType::kHttp, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + ClientSocketHandle handle; + TestCompletionCallback callback; + EXPECT_THAT( + handle.Init(group_id, + base::MakeRefCounted<ClientSocketPool::SocketParams>( + nullptr /* ssl_config_for_origin */, + std::make_unique<SSLConfig>() /* ssl_config_for_proxy */), + TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), &proxy_pool, + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, session_deps_.host_resolver->last_id()); + EXPECT_EQ(NetworkIsolationKey(), + session_deps_.host_resolver->request_network_isolation_key(1)); +} + +// Test that, in the case of a SOCKS5 proxy, the NetworkIsolationKey is not +// used. +TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks5Proxy) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + session_deps_.host_resolver->set_ondemand_mode(true); + + TransportClientSocketPool proxy_pool( + kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, + ProxyServer::FromURI("socks5://proxy.test", + ProxyServer::SCHEME_HTTP /* default_scheme */), + false /* is_for_websockets */, tagging_common_connect_job_params_.get()); + + TransportClientSocketPool::GroupId group_id( + HostPortPair("bar.test", 80), ClientSocketPool::SocketType::kHttp, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + ClientSocketHandle handle; + TestCompletionCallback callback; + EXPECT_THAT( + handle.Init(group_id, + base::MakeRefCounted<ClientSocketPool::SocketParams>( + nullptr /* ssl_config_for_origin */, + nullptr /* ssl_config_for_proxy */), + TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), &proxy_pool, + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, session_deps_.host_resolver->last_id()); + EXPECT_EQ(NetworkIsolationKey(), + session_deps_.host_resolver->request_network_isolation_key(1)); +} + // Test that SocketTag passed into TransportClientSocketPool is applied to // returned sockets. #if defined(OS_ANDROID)
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc index 4a734a799..23575474 100644 --- a/net/socket/transport_connect_job.cc +++ b/net/socket/transport_connect_job.cc
@@ -47,9 +47,11 @@ TransportSocketParams::TransportSocketParams( const HostPortPair& host_port_pair, + const NetworkIsolationKey& network_isolation_key, bool disable_secure_dns, const OnHostResolutionCallback& host_resolution_callback) : destination_(host_port_pair), + network_isolation_key_(network_isolation_key), disable_secure_dns_(disable_secure_dns), host_resolution_callback_(host_resolution_callback) {} @@ -263,8 +265,9 @@ parameters.initial_priority = priority(); if (params_->disable_secure_dns()) parameters.secure_dns_mode_override = DnsConfig::SecureDnsMode::OFF; - request_ = host_resolver()->CreateRequest(params_->destination(), net_log(), - parameters); + request_ = host_resolver()->CreateRequest(params_->destination(), + params_->network_isolation_key(), + net_log(), parameters); return request_->Start(base::BindOnce(&TransportConnectJob::OnIOComplete, base::Unretained(this)));
diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h index 0d02929..ad4804e 100644 --- a/net/socket/transport_connect_job.h +++ b/net/socket/transport_connect_job.h
@@ -16,6 +16,7 @@ #include "base/timer/timer.h" #include "net/base/host_port_pair.h" #include "net/base/net_export.h" +#include "net/base/network_isolation_key.h" #include "net/dns/host_resolver.h" #include "net/socket/connect_job.h" #include "net/socket/connection_attempts.h" @@ -30,14 +31,19 @@ : public base::RefCounted<TransportSocketParams> { public: // |host_resolution_callback| will be invoked after the the hostname is - // resolved. If |host_resolution_callback| does not return OK, then the + // resolved. |network_isolation_key| is passed to the HostResolver to prevent + // cross-NIK leaks. If |host_resolution_callback| does not return OK, then the // connection will be aborted with that value. TransportSocketParams( const HostPortPair& host_port_pair, + const NetworkIsolationKey& network_isolation_key, bool disable_secure_dns, const OnHostResolutionCallback& host_resolution_callback); const HostPortPair& destination() const { return destination_; } + const NetworkIsolationKey& network_isolation_key() const { + return network_isolation_key_; + } bool disable_secure_dns() const { return disable_secure_dns_; } const OnHostResolutionCallback& host_resolution_callback() const { return host_resolution_callback_; @@ -48,6 +54,7 @@ ~TransportSocketParams(); const HostPortPair destination_; + const NetworkIsolationKey network_isolation_key_; const bool disable_secure_dns_; const OnHostResolutionCallback host_resolution_callback_;
diff --git a/net/socket/transport_connect_job_unittest.cc b/net/socket/transport_connect_job_unittest.cc index 59a90e8..446a5f8 100644 --- a/net/socket/transport_connect_job_unittest.cc +++ b/net/socket/transport_connect_job_unittest.cc
@@ -56,8 +56,8 @@ static scoped_refptr<TransportSocketParams> DefaultParams() { return base::MakeRefCounted<TransportSocketParams>( - HostPortPair(kHostName, 80), false /* disable_secure_dns */, - OnHostResolutionCallback()); + HostPortPair(kHostName, 80), NetworkIsolationKey(), + false /* disable_secure_dns */, OnHostResolutionCallback()); } protected: @@ -262,9 +262,9 @@ TestConnectJobDelegate test_delegate; TransportConnectJob transport_connect_job( DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_, - base::MakeRefCounted<TransportSocketParams>(HostPortPair(kHostName, 80), - disable_secure_dns, - OnHostResolutionCallback()), + base::MakeRefCounted<TransportSocketParams>( + HostPortPair(kHostName, 80), NetworkIsolationKey(), + disable_secure_dns, OnHostResolutionCallback()), &test_delegate, nullptr /* net_log */); test_delegate.StartJobExpectingResult(&transport_connect_job, OK, false /* expect_sync_result */);
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc index fc2c62e..ec578d4 100644 --- a/net/socket/websocket_transport_client_socket_pool_unittest.cc +++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -15,8 +15,10 @@ #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "net/base/features.h" #include "net/base/ip_endpoint.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" @@ -39,6 +41,8 @@ #include "net/test/test_with_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" +#include "url/origin.h" using net::test::IsError; using net::test::IsOk; @@ -1125,6 +1129,40 @@ request(2)->handle()->GetLoadState()); } +// Make sure that WebSocket requests use the correct NetworkIsolationKey. +TEST_F(WebSocketTransportClientSocketPoolTest, NetworkIsolationKey) { + const auto kOrigin = url::Origin::Create(GURL("https://foo.test/")); + const NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + // enabled_features + {features::kPartitionConnectionsByNetworkIsolationKey, + features::kSplitHostCacheByNetworkIsolationKey}, + // disabled_features + {}); + + host_resolver_->set_ondemand_mode(true); + + TestCompletionCallback callback; + ClientSocketHandle handle; + ClientSocketPool::GroupId group_id( + HostPortPair("www.google.com", 80), ClientSocketPool::SocketType::kHttp, + PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey, + false /* disable_secure_dns */); + EXPECT_THAT( + handle.Init(group_id, params_, base::nullopt /* proxy_annotation_tag */, + kDefaultPriority, SocketTag(), + ClientSocketPool::RespectLimits::ENABLED, callback.callback(), + ClientSocketPool::ProxyAuthCallback(), &pool_, + NetLogWithSource()), + IsError(ERR_IO_PENDING)); + + ASSERT_EQ(1u, host_resolver_->last_id()); + EXPECT_EQ(kNetworkIsolationKey, + host_resolver_->request_network_isolation_key(1)); +} + } // namespace } // namespace net
diff --git a/net/socket/websocket_transport_connect_job.cc b/net/socket/websocket_transport_connect_job.cc index 926cf67..c96d542 100644 --- a/net/socket/websocket_transport_connect_job.cc +++ b/net/socket/websocket_transport_connect_job.cc
@@ -110,8 +110,9 @@ HostResolver::ResolveHostParameters parameters; parameters.initial_priority = priority(); DCHECK(!params_->disable_secure_dns()); - request_ = host_resolver()->CreateRequest(params_->destination(), net_log(), - parameters); + request_ = host_resolver()->CreateRequest(params_->destination(), + params_->network_isolation_key(), + net_log(), parameters); return request_->Start(base::BindOnce( &WebSocketTransportConnectJob::OnIOComplete, base::Unretained(this)));
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 3a666c85..abe16d4 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -93,8 +93,8 @@ NetLogWithSource())); auto transport_params = base::MakeRefCounted<TransportSocketParams>( - key.host_port_pair(), false /* disable_secure_dns */, - OnHostResolutionCallback()); + key.host_port_pair(), NetworkIsolationKey(), + false /* disable_secure_dns */, OnHostResolutionCallback()); SSLConfig ssl_config; auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index 7907c88..cf517fe4 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -1339,6 +1339,10 @@ } TEST_F(NetworkContextTest, NotifyExternalCacheHit) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + net::features::kSplitCacheByNetworkIsolationKey); + net::MockHttpCache mock_cache; mojom::NetworkContextParamsPtr context_params = CreateContextParams(); context_params->http_cache_enabled = true; @@ -1366,13 +1370,7 @@ EXPECT_EQ(i + 1, mock_cache.disk_cache()->GetExternalCacheHits().size()); // Note: if this breaks check HttpCache::GenerateCacheKey() for changes. - std::string expected_key_prefix = - base::FeatureList::IsEnabled( - net::features::kSplitCacheByNetworkIsolationKey) - ? base::StrCat({"_dk_", key.ToString(), " "}) - : ""; - EXPECT_EQ(expected_key_prefix + test_url.spec(), - mock_cache.disk_cache()->GetExternalCacheHits().back()); + EXPECT_EQ(test_url, mock_cache.disk_cache()->GetExternalCacheHits().back()); } }
diff --git a/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc b/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc index e2eb653..20e9132 100644 --- a/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
@@ -18,18 +18,16 @@ viz::CompositorFrameMetadata>:: Read(viz::mojom::CompositorFrameMetadataDataView data, viz::CompositorFrameMetadata* out) { - if (data.device_scale_factor() <= 0) - return false; + // TODO(samans): Replace CHECKs with early-outs once we find out the cause for + // deserialization failures. https://crbug.com/979564 + CHECK_GT(data.device_scale_factor(), 0); out->device_scale_factor = data.device_scale_factor(); - if (!data.ReadRootScrollOffset(&out->root_scroll_offset)) - return false; + CHECK(data.ReadRootScrollOffset(&out->root_scroll_offset)); out->page_scale_factor = data.page_scale_factor(); - if (!data.ReadScrollableViewportSize(&out->scrollable_viewport_size)) - return false; + CHECK(data.ReadScrollableViewportSize(&out->scrollable_viewport_size)); - if (data.frame_token() == 0u) - return false; + CHECK(data.frame_token()); out->frame_token = data.frame_token(); out->may_contain_video = data.may_contain_video(); @@ -45,15 +43,16 @@ out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio(); #endif - return data.ReadLatencyInfo(&out->latency_info) && - data.ReadReferencedSurfaces(&out->referenced_surfaces) && - data.ReadDeadline(&out->deadline) && - data.ReadActivationDependencies(&out->activation_dependencies) && - data.ReadBeginFrameAck(&out->begin_frame_ack) && - data.ReadLocalSurfaceIdAllocationTime( - &out->local_surface_id_allocation_time) && - !out->local_surface_id_allocation_time.is_null() && - data.ReadPreferredFrameInterval(&out->preferred_frame_interval); + CHECK(data.ReadLatencyInfo(&out->latency_info)); + CHECK(data.ReadReferencedSurfaces(&out->referenced_surfaces)); + CHECK(data.ReadDeadline(&out->deadline)); + CHECK(data.ReadActivationDependencies(&out->activation_dependencies)); + CHECK(data.ReadBeginFrameAck(&out->begin_frame_ack)); + CHECK(data.ReadLocalSurfaceIdAllocationTime( + &out->local_surface_id_allocation_time)); + CHECK(!out->local_surface_id_allocation_time.is_null()); + CHECK(data.ReadPreferredFrameInterval(&out->preferred_frame_interval)); + return true; } } // namespace mojo
diff --git a/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc b/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc index f3dc02f55..8b25f0e 100644 --- a/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc
@@ -9,11 +9,12 @@ // static bool StructTraits<viz::mojom::CompositorFrameDataView, viz::CompositorFrame>:: Read(viz::mojom::CompositorFrameDataView data, viz::CompositorFrame* out) { - return data.ReadPasses(&out->render_pass_list) && - !out->render_pass_list.empty() && - !out->render_pass_list.back()->output_rect.size().IsEmpty() && - data.ReadMetadata(&out->metadata) && - data.ReadResources(&out->resource_list); + CHECK(data.ReadPasses(&out->render_pass_list)); + CHECK(!out->render_pass_list.empty()); + CHECK(!out->render_pass_list.back()->output_rect.size().IsEmpty()); + CHECK(data.ReadMetadata(&out->metadata)); + CHECK(data.ReadResources(&out->resource_list)); + return true; } } // namespace mojo
diff --git a/services/viz/public/cpp/compositing/local_surface_id_mojom_traits.h b/services/viz/public/cpp/compositing/local_surface_id_mojom_traits.h index 7bcc38d..1ff9376 100644 --- a/services/viz/public/cpp/compositing/local_surface_id_mojom_traits.h +++ b/services/viz/public/cpp/compositing/local_surface_id_mojom_traits.h
@@ -32,7 +32,9 @@ viz::LocalSurfaceId* out) { out->parent_sequence_number_ = data.parent_sequence_number(); out->child_sequence_number_ = data.child_sequence_number(); - return data.ReadEmbedToken(&out->embed_token_) && out->is_valid(); + CHECK(data.ReadEmbedToken(&out->embed_token_)); + CHECK(out->is_valid()); + return true; } };
diff --git a/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc b/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc index 92ac1dbc..efa2c61 100644 --- a/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc
@@ -15,20 +15,17 @@ Read(viz::mojom::RenderPassDataView data, std::unique_ptr<viz::RenderPass>* out) { *out = viz::RenderPass::Create(); - if (!data.ReadOutputRect(&(*out)->output_rect) || - !data.ReadDamageRect(&(*out)->damage_rect) || - !data.ReadTransformToRootTarget(&(*out)->transform_to_root_target) || - !data.ReadFilters(&(*out)->filters) || - !data.ReadBackdropFilters(&(*out)->backdrop_filters) || - !data.ReadBackdropFilterBounds(&(*out)->backdrop_filter_bounds) || - !data.ReadColorSpace(&(*out)->color_space) || - !data.ReadCopyRequests(&(*out)->copy_requests)) { - return false; - } + CHECK(data.ReadOutputRect(&(*out)->output_rect)); + CHECK(data.ReadDamageRect(&(*out)->damage_rect)); + CHECK(data.ReadTransformToRootTarget(&(*out)->transform_to_root_target)); + CHECK(data.ReadFilters(&(*out)->filters)); + CHECK(data.ReadBackdropFilters(&(*out)->backdrop_filters)); + CHECK(data.ReadBackdropFilterBounds(&(*out)->backdrop_filter_bounds)); + CHECK(data.ReadColorSpace(&(*out)->color_space)); + CHECK(data.ReadCopyRequests(&(*out)->copy_requests)); (*out)->id = data.id(); // RenderPass ids are never zero. - if (!(*out)->id) - return false; + CHECK((*out)->id); (*out)->has_transparent_background = data.has_transparent_background(); (*out)->cache_render_pass = data.cache_render_pass(); (*out)->has_damage_from_contributing_content = @@ -46,10 +43,8 @@ viz::DrawQuad* quad = AllocateAndConstruct(quad_state_data_view.tag(), &(*out)->quad_list); - if (!quad) - return false; - if (!quads.Read(i, quad)) - return false; + CHECK(quad); + CHECK(quads.Read(i, quad)); // Read the SharedQuadState. viz::mojom::SharedQuadStateDataView sqs_data_view; @@ -58,12 +53,10 @@ // one. if (!sqs_data_view.is_null()) { last_sqs = (*out)->CreateAndAppendSharedQuadState(); - if (!quad_data_view.ReadSqs(last_sqs)) - return false; + CHECK(quad_data_view.ReadSqs(last_sqs)); } quad->shared_quad_state = last_sqs; - if (!quad->shared_quad_state) - return false; + CHECK(quad->shared_quad_state); } return true; }
diff --git a/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc b/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc index a6468df..71bdf46 100644 --- a/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/transferable_resource_mojom_traits.cc
@@ -17,12 +17,10 @@ viz::TransferableResource>:: Read(viz::mojom::TransferableResourceDataView data, viz::TransferableResource* out) { - if (!data.ReadSize(&out->size) || - !data.ReadMailboxHolder(&out->mailbox_holder) || - !data.ReadColorSpace(&out->color_space) || - !data.ReadYcbcrInfo(&out->ycbcr_info)) { - return false; - } + CHECK(data.ReadSize(&out->size)); + CHECK(data.ReadMailboxHolder(&out->mailbox_holder)); + CHECK(data.ReadColorSpace(&out->color_space)); + CHECK(data.ReadYcbcrInfo(&out->ycbcr_info)); out->id = data.id(); out->format = static_cast<viz::ResourceFormat>(data.format()); out->filter = data.filter();
diff --git a/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc b/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc index a15ba4b4..032fb672 100644 --- a/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc +++ b/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc
@@ -10,12 +10,9 @@ bool StructTraits<viz::mojom::HitTestRegionDataView, viz::HitTestRegion>::Read( viz::mojom::HitTestRegionDataView data, viz::HitTestRegion* out) { - if (!data.ReadFrameSinkId(&out->frame_sink_id)) - return false; - if (!data.ReadRect(&out->rect)) - return false; - if (!data.ReadTransform(&out->transform)) - return false; + CHECK(data.ReadFrameSinkId(&out->frame_sink_id)); + CHECK(data.ReadRect(&out->rect)); + CHECK(data.ReadTransform(&out->transform)); out->flags = data.flags(); out->async_hit_test_reasons = data.async_hit_test_reasons(); return true; @@ -26,12 +23,9 @@ viz::mojom::HitTestRegionListDataView, viz::HitTestRegionList>::Read(viz::mojom::HitTestRegionListDataView data, viz::HitTestRegionList* out) { - if (!data.ReadRegions(&out->regions)) - return false; - if (!data.ReadBounds(&out->bounds)) - return false; - if (!data.ReadTransform(&out->transform)) - return false; + CHECK(data.ReadRegions(&out->regions)); + CHECK(data.ReadBounds(&out->bounds)); + CHECK(data.ReadTransform(&out->transform)); out->flags = data.flags(); out->async_hit_test_reasons = data.async_hit_test_reasons(); return true;
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 1aed81c..758990a4 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -304,6 +304,74 @@ }, "test": "webview_ui_test_app_test_apk" } + ], + "isolated_scripts": [ + { + "args": [ + "--enable-features=OutOfBlinkCors" + ], + "isolate_name": "chrome_public_wpt", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "chrome_public_wpt", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/chrome/test/chromedriver/cipd", + "location": "chrome/test/chromedriver/cipd", + "revision": "PCCG9OmVmpDaf9oaKhJ3sSxXgINilZ9qpl4oaRU0R60C" + } + ], + "dimension_sets": [ + { + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "walleye", + "os": "Android" + } + ], + "expiration": 18000, + "hard_timeout": 14400, + "shards": 15 + } + }, + { + "args": [ + "--enable-features=OutOfBlinkCors" + ], + "isolate_name": "system_webview_wpt", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "system_webview_wpt", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/chrome/test/chromedriver/cipd", + "location": "chrome/test/chromedriver/cipd", + "revision": "PCCG9OmVmpDaf9oaKhJ3sSxXgINilZ9qpl4oaRU0R60C" + } + ], + "dimension_sets": [ + { + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "walleye", + "os": "Android" + } + ], + "expiration": 18000, + "hard_timeout": 14400, + "shards": 15 + } + } ] }, "Memory Infra Tester": {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 23c34627..db1862b 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -673,6 +673,7 @@ "args": [ "--product=chrome_android", "--apk=apks/ChromePublic.apk", + "--verbose", ], }, "chrome_sandbox": { @@ -2641,6 +2642,7 @@ "--product=android_webview", "--apk=apks/SystemWebView.apk", "--system-webview-shell=apks/SystemWebViewShell.apk", + "--verbose", ], }, "telemetry_gpu_integration_test": {
diff --git a/testing/buildbot/tryserver.webrtc.json b/testing/buildbot/tryserver.webrtc.json index 1619cb0..baaacd1c 100644 --- a/testing/buildbot/tryserver.webrtc.json +++ b/testing/buildbot/tryserver.webrtc.json
@@ -23,6 +23,18 @@ "remoting/webapp:webapp" ] }, + "linux_chromium_compile_dbg": { + "additional_compile_targets": [ + "blink_unittests", + "browser_tests", + "capture_unittests", + "content_browsertests", + "content_unittests", + "jingle_unittests", + "remoting_unittests", + "remoting/webapp:webapp" + ] + }, "mac_chromium_compile": { "additional_compile_targets": [ "blink_unittests", @@ -46,5 +58,17 @@ "remoting_unittests", "remoting/webapp:webapp" ] + }, + "win_chromium_compile_dbg": { + "additional_compile_targets": [ + "blink_unittests", + "browser_tests", + "capture_unittests", + "content_browsertests", + "content_unittests", + "jingle_unittests", + "remoting_unittests", + "remoting/webapp:webapp" + ] } }
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 4e161f4..920f9b9 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -666,6 +666,7 @@ ], 'test_suites': { 'gtest_tests': 'webview_bot_oor_cors_gtests', + 'isolated_scripts': 'android_wpt_scripts', }, 'args': [ '--enable-features=OutOfBlinkCors', @@ -4481,6 +4482,18 @@ 'remoting/webapp:webapp', ], }, + 'linux_chromium_compile_dbg': { + 'additional_compile_targets': [ + 'blink_unittests', + 'browser_tests', + 'capture_unittests', + 'content_browsertests', + 'content_unittests', + 'jingle_unittests', + 'remoting_unittests', + 'remoting/webapp:webapp', + ], + }, 'mac_chromium_compile': { 'additional_compile_targets': [ 'blink_unittests', @@ -4505,6 +4518,18 @@ 'remoting/webapp:webapp', ], }, + 'win_chromium_compile_dbg': { + 'additional_compile_targets': [ + 'blink_unittests', + 'browser_tests', + 'capture_unittests', + 'content_browsertests', + 'content_unittests', + 'jingle_unittests', + 'remoting_unittests', + 'remoting/webapp:webapp', + ], + }, }, }, ]
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 33919fcf8..3461333 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1371,6 +1371,22 @@ ] } ], + "BoostThreadPriorityOnLibraryLoadingAndBackgroundMode": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "BoostPriorityAndBackgroundThreadMode", + "enable_features": [ + "BoostThreadPriorityOnLibraryLoading", + "WindowsThreadModeBackground" + ] + } + ] + } + ], "BrowserBlacklist": [ { "platforms": [ @@ -1885,21 +1901,6 @@ ] } ], - "DeferAllScript": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "DeferAllScriptPreviews_Enabled_20190814", - "enable_features": [ - "DeferAllScript" - ] - } - ] - } - ], "DialMediaRouteProvider": [ { "platforms": [
diff --git a/third_party/blink/public/platform/web_rtc_offer_options.h b/third_party/blink/public/platform/web_rtc_offer_options.h deleted file mode 100644 index c4718bbb..0000000 --- a/third_party/blink/public/platform/web_rtc_offer_options.h +++ /dev/null
@@ -1,49 +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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_OFFER_OPTIONS_H_ -#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_OFFER_OPTIONS_H_ - -#include "third_party/blink/public/platform/web_common.h" -#include "third_party/blink/public/platform/web_private_ptr.h" - -namespace blink { - -class RTCOfferOptionsPlatform; - -class BLINK_PLATFORM_EXPORT WebRTCOfferOptions { - public: - WebRTCOfferOptions(int32_t offer_to_receive_audio, - int32_t offer_to_receive_video, - bool voice_activity_detection, - bool ice_restart); - WebRTCOfferOptions(const WebRTCOfferOptions& other) { Assign(other); } - ~WebRTCOfferOptions() { Reset(); } - - WebRTCOfferOptions& operator=(const WebRTCOfferOptions& other) { - Assign(other); - return *this; - } - - void Assign(const WebRTCOfferOptions&); - - void Reset(); - bool IsNull() const { return private_.IsNull(); } - - int32_t OfferToReceiveVideo() const; - int32_t OfferToReceiveAudio() const; - bool VoiceActivityDetection() const; - bool IceRestart() const; - -#if INSIDE_BLINK - WebRTCOfferOptions(RTCOfferOptionsPlatform*); -#endif - - private: - WebPrivatePtr<RTCOfferOptionsPlatform> private_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_OFFER_OPTIONS_H_
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 277ec2b..5b0d8b8 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -435,11 +435,12 @@ DCHECK(!stream_); DCHECK(!source_); - stream_ = new SourceStream; + auto stream_ptr = std::make_unique<SourceStream>(); + stream_ = stream_ptr.get(); // |source_| takes ownership of |stream_|, and will keep |stream_| alive until // |source_| is destructed. - source_ = - std::make_unique<v8::ScriptCompiler::StreamedSource>(stream_, encoding_); + source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>( + std::move(stream_ptr), encoding_); std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> script_streaming_task(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc index 3a3e890..75ea8b1 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -348,18 +348,20 @@ key_tracing_callback_(key_tracing_callback), value_tracing_callback_(value_tracing_callback) {} - void Process(V8EmbedderGraphBuilder* builder) { + bool Process(V8EmbedderGraphBuilder* builder) { Traceable key = nullptr; { TraceKeysScope scope(builder, &key); key_tracing_callback_(builder, const_cast<void*>(key_)); } DCHECK(key); - DCHECK(builder->GetStateNotNull(key)); + if (!builder->StateExists(key)) + return false; { TraceValuesScope scope(builder, key); value_tracing_callback_(builder, const_cast<void*>(value_)); } + return true; } private: @@ -378,6 +380,10 @@ return states_.at(traceable); } + bool StateExists(Traceable traceable) const { + return states_.Contains(traceable); + } + State* GetStateNotNull(Traceable traceable) { CHECK(states_.Contains(traceable)); return states_.at(traceable); @@ -772,6 +778,12 @@ // tracing can record new ephemerons, and tracing an ephemeron can add // items to the regular worklist, we need to repeatedly process the worklist // until a fixed point is reached. + + // Because snapshots are processed in stages, there may be ephemerons that + // where key's do not have yet a state associated with them which prohibits + // them from being processed. Such ephemerons are stashed for later + // processing. + Deque<std::unique_ptr<EphemeronItem>> unprocessed_ephemerons_; do { // Step 1: Go through all items in the worklist using depth-first search. while (!worklist_.empty()) { @@ -780,15 +792,29 @@ item->Process(this); } - // Step 2: Go through ephemeron items. Only process an ephemeron item if - // its key was already observed. + // Step 2: Go through ephemeron items. + + // Re-add unprocessed ephemerons from last loop iteration. + while (!unprocessed_ephemerons_.empty()) { + ephemeron_worklist_.push_back(unprocessed_ephemerons_.TakeFirst()); + } + + // Only process an ephemeron item if its key was already observed. while (!ephemeron_worklist_.empty()) { std::unique_ptr<EphemeronItem> item = std::move(ephemeron_worklist_.front()); ephemeron_worklist_.pop_front(); - item->Process(this); + if (!item->Process(this)) { + unprocessed_ephemerons_.push_back(std::move(item)); + } } } while (!worklist_.empty()); + + // Re-add unprocessed ephemerons. A later invocation of VisitTransitiveClosure + // must process them. + while (!unprocessed_ephemerons_.empty()) { + ephemeron_worklist_.push_back(unprocessed_ephemerons_.TakeFirst()); + } } } // namespace
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py index e1db1acf..e60e363 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
@@ -2,17 +2,156 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import web_idl + +from . import name_style from .code_node import CodeNode from .code_node import SymbolDefinitionNode from .code_node import SymbolNode from .code_node import SymbolScopeNode from .code_node import TextNode from .code_node import UnlikelyExitNode -import web_idl _format = CodeNode.format_template +def blink_type_info(idl_type): + """ + Returns the types of Blink implementation corresponding to the given IDL + type. The returned object has the following attributes. + + member_t: The type of a member variable. E.g. T => Member<T> + ref_t: The type of a local variable that references to an already-existing + value. E.g. String => String& + value_t: The type of a variable that behaves as a value. E.g. String => + String + is_nullable: True if the Blink implementation type can represent IDL null + value by itself. + """ + assert isinstance(idl_type, web_idl.IdlType) + + class TypeInfo(object): + def __init__(self, + typename, + member_fmt="{}", + ref_fmt="{}", + value_fmt="{}", + is_nullable=False): + self.member_t = member_fmt.format(typename) + self.ref_t = ref_fmt.format(typename) + self.value_t = value_fmt.format(typename) + # Whether Blink impl type can represent IDL null or not. + self.is_nullable = is_nullable + + real_type = idl_type.unwrap(typedef=True) + + if real_type.is_boolean or real_type.is_numeric: + cxx_type = { + "boolean": "bool", + "byte": "int8_t", + "octet": "uint8_t", + "short": "int16_t", + "unsigned short": "uint16_t", + "long": "int32_t", + "unsigned long": "uint32_t", + "long long": "int64_t", + "unsigned long long": "uint64_t", + "float": "float", + "unrestricted float": "float", + "double": "double", + "unrestricted double": "double", + } + return TypeInfo(cxx_type[real_type.keyword_typename]) + + if real_type.is_string: + return TypeInfo("String", ref_fmt="{}&", is_nullable=True) + + if real_type.is_symbol: + assert False, "Blink does not support/accept IDL symbol type." + + if real_type.is_any or real_type.is_object: + return TypeInfo("ScriptValue", ref_fmt="{}&", is_nullable=True) + + if real_type.is_void: + assert False, "Blink does not support/accept IDL void type." + + if real_type.type_definition_object is not None: + type_def_obj = real_type.type_definition_object + blink_impl_type = ( + type_def_obj.code_generator_info.receiver_implemented_as + or name_style.class_(type_def_obj.identifier)) + return TypeInfo( + blink_impl_type, + member_fmt="Member<{}>", + ref_fmt="{}*", + is_nullable=True) + + if (real_type.is_sequence or real_type.is_frozen_array + or real_type.is_variadic): + element_type = blink_type_info(real_type.element_type) + return TypeInfo( + "VectorOf<{}>".format(element_type.value_t), ref_fmt="{}&") + + if real_type.is_record: + key_type = blink_type_info(real_type.key_type) + value_type = blink_type_info(real_type.value_type) + return TypeInfo( + "VectorOfPairs<{}, {}>".format(key_type.value_t, + value_type.value_t), + ref_fmt="{}&") + + if real_type.is_promise: + return TypeInfo("ScriptPromise", ref_fmt="{}&") + + if real_type.is_union: + return TypeInfo("ToBeImplementedUnion") + + if real_type.is_nullable: + inner_type = blink_type_info(real_type.inner_type) + if inner_type.is_nullable: + return inner_type + return TypeInfo( + "base::Optional<{}>".format(inner_type.value_t), ref_fmt="{}&") + + +def native_value_tag(idl_type): + """Returns the tag type of NativeValueTraits.""" + assert isinstance(idl_type, web_idl.IdlType) + + real_type = idl_type.unwrap(typedef=True) + + if (real_type.is_boolean or real_type.is_numeric or real_type.is_string + or real_type.is_any or real_type.is_object): + return "IDL{}".format(real_type.type_name) + + if real_type.is_symbol: + assert False, "Blink does not support/accept IDL symbol type." + + if real_type.is_void: + assert False, "Blink does not support/accept IDL void type." + + if real_type.type_definition_object is not None: + return blink_type_info(real_type).value_t + + if real_type.is_sequence: + return "IDLSequence<{}>".format( + native_value_tag(real_type.element_type)) + + if real_type.is_record: + return "IDLRecord<{}, {}>".format( + native_value_tag(real_type.key_type), + native_value_tag(real_type.value_type)) + + if real_type.is_promise: + return "IDLPromise" + + if real_type.is_union: + return blink_type_info(real_type).value_t + + if real_type.is_nullable: + return "IDLNullable<{}>".format(native_value_tag(real_type.inner_type)) + + def make_v8_to_blink_value(blink_var_name, v8_value_expr, idl_type): """ Returns a SymbolNode whose definition converts a v8::Value to a Blink value. @@ -22,17 +161,14 @@ assert isinstance(idl_type, web_idl.IdlType) pattern = "NativeValueTraits<{_1}>::NativeValue({_2})" - _1 = "IDL{}".format(idl_type.type_name) + _1 = native_value_tag(idl_type) _2 = ["${isolate}", v8_value_expr, "${exception_state}"] - blink_value = _format(pattern, _1=_1, _2=", ".join(_2)) - idl_type_tag = _1 - pattern = "{_1}& ${{{_2}}} = {_3};" - _1 = "NativeValueTraits<{}>::ImplType".format(idl_type_tag) - _2 = blink_var_name - _3 = blink_value - text = _format(pattern, _1=_1, _2=_2, _3=_3) + pattern = "const auto& ${{{_1}}} = {_2};" + _1 = blink_var_name + _2 = blink_value + text = _format(pattern, _1=_1, _2=_2) def create_definition(symbol_node): return SymbolDefinitionNode(symbol_node, [
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_generation_context.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_generation_context.py index 91ba2edc..fcbf1e8 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_generation_context.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_generation_context.py
@@ -4,7 +4,7 @@ import copy -from blinkbuild.name_style_converter import NameStyleConverter +from . import name_style class CodeGenerationContext(object): @@ -196,9 +196,7 @@ def v8_class(self): if not self.idl_definition: return None - return "V8{}".format( - NameStyleConverter( - self.idl_definition.identifier).to_upper_camel_case()) + return name_style.class_("v8", self.idl_definition.identifier) CodeGenerationContext.init()
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index ccc4092..78075e5 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -5,6 +5,7 @@ import os.path from . import name_style +from .blink_v8_bridge import blink_type_info from .blink_v8_bridge import make_v8_to_blink_value from .code_generation_context import CodeGenerationContext from .code_node import CodeNode @@ -193,7 +194,9 @@ if cg_context.return_type.unwrap().is_void: text = "${blink_api_call};" elif cg_context.is_return_by_argument: - text = "${blink_return_type} ${return_value};\n${blink_api_call};" + pattern = "{_1} ${return_value};\n${blink_api_call};" + _1 = blink_type_info(cg_context.return_type).value_t + text = _format(pattern, _1=_1) else: text = "const auto& ${return_value} = ${blink_api_call};" node = SymbolDefinitionNode(symbol_node, [TextNode(text)])
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py index 103411a1..79a6136 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -192,6 +192,15 @@ """ raise exceptions.NotImplementedError() + @property + def keyword_typename(self): + """ + Returns the keyword name of the type if this is a simple built-in type, + e.g. "any", "boolean", "unsigned long long", "void", etc. Otherwise, + returns None. + """ + return None + def apply_to_all_composing_elements(self, callback): """ Applies |callback| to all instances of IdlType of which this IdlType @@ -516,6 +525,10 @@ NameStyleConverter(name).to_upper_camel_case()) @property + def keyword_typename(self): + return self._name + + @property def is_numeric(self): return self._name in SimpleType._NUMERIC_TYPES
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index 213c8b7..aaaa464 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -680,7 +680,7 @@ return {"ObsoleteWebRtcCipherSuite", kM81, String::Format( "Your partner is negotiating an obsolete (D)TLS version. " - "Support for this will be removed in %s" + "Support for this will be removed in %s. " "Please check with your partner to have this fixed.", MilestoneString(kM81))};
diff --git a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc index 24110a3..1b1a0f7 100644 --- a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc +++ b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
@@ -7,7 +7,6 @@ #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/platform/interface_provider.h" -#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -102,26 +101,6 @@ } } - // Record the child frame and top-level frame URLs for autoplay muted videos - // by attribute. - if (element_->IsHTMLVideoElement() && element_->muted()) { - if (sources_.size() == - static_cast<size_t>(AutoplaySource::kNumberOfSources)) { - Platform::Current()->RecordRapporURL( - "Media.Video.Autoplay.Muted.DualSource.Frame", - element_->GetDocument().Url()); - } else if (source == AutoplaySource::kAttribute) { - Platform::Current()->RecordRapporURL( - "Media.Video.Autoplay.Muted.Attribute.Frame", - element_->GetDocument().Url()); - } else { - DCHECK(source == AutoplaySource::kMethod); - Platform::Current()->RecordRapporURL( - "Media.Video.Autoplay.Muted.PlayMethod.Frame", - element_->GetDocument().Url()); - } - } - // Record if it will be blocked by the Autoplay setting. if (element_->IsHTMLVideoElement() && element_->muted() && AutoplayPolicy::DocumentShouldAutoplayMutedVideos(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc index 07118b1..0070061 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -184,6 +184,38 @@ EXPECT_FALSE(iterator.NextChild()); } +TEST_F(NGColumnLayoutAlgorithmTest, ZeroHeightBlockAtFragmentainerBoundary) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 2; + column-fill: auto; + column-gap: 10px; + height: 100px; + width: 210px; + } + </style> + <div id="container"> + <div id="parent"> + <div style="width:33px; height:200px;"></div> + <div style="width:44px;"></div> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x100 + offset:0,0 size:210x100 + offset:0,0 size:100x100 + offset:0,0 size:33x100 + offset:110,0 size:100x100 + offset:0,0 size:33x100 + offset:0,100 size:44x0 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + TEST_F(NGColumnLayoutAlgorithmTest, BlockInTwoColumns) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index e1d3a77..cd77c684 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -368,8 +368,10 @@ // If the block-offset is past the fragmentainer boundary (or exactly at // the boundary), no part of the fragment is going to fit in the current // fragmentainer. Fragments may be pushed past the fragmentainer boundary - // by margins. - need_break = space_left <= LayoutUnit(); + // by margins. We shouldn't break before a zero-size block that's exactly + // at a fragmentainer boundary, though. + need_break = space_left < LayoutUnit() || + (space_left == LayoutUnit() && fragment.BlockSize()); } if (need_break) { // If we haven't used any space at all in the fragmentainer yet, though,
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc index 03536cd..792534a 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
@@ -93,13 +93,9 @@ if (is_overlay_button_) { Platform::Current()->RecordAction( UserMetricsAction("Media.Controls.CastOverlay")); - Platform::Current()->RecordRapporURL("Media.Controls.CastOverlay", - WebURL(GetDocument().Url())); } else { Platform::Current()->RecordAction( UserMetricsAction("Media.Controls.Cast")); - Platform::Current()->RecordRapporURL("Media.Controls.Cast", - WebURL(GetDocument().Url())); } RemotePlayback::From(MediaElement()).PromptInternal();
diff --git a/third_party/blink/renderer/modules/mediasession/media_session.cc b/third_party/blink/renderer/modules/mediasession/media_session.cc index bd6d83f5..5911652 100644 --- a/third_party/blink/renderer/modules/mediasession/media_session.cc +++ b/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -7,7 +7,6 @@ #include <memory> #include "base/optional.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_media_session_action_handler.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" @@ -322,12 +321,8 @@ GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI); frame->GetBrowserInterfaceBroker().GetInterface( service_.BindNewPipeAndPassReceiver()); - if (service_.get()) { - // Record the eTLD+1 of the frame using the API. - Platform::Current()->RecordRapporURL("Media.Session.APIUsage.Origin", - document->Url()); + if (service_.get()) service_->SetClient(client_receiver_.BindNewPipeAndPassRemote(task_runner)); - } return service_.get(); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc index 12c0cd99..a75d9abf 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
@@ -99,17 +99,6 @@ void RTCDtlsTransport::ChangeState(webrtc::DtlsTransportInformation info) { DCHECK(current_state_.state() != webrtc::DtlsTransportState::kClosed); current_state_ = info; - if (current_state_.state() == webrtc::DtlsTransportState::kConnected) { - if (current_state_.tls_version()) { - if (*current_state_.tls_version() == DTLS1_VERSION || - *current_state_.tls_version() == SSL3_VERSION || - *current_state_.tls_version() == TLS1_VERSION || - *current_state_.tls_version() == TLS1_1_VERSION) { - Deprecation::CountDeprecation(GetExecutionContext(), - WebFeature::kObsoleteWebrtcTlsVersion); - } - } - } } void RTCDtlsTransport::Close() { @@ -129,6 +118,20 @@ // We depend on closed only happening once for safe garbage collection. DCHECK(current_state_.state() != webrtc::DtlsTransportState::kClosed); current_state_ = info; + + // DTLS 1.0 is deprecated, emit a console warning. + if (current_state_.state() == webrtc::DtlsTransportState::kConnected) { + if (current_state_.tls_version()) { + if (*current_state_.tls_version() == DTLS1_VERSION || + *current_state_.tls_version() == SSL3_VERSION || + *current_state_.tls_version() == TLS1_VERSION || + *current_state_.tls_version() == TLS1_1_VERSION) { + Deprecation::CountDeprecation(GetExecutionContext(), + WebFeature::kObsoleteWebrtcTlsVersion); + } + } + } + // If the certificates have changed, copy them as DOMArrayBuffers. // This makes sure that getRemoteCertificates() == getRemoteCertificates() if (current_state_.remote_ssl_certificates()) {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc index c9f617a..839d8c8 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -257,6 +257,21 @@ return promise; } +bool AudioContext::IsPullingAudioGraph() const { + DCHECK(IsMainThread()); + + if (!destination()) + return false; + + RealtimeAudioDestinationHandler& destination_handler = + static_cast<RealtimeAudioDestinationHandler&>( + destination()->GetAudioDestinationHandler()); + + // The realtime context is pulling on the audio graph if the realtime + // destination allows it. + return destination_handler.IsPullingAudioGraphAllowed(); +} + AudioTimestamp* AudioContext::getOutputTimestamp( ScriptState* script_state) const { AudioTimestamp* result = AudioTimestamp::Create();
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.h b/third_party/blink/renderer/modules/webaudio/audio_context.h index 3779376..e0d4cf1 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -56,6 +56,8 @@ bool HasRealtimeConstraint() final { return true; } + bool IsPullingAudioGraph() const final; + AudioTimestamp* getOutputTimestamp(ScriptState*) const; double baseLatency() const;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node.cc b/third_party/blink/renderer/modules/webaudio/audio_node.cc index e9b0bcf..168593b 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -609,25 +609,15 @@ BaseAudioContext::GraphAutoLocker locker(context()); Handler().Dispose(); - if (context()->HasRealtimeConstraint()) { - // Add the handler to the orphan list if the context is not - // uninitialized (Nothing will clean up the orphan list if the context - // is uninitialized.) These will get cleaned up in the post render task - // if audio thread is running or when the context is colleced (in - // the worst case). - if (!context()->IsContextClosed()) { - context()->GetDeferredTaskHandler().AddRenderingOrphanHandler( - std::move(handler_)); - } - } else { - // For an offline context, only need to save the handler when the - // context is running. The change in the context state is - // synchronous with the main thread (even though the offline - // thread is not synchronized to the main thread). - if (context()->ContextState() == BaseAudioContext::kRunning) { - context()->GetDeferredTaskHandler().AddRenderingOrphanHandler( - std::move(handler_)); - } + // Add the handler to the orphan list if the context is pulling on the audio + // graph. This keeps the handler alive until it can be deleted at a safe + // point (in pre/post handler task). If graph isn't being pulled, we can + // delete the handler now since nothing on the audio thread will be touching + // it. + DCHECK(context()); + if (context()->IsPullingAudioGraph()) { + context()->GetDeferredTaskHandler().AddRenderingOrphanHandler( + std::move(handler_)); } // Notify the inspector that this node is going away. The actual clean up
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h index b99f526..d5aadf7 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -142,6 +142,10 @@ // does nothing useful because the context is closed. void WarnForConnectionIfContextClosed() const; + // Return true if the destination is pulling on the audio graph. Otherwise + // return false. + virtual bool IsPullingAudioGraph() const = 0; + AudioBuffer* createBuffer(uint32_t number_of_channels, uint32_t number_of_frames, float sample_rate,
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc index 8c42f49a..3d93311 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
@@ -479,6 +479,15 @@ RejectPendingDecodeAudioDataResolvers(); } +bool OfflineAudioContext::IsPullingAudioGraph() const { + DCHECK(IsMainThread()); + + // For an offline context, we're rendering only while the context is running. + // Unlike an AudioContext, there's no audio device that keeps pulling on graph + // after the context has finished rendering. + return ContextState() == BaseAudioContext::kRunning; +} + bool OfflineAudioContext::ShouldSuspend() { DCHECK(IsAudioThread());
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.h b/third_party/blink/renderer/modules/webaudio/offline_audio_context.h index a0ffabb..f35b536 100644 --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.h
@@ -70,6 +70,8 @@ bool HasRealtimeConstraint() final { return false; } + bool IsPullingAudioGraph() const final; + DEFINE_ATTRIBUTE_EVENT_LISTENER(complete, kComplete) // Fire completion event when the rendering is finished.
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc index aac30e2..9f7119b 100644 --- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc +++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
@@ -52,7 +52,8 @@ base::Optional<float> sample_rate) : AudioDestinationHandler(node), latency_hint_(latency_hint), - sample_rate_(sample_rate) { + sample_rate_(sample_rate), + allow_pulling_audio_graph_(false) { // Node-specific default channel count and mixing rules. channel_count_ = 2; SetInternalChannelCountMode(kExplicit); @@ -194,19 +195,26 @@ context->HandlePreRenderTasks(&output_position, &metric); - // Renders the graph by pulling all the input(s) to this node. This will in - // turn pull on their input(s), all the way backwards through the graph. - AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames); + // Only pull on the audio graph if we have not stopped the destination. It + // takes time for the destination to stop, but we want to stop pulling before + // the destination has actually stopped. + if (IsPullingAudioGraphAllowed()) { + // Renders the graph by pulling all the input(s) to this node. This will in + // turn pull on their input(s), all the way backwards through the graph. + AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames); - DCHECK(rendered_bus); - if (!rendered_bus) { - // AudioNodeInput might be in the middle of destruction. Then the internal - // summing bus will return as nullptr. Then zero out the output. + DCHECK(rendered_bus); + if (!rendered_bus) { + // AudioNodeInput might be in the middle of destruction. Then the internal + // summing bus will return as nullptr. Then zero out the output. + destination_bus->Zero(); + } else if (rendered_bus != destination_bus) { + // In-place processing was not possible. Copy the rendererd result to the + // given |destination_bus| buffer. + destination_bus->CopyFrom(*rendered_bus); + } + } else { destination_bus->Zero(); - } else if (rendered_bus != destination_bus) { - // In-place processing was not possible. Copy the rendererd result to the - // given |destination_bus| buffer. - destination_bus->CopyFrom(*rendered_bus); } // Processes "automatic" nodes that are not connected to anything. This can @@ -243,6 +251,8 @@ } void RealtimeAudioDestinationHandler::StartPlatformDestination() { + DCHECK(IsMainThread()); + if (platform_destination_->IsPlaying()) { return; } @@ -258,9 +268,19 @@ } else { platform_destination_->Start(); } + + // Allow the graph to be pulled once the destination actually starts + // requesting data. + EnablePullingAudioGraph(); } void RealtimeAudioDestinationHandler::StopPlatformDestination() { + DCHECK(IsMainThread()); + + // Stop pulling on the graph, even if the destination is still requesting data + // for a while. (It may take a bit of time for the destination to stop.) + DisablePullingAudioGraph(); + if (platform_destination_->IsPlaying()) { platform_destination_->Stop(); }
diff --git a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h index 05a865d1..9c865388 100644 --- a/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h +++ b/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h
@@ -26,6 +26,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_REALTIME_AUDIO_DESTINATION_NODE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_REALTIME_AUDIO_DESTINATION_NODE_H_ +#include <atomic> #include <memory> #include "third_party/blink/public/platform/web_audio_latency_hint.h" #include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h" @@ -80,6 +81,10 @@ // Returns a given frames-per-buffer size from audio infra. int GetFramesPerBuffer() const; + bool IsPullingAudioGraphAllowed() const { + return allow_pulling_audio_graph_.load(std::memory_order_acquire); + } + private: explicit RealtimeAudioDestinationHandler(AudioNode&, const WebAudioLatencyHint&, @@ -89,12 +94,32 @@ void StartPlatformDestination(); void StopPlatformDestination(); + // Should only be called from StartPlatformDestination. + void EnablePullingAudioGraph() { + allow_pulling_audio_graph_.store(true, std::memory_order_release); + } + + // Should only be called from StopPlatformDestination. + void DisablePullingAudioGraph() { + allow_pulling_audio_graph_.store(false, std::memory_order_release); + } + const WebAudioLatencyHint latency_hint_; // Holds the audio device thread that runs the real time audio context. scoped_refptr<AudioDestination> platform_destination_; base::Optional<float> sample_rate_; + + // If true, the audio graph will be pulled to get new data. Otherwise, the + // graph is not pulled, even if the audio thread is still running and + // requesting data. + // + // Must be modified only in StartPlatformDestination (via + // EnablePullingAudioGraph) or StopPlatformDestination (via + // DisablePullingAudioGraph) . This is modified only by the main threda and + // the audio thread only reads this. + std::atomic_bool allow_pulling_audio_graph_; }; // -----------------------------------------------------------------------------
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc index 72c12b2..1650037 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -165,13 +165,10 @@ resolver->Resolve(mapped_buffer_); break; case WGPUBufferMapAsyncStatus_Error: - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kOperationError)); - break; case WGPUBufferMapAsyncStatus_Unknown: case WGPUBufferMapAsyncStatus_DeviceLost: - resolver->Reject( - MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError)); + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kOperationError)); break; default: NOTREACHED();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc index c1d13fc..952a53f7 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -273,8 +273,8 @@ break; case WGPUErrorType_Unknown: case WGPUErrorType_DeviceLost: - resolver->Reject( - MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError)); + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kOperationError)); break; default: NOTREACHED();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_fence.cc b/third_party/blink/renderer/modules/webgpu/gpu_fence.cc index 15eacf0a..11d75d8 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_fence.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_fence.cc
@@ -39,13 +39,10 @@ resolver->Resolve(); break; case WGPUFenceCompletionStatus_Error: - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kOperationError)); - break; case WGPUFenceCompletionStatus_Unknown: case WGPUFenceCompletionStatus_DeviceLost: - resolver->Reject( - MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError)); + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kOperationError)); break; default: NOTREACHED();
diff --git a/third_party/blink/renderer/platform/heap/trace_traits.h b/third_party/blink/renderer/platform/heap/trace_traits.h index fcc7e0c..eab0aa30 100644 --- a/third_party/blink/renderer/platform/heap/trace_traits.h +++ b/third_party/blink/renderer/platform/heap/trace_traits.h
@@ -289,58 +289,42 @@ } }; -// The parameter Strongify serve as an override for weak handling. If it is set -// to true, we ignore the kWeakHandlingFlag provided by the traits and always -// trace strongly (i.e. using kNoWeakHandling). -template <typename Key, - typename Value, - typename KeyTraits, - typename ValueTraits, - bool Strongify> -struct TraceKeyValuePairTraits { - static constexpr bool kKeyIsWeak = - KeyTraits::kWeakHandlingFlag == WTF::kWeakHandling; - static constexpr bool kValueIsWeak = - ValueTraits::kWeakHandlingFlag == WTF::kWeakHandling; +// Reorders parameters for use in blink::Visitor::VisitEphemeronKeyValuePair. +template <typename _KeyType, + typename _ValueType, + typename _KeyTraits, + typename _ValueTraits, + bool = WTF::IsWeak<_ValueType>::value> +struct EphemeronKeyValuePair { + using KeyType = _KeyType; + using ValueType = _ValueType; + using KeyTraits = _KeyTraits; + using ValueTraits = _ValueTraits; - static bool IsAlive(Key& key, Value& value) { - return (blink::TraceCollectionIfEnabled < Strongify - ? WTF::kNoWeakHandling - : KeyTraits::kWeakHandlingFlag, - Key, KeyTraits > ::IsAlive(key)) && - blink::TraceCollectionIfEnabled < Strongify - ? WTF::kNoWeakHandling - : ValueTraits::kWeakHandlingFlag, - Value, ValueTraits > ::IsAlive(value); - } + EphemeronKeyValuePair(KeyType* k, ValueType* v) : key(k), value(v) {} + KeyType* key; + ValueType* value; +}; - // Trace the value only if the key is alive. - template <bool is_ephemeron = kKeyIsWeak && !kValueIsWeak> - static bool Trace(Visitor* visitor, Key& key, Value& value) { - const bool key_is_dead = blink::TraceCollectionIfEnabled < Strongify - ? WTF::kNoWeakHandling - : KeyTraits::kWeakHandlingFlag, - Key, KeyTraits > ::Trace(visitor, &key); - if (key_is_dead && !Strongify) - return true; - return TraceCollectionIfEnabled < Strongify - ? WTF::kNoWeakHandling - : ValueTraits::kWeakHandlingFlag, - Value, ValueTraits > ::Trace(visitor, &value); - } - - // Specializations for ephemerons: - template <> - static bool Trace<true>(Visitor* visitor, Key& key, Value& value) { - return visitor->VisitEphemeronKeyValuePair( - &key, &value, - TraceCollectionIfEnabled < Strongify ? WTF::kNoWeakHandling - : KeyTraits::kWeakHandlingFlag, - Key, KeyTraits > ::Trace, - TraceCollectionIfEnabled < Strongify ? WTF::kNoWeakHandling - : ValueTraits::kWeakHandlingFlag, - Value, ValueTraits > ::Trace); - } +template <typename _KeyType, + typename _ValueType, + typename _KeyTraits, + typename _ValueTraits> +struct EphemeronKeyValuePair<_KeyType, + _ValueType, + _KeyTraits, + _ValueTraits, + true> : EphemeronKeyValuePair<_ValueType, + _KeyType, + _ValueTraits, + _KeyTraits, + false> { + EphemeronKeyValuePair(_KeyType* k, _ValueType* v) + : EphemeronKeyValuePair<_ValueType, + _KeyType, + _ValueTraits, + _KeyTraits, + false>(v, k) {} }; } // namespace blink @@ -558,77 +542,75 @@ struct TraceInCollectionTrait<kNoWeakHandling, KeyValuePair<Key, Value>, Traits> { + using EphemeronHelper = + blink::EphemeronKeyValuePair<Key, + Value, + typename Traits::KeyTraits, + typename Traits::ValueTraits>; + static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) { - static_assert(IsTraceableInCollectionTrait<Traits>::value || - Traits::kWeakHandlingFlag == WTF::kWeakHandling, - "T should not be traced"); - blink::TraceKeyValuePairTraits<Key, Value, typename Traits::KeyTraits, - typename Traits::ValueTraits, - true>::Trace(visitor, self.key, self.value); + if (WTF::IsWeak<Key>::value != WTF::IsWeak<Value>::value) { + // Strongification of Weak/Strong and Strong/Weak. + EphemeronHelper helper(&self.key, &self.value); + visitor->VisitEphemeronKeyValuePair( + helper.key, helper.value, + blink::TraceCollectionIfEnabled< + kNoWeakHandling, typename EphemeronHelper::KeyType, + typename EphemeronHelper::KeyTraits>::Trace, + blink::TraceCollectionIfEnabled< + kNoWeakHandling, typename EphemeronHelper::ValueType, + typename EphemeronHelper::ValueTraits>::Trace); + } else { + // Strongification of Strong/Strong or Weak/Weak. Order does not matter + // here. + blink::TraceCollectionIfEnabled< + kNoWeakHandling, Key, typename Traits::KeyTraits>::Trace(visitor, + &self.key); + blink::TraceCollectionIfEnabled< + kNoWeakHandling, Value, + typename Traits::ValueTraits>::Trace(visitor, &self.value); + } return false; } }; template <typename Key, typename Value, typename Traits> struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> { - static constexpr bool kKeyIsWeak = - Traits::KeyTraits::kWeakHandlingFlag == kWeakHandling; - static constexpr bool kValueIsWeak = - Traits::ValueTraits::kWeakHandlingFlag == kWeakHandling; - static const bool kKeyHasStrongRefs = - IsTraceableInCollectionTrait<typename Traits::KeyTraits>::value; - static const bool kValueHasStrongRefs = - IsTraceableInCollectionTrait<typename Traits::ValueTraits>::value; + using EphemeronHelper = + blink::EphemeronKeyValuePair<Key, + Value, + typename Traits::KeyTraits, + typename Traits::ValueTraits>; + + template <typename T> + static constexpr WeakHandlingFlag GetWeaknessFlag() { + return WTF::IsWeak<T>::value ? kWeakHandling : kNoWeakHandling; + } static bool IsAlive(KeyValuePair<Key, Value>& self) { - static_assert(!kKeyIsWeak || !kValueIsWeak || !kKeyHasStrongRefs || - !kValueHasStrongRefs, - "this configuration is disallowed to avoid unexpected leaks"); - if ((kValueIsWeak && !kKeyIsWeak) || - (kValueIsWeak && kKeyIsWeak && !kValueHasStrongRefs)) { - // Check value first. The only difference between checking the key first - // or the checking the value first is the order in which we pass them. - return blink::TraceKeyValuePairTraits< - Value, Key, typename Traits::ValueTraits, typename Traits::KeyTraits, - false>::IsAlive(self.value, self.key); - } - // Check key first. - return blink::TraceKeyValuePairTraits< - Key, Value, typename Traits::KeyTraits, typename Traits::ValueTraits, - false>::IsAlive(self.key, self.value); + // Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong + // (ephemeron). Order of invocation does not matter as tracing weak key or + // value does not have any side effects. + return blink::TraceCollectionIfEnabled< + GetWeaknessFlag<Key>(), Key, + typename Traits::KeyTraits>::IsAlive(self.key) && + blink::TraceCollectionIfEnabled< + GetWeaknessFlag<Value>(), Value, + typename Traits::ValueTraits>::IsAlive(self.value); } static bool Trace(blink::Visitor* visitor, KeyValuePair<Key, Value>& self) { - // This is the core of the ephemeron-like functionality. If there is - // weakness on the key side then we first check whether there are - // dead weak pointers on that side, and if there are we don't mark the - // value side (yet). Conversely if there is weakness on the value side - // we check that first and don't mark the key side yet if we find dead - // weak pointers. - // Corner case: If there is weakness on both the key and value side, - // and there are also strong pointers on the both sides then we could - // unexpectedly leak. The scenario is that the weak pointer on the key - // side is alive, which causes the strong pointer on the key side to be - // marked. If that then results in the object pointed to by the weak - // pointer on the value side being marked live, then the whole - // key-value entry is leaked. To avoid unexpected leaking, we disallow - // this case, but if you run into this assert, please reach out to Blink - // reviewers, and we may relax it. - static_assert(!kKeyIsWeak || !kValueIsWeak || !kKeyHasStrongRefs || - !kValueHasStrongRefs, - "this configuration is disallowed to avoid unexpected leaks"); - if ((kValueIsWeak && !kKeyIsWeak) || - (kValueIsWeak && kKeyIsWeak && !kValueHasStrongRefs)) { - // Check value first. The only difference between checking the key first - // or the checking the value first is the order in which we pass them. - return blink::TraceKeyValuePairTraits< - Value, Key, typename Traits::ValueTraits, typename Traits::KeyTraits, - false>::Trace(visitor, self.value, self.key); - } - // Check key first. - return blink::TraceKeyValuePairTraits< - Key, Value, typename Traits::KeyTraits, typename Traits::ValueTraits, - false>::Trace(visitor, self.key, self.value); + EphemeronHelper helper(&self.key, &self.value); + return visitor->VisitEphemeronKeyValuePair( + helper.key, helper.value, + blink::TraceCollectionIfEnabled< + GetWeaknessFlag<typename EphemeronHelper::KeyType>(), + typename EphemeronHelper::KeyType, + typename EphemeronHelper::KeyTraits>::Trace, + blink::TraceCollectionIfEnabled< + GetWeaknessFlag<typename EphemeronHelper::ValueType>(), + typename EphemeronHelper::ValueType, + typename EphemeronHelper::ValueTraits>::Trace); } };
diff --git a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc index 75169aa..708d7c9 100644 --- a/third_party/blink/renderer/platform/heap/unified_heap_controller.cc +++ b/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
@@ -181,6 +181,12 @@ class_id != WrapperTypeInfo::kObjectClassId) return; + // We should not reset any handles during an already running tracing + // collection. Resetting a handle could re-allocate a backing or trigger + // potential in place rehashing. Both operations may trigger write barriers by + // moving references. Such references may already be dead but not yet cleared + // which would result in reporting dead objects to V8. + DCHECK(IsTracingDone()); // Clearing the wrapper below adjusts the DOM wrapper store which may // re-allocate its backing. We have to avoid report memory to V8 as that may // trigger GC during GC.
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 7fe40cc..c932782 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -267,10 +267,6 @@ name: "CacheInlineScriptCode" }, { - name: "CacheStorageAddAllRejectsDuplicates", - status: "stable", - }, - { name: "Canvas2dContextLostRestored", status: "experimental", },
diff --git a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item index 89bce3b..a4324a0 100644 --- a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item +++ b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
@@ -3584,7 +3584,6 @@ crbug.com/420008 http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile-no-url-end-to-end.js [ Crash ] crbug.com/420008 http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js [ Crash ] crbug.com/420008 crbug.com/916975 http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Crash Failure Pass Timeout ] -crbug.com/420008 http/tests/devtools/tracing/timeline-misc/timeline-event-details.js [ Crash ] crbug.com/420008 http/tests/devtools/tracing/timeline-misc/timeline-event-dispatch.js [ Timeout ] crbug.com/420008 http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Crash ] crbug.com/982194 http/tests/devtools/unit/datagrid-editable-longtext.js [ Crash ] @@ -6107,7 +6106,6 @@ crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile-end-to-end.js [ Crash Pass ] crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js [ Crash Pass ] crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Crash Failure ] -crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-details.js [ Crash Pass ] crbug.com/420008 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-dispatch.js [ Timeout ] crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Crash ] crbug.com/982194 virtual/threaded/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Crash Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index db5feb5..7fd8df8 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1265,6 +1265,7 @@ crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/tall-float1.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/tall-float2.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/three-inner-rows.html [ Failure ] +crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/transform-inside-opacity.html [ Failure ] crbug.com/874506 virtual/layout_ng_block_frag/fast/multicol/unsplittable-inline-block.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/vertical-lr/break-properties.html [ Failure ] @@ -5744,6 +5745,14 @@ crbug.com/963183 http/tests/devtools/network/waterfall-header-height-updates.js [ Pass Failure ] crbug.com/963183 http/tests/devtools/network/network-search.js [ Pass Timeout Failure ] +# Temporarily disabled for landing productregistry removal in devtools +crbug.com/1011466 http/tests/devtools/console/console-format-classes.js [ Pass Failure ] +crbug.com/1011466 http/tests/devtools/modules-load-initial.js [ Pass Failure ] +crbug.com/1011466 http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js [ Pass Failure ] +crbug.com/1011466 http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js [ Pass Failure ] +crbug.com/1011466 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js [ Pass Failure ] +crbug.com/1011466 virtual/threaded/http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js [ Pass Failure ] + # Sheriff 2019-11-04 crbug.com/1021407 [ Retina Release ] virtual/audio-service/media/video-controls-rendering.html [ Pass Failure ] crbug.com/1021407 [ Mac10.11 ] virtual/audio-service/media/controls/video-overlay-cast-dark-rendering.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index 2f08514c..d8fa4c98 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -126085,6 +126085,9 @@ "content-security-policy/frame-src/frame-src-redirect.html.headers": [ [] ], + "content-security-policy/frame-src/frame-src-same-document.html.headers": [ + [] + ], "content-security-policy/frame-src/support/frame.html": [ [] ], @@ -160702,9 +160705,6 @@ "html/semantics/embedded-content/the-iframe-element/same_origin_grandchild.html": [ [] ], - "html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes-expected.txt": [ - [] - ], "html/semantics/embedded-content/the-iframe-element/stash.py": [ [] ], @@ -201188,6 +201188,18 @@ {} ] ], + "content-security-policy/frame-src/frame-src-same-document-meta.html": [ + [ + "content-security-policy/frame-src/frame-src-same-document-meta.html", + {} + ] + ], + "content-security-policy/frame-src/frame-src-same-document.html": [ + [ + "content-security-policy/frame-src/frame-src-same-document.html", + {} + ] + ], "content-security-policy/frame-src/frame-src-self-unique-origin.html": [ [ "content-security-policy/frame-src/frame-src-self-unique-origin.html", @@ -342449,6 +342461,18 @@ "338bea13b84a2f5c4d95b778637409e2bf8d3263", "support" ], + "content-security-policy/frame-src/frame-src-same-document-meta.html": [ + "f3750b1e7d83fb50089a1b643045b89df223dff4", + "testharness" + ], + "content-security-policy/frame-src/frame-src-same-document.html": [ + "398d0223bcb7cf3fad9086c424510bbfcdcdc818", + "testharness" + ], + "content-security-policy/frame-src/frame-src-same-document.html.headers": [ + "6502444407f59e6ea08da63c8dcdb22978e5ae83", + "support" + ], "content-security-policy/frame-src/frame-src-self-unique-origin.html": [ "947b11e063de776b4d9afffb91e1667460d9099f", "testharness" @@ -440566,7 +440590,7 @@ "testharness" ], "fetch/api/response/response-consume.html": [ - "4946a4d33a437af657d4440b270bec3f56534d0a", + "7a9c6505d80f3feff2ffa297df03cf37e546f0d7", "testharness" ], "fetch/api/response/response-error-from-stream-expected.txt": [ @@ -456369,12 +456393,8 @@ "fe72333d1a638966e14e46fdb6b0bdf21beaa75d", "testharness" ], - "html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes-expected.txt": [ - "6bc9fd1a201d8a102d3ac7a7f2a47671bf85764b", - "support" - ], "html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes.html": [ - "397c95a23911ef979718a3aa8b879d257803fb85", + "0bd9f9b2295813f0a4664c01a9594ba94d76233d", "testharness" ], "html/semantics/embedded-content/the-iframe-element/stash.py": [ @@ -464926,7 +464946,7 @@ "support" ], "interfaces/appmanifest.idl": [ - "4a6425829f23da3cd1f78f74ff52a18635f7af7c", + "b3a303652f53d2ca225fbd8da4899d3eefe6aa15", "support" ], "interfaces/audio-output.idl": [ @@ -465246,7 +465266,7 @@ "support" ], "interfaces/picture-in-picture.idl": [ - "3323fc1f099f86ebd06a85baabfe953211be3ae1", + "3d3bad08219af2e422f2cb0d4cabeffa1f8a2b80", "support" ], "interfaces/pointerevents-extension.idl": [ @@ -465386,7 +465406,7 @@ "support" ], "interfaces/web-nfc.idl": [ - "117812a1f276d0bb84de94c2357485d7670ad314", + "9f726ece289dde08facf194c40b59539d8e799c2", "support" ], "interfaces/web-share.idl": [ @@ -514202,7 +514222,7 @@ "support" ], "web-nfc/idlharness.https.window-expected.txt": [ - "3fc1349ad8db416afa3f5a31574b288900483b99", + "6f05c69de7629c8967c925532c7e0b1d0742de8a", "support" ], "web-nfc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes-expected.txt deleted file mode 100644 index 6bc9fd1a..0000000 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL Adding `srcdoc` attribute triggers attributes processing assert_false: expected false got true -FAIL Changing `srcdoc` (via property) triggers attributes processing assert_false: expected false got true -FAIL Removing `srcdoc` attribute triggers attributes processing assert_false: expected false got true -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes.html index 397c95a..0bd9f9b2 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc_process_attributes.html
@@ -20,7 +20,7 @@ assert_equals(iframe.contentDocument.body.textContent, "src"); iframe.onload = t.step_func_done(function() { - assert_false(isAdded); + assert_true(isAdded); assert_equals(iframe.contentDocument.location.href, "about:srcdoc"); assert_equals(iframe.contentDocument.body.textContent, "srcdoc"); }); @@ -41,7 +41,7 @@ assert_equals(iframe.contentDocument.body.textContent, "old"); iframe.onload = t.step_func_done(function() { - assert_false(isChanged); + assert_true(isChanged); assert_equals(iframe.contentDocument.location.href, "about:srcdoc"); assert_equals(iframe.contentDocument.body.textContent, "new"); }); @@ -51,7 +51,7 @@ }); document.body.appendChild(iframe); -}, "Changing `srcdoc` (via property) triggers attributes processing"); +}, "Setting `srcdoc` (via property) triggers attributes processing"); async_test(function(t) { var iframe = createIFrameWithBlobSrc(); @@ -62,7 +62,7 @@ assert_equals(iframe.contentDocument.body.textContent, "srcdoc"); iframe.onload = t.step_func_done(function() { - assert_false(isRemoved); + assert_true(isRemoved); assert_equals(iframe.contentDocument.location.protocol, "blob:"); assert_equals(iframe.contentDocument.body.textContent, "src"); });
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/multiTouchPoints.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/multiTouchPoints.html new file mode 100644 index 0000000..c816973 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/actions/multiTouchPoints.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: two touch points with one moving one pause</title> +<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> + +<style> +div#test1{ + position: fixed; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +let event_type = []; +let event_id = []; + +async_test(t => { + let test1 = document.getElementById("test1"); + document.getElementById("test1").addEventListener("pointerdown", + e => {event_type.push(e.type); event_id.push(e.pointerId);}); + document.getElementById("test1").addEventListener("pointerup", + e => {event_type.push(e.type); event_id.push(e.pointerId);}); + document.getElementById("test1").addEventListener("pointermove", + e => {event_type.push(e.type); event_id.push(e.pointerId);}); + + let actions = new test_driver.Actions() + .addPointer("touchPointer1", "touch") + .addPointer("touchPointer2", "touch") + .pointerMove(0, 0, {origin: test1, sourceName: "touchPointer1"}) + .pointerMove(10, 0, {origin: test1, sourceName: "touchPointer2"}) + .pointerDown({sourceName: "touchPointer1"}) + .pointerDown({sourceName: "touchPointer2"}) + .pointerMove(0, 10, {origin: test1, sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer2"}); + + actions.send() + .then(t.step_func_done(() => {assert_array_equals(event_type, ["pointerdown", "pointerdown", "pointermove", "pointerup", "pointerup"]); + assert_array_equals(event_id, [2, 3, 2, 2, 3]);})) + .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl b/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl index 4a642582..b3a3036 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/appmanifest.idl
@@ -42,6 +42,7 @@ ServiceWorkerRegistrationObject serviceworker; sequence<ExternalApplicationResource> related_applications; boolean prefer_related_applications = "false"; + sequence<ShortcutItem> shortcuts; }; enum TextDirectionType { "ltr", "rtl", "auto" }; @@ -61,6 +62,14 @@ USVString platform; }; +dictionary ShortcutItem { + required USVString name; + USVString short_name; + USVString description; + required USVString url; + sequence<ImageResource> icons; +}; + dictionary ServiceWorkerRegistrationObject { required USVString src; USVString scope;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl b/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl index 3323fc1..3d3bad0 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl
@@ -31,11 +31,9 @@ attribute EventHandler onresize; }; -[ - Constructor(DOMString type, EnterPictureInPictureEventInit eventInitDict), - Exposed=Window -] +[Exposed=Window] interface EnterPictureInPictureEvent : Event { + constructor(DOMString type, EnterPictureInPictureEventInit eventInitDict); [SameObject] readonly attribute PictureInPictureWindow pictureInPictureWindow; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl index 117812a1..9f726ece 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl
@@ -52,6 +52,7 @@ interface NDEFReader : EventTarget { constructor(); + attribute EventHandler onerror; attribute EventHandler onreading; Promise<void> scan(optional NDEFScanOptions options={});
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt index 3fc1349..6f05c69 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 70 tests; 68 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 72 tests; 70 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS NDEFMessage interface: existence and properties of interface object @@ -51,10 +51,12 @@ PASS NDEFReader interface: existence and properties of interface prototype object PASS NDEFReader interface: existence and properties of interface prototype object's "constructor" property PASS NDEFReader interface: existence and properties of interface prototype object's @@unscopables property +PASS NDEFReader interface: attribute onerror PASS NDEFReader interface: attribute onreading FAIL NDEFReader interface: operation scan(NDEFScanOptions) assert_unreached: Throws "TypeError: Illegal invocation" instead of rejecting promise Reached unreachable code PASS NDEFReader must be primary interface of new NDEFReader(); PASS Stringification of new NDEFReader(); +PASS NDEFReader interface: new NDEFReader(); must inherit property "onerror" with the proper type PASS NDEFReader interface: new NDEFReader(); must inherit property "onreading" with the proper type PASS NDEFReader interface: new NDEFReader(); must inherit property "scan(NDEFScanOptions)" with the proper type PASS NDEFReader interface: calling scan(NDEFScanOptions) on new NDEFReader(); with too few arguments must throw TypeError
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt index 4578e8c..afc84ea 100644 --- a/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/console/console-format-classes-expected.txt
@@ -6,8 +6,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text object-value-error source-code devtools-link @@ -17,8 +15,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-array source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -40,8 +36,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-object source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -59,8 +53,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-object source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -86,8 +78,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-object source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -111,8 +101,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-proxy source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -131,8 +119,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-array source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow @@ -158,8 +144,6 @@ source-code console-message-anchor devtools-link - hidden console-message-badge - hide-badge-title console-message-text console-view-object-properties-section object-value-array source-code tree-outline-disclosure tree-outline-disclosure-hide-overflow
diff --git a/third_party/blink/web_tests/http/tests/devtools/modules-load-initial-expected.txt b/third_party/blink/web_tests/http/tests/devtools/modules-load-initial-expected.txt index 0d01d5a..15c6280 100644 --- a/third_party/blink/web_tests/http/tests/devtools/modules-load-initial-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/modules-load-initial-expected.txt
@@ -15,7 +15,6 @@ mobile_throttling persistence platform - product_registry protocol sdk services
diff --git a/third_party/blink/web_tests/http/tests/devtools/sha1-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sha1-expected.txt deleted file mode 100644 index 8b74348..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/sha1-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -Tests SHA-1 hashes. - -foobar : 8843d7f92416211de9ebb963ff4ce28125932878 -hello : aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d -abcdefghijklmnopqrstuvwxyz : 32d10c7b8cf96570ca04ce37f2a19d84240d3a89 -ABCDEFGHIJKLMNOPQRSTUVWXYZ : 80256f39a9d308650ac90d9be9a72a9562454574 -a : 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 -A : 6dcd4ce23d88e2ee9568ba546c007c63d9131c1b -A1 : 1ffd4ba3eb9ffadf4db3c3ff4c1bbcf94a64cc59 -
diff --git a/third_party/blink/web_tests/http/tests/devtools/sha1.js b/third_party/blink/web_tests/http/tests/devtools/sha1.js deleted file mode 100644 index 5228cc1..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/sha1.js +++ /dev/null
@@ -1,17 +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. - -(async function() { - TestRunner.addResult(`Tests SHA-1 hashes.\n`); - await TestRunner.loadModule('product_registry_impl'); - - TestRunner.addResult('foobar : ' + ProductRegistryImpl.sha1('foobar')); - TestRunner.addResult('hello : ' + ProductRegistryImpl.sha1('hello')); - TestRunner.addResult('abcdefghijklmnopqrstuvwxyz : ' + ProductRegistryImpl.sha1('abcdefghijklmnopqrstuvwxyz')); - TestRunner.addResult('ABCDEFGHIJKLMNOPQRSTUVWXYZ : ' + ProductRegistryImpl.sha1('ABCDEFGHIJKLMNOPQRSTUVWXYZ')); - TestRunner.addResult('a : ' + ProductRegistryImpl.sha1('a')); - TestRunner.addResult('A : ' + ProductRegistryImpl.sha1('A')); - TestRunner.addResult('A1 : ' + ProductRegistryImpl.sha1('A1')); - TestRunner.completeTest(); -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details-expected.txt index 516b3f91b..ebd3aa4 100644 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details-expected.txt
@@ -1,7 +1,5 @@ Test timeline aggregated details. -Cleared ProductRegistryImpl -Adding entry: *.google.com CallTree Group by: None @@ -371,7 +369,7 @@ Function Call: 0.600 1.000 Other: 0.600 1.000 Other: 260.000 300.000 - google.com — Google: 0.215 0.215 + google.com: 0.215 0.215 recursive_b: 0.110 0.114 recursive_a: 0.110 0.114 recursive_b: 0.008 0.008 @@ -467,103 +465,7 @@ Function Call: 0.600 1.000 Other: 0.600 1.000 Other: 260.000 300.000 - www.google.com — Google: 0.215 0.215 - recursive_b: 0.110 0.114 - recursive_a: 0.110 0.114 - recursive_b: 0.008 0.008 - recursive_a: 0.008 0.008 - Function Call: 0.008 0.008 - Other: 0.008 0.008 - Function Call: 0.102 0.106 - Other: 0.102 0.114 - recursive_a: 0.105 0.215 - recursive_b: 0.004 0.012 - recursive_a: 0.004 0.012 - Function Call: 0.004 0.012 - Other: 0.004 0.012 - Function Call: 0.101 0.203 - Other: 0.101 0.215 - -CallTree Group by: Product - [unattributed]: 260.000 300.000 - Other: 260.000 300.000 - Function Call: 17.660 40.000 - a: 0.000 11.125 - b: 0.000 11.125 - c: 8.250 8.250 - e: 0.000 2.875 - g: 2.875 2.875 - f: 0.000 0.125 - l: 0.000 0.125 - a: 0.025 0.125 - Layout: 0.100 0.100 - sin: 0.000 9.875 - f: 0.000 9.875 - l: 0.000 9.875 - a: 9.875 9.875 - Function Call: 0.000 1.000 - x: 0.000 1.000 - y: 0.600 1.000 - z: 0.000 0.200 - w: 0.200 0.200 - w: 0.200 0.200 - recursive_a: 0.101 0.215 - recursive_b: 0.102 0.114 - recursive_a: 0.004 0.012 - recursive_b: 0.008 0.008 - -BottomUp Group by: Product - [unattributed]: 299.785 299.785 - c: 8.250 8.250 - b: 8.250 8.250 - a: 8.250 8.250 - Function Call: 8.250 8.250 - Other: 8.250 8.250 - a: 9.900 21.125 - Function Call: 0.000 11.125 - Other: 0.000 11.125 - l: 9.900 10.000 - f: 9.900 10.000 - Function Call: 0.025 0.125 - Other: 0.025 0.125 - sin: 9.875 9.875 - Function Call: 9.875 9.875 - Other: 9.875 9.875 - g: 2.875 2.875 - e: 2.875 2.875 - b: 2.875 2.875 - a: 2.875 2.875 - Function Call: 2.875 2.875 - Other: 2.875 2.875 - Layout: 0.100 0.100 - a: 0.100 0.100 - l: 0.100 0.100 - f: 0.100 0.100 - Function Call: 0.100 0.100 - Other: 0.100 0.100 - Function Call: 17.660 40.000 - Other: 17.660 38.000 - Function Call: 0.000 1.000 - Other: 0.000 1.000 - w: 0.400 0.400 - z: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - Function Call: 0.200 0.200 - Function Call: 0.200 0.200 - Other: 0.200 0.200 - y: 0.200 0.200 - x: 0.200 0.200 - Function Call: 0.200 0.200 - Function Call: 0.200 0.200 - Other: 0.200 0.200 - y: 0.600 1.000 - x: 0.600 1.000 - Function Call: 0.600 1.000 - Function Call: 0.600 1.000 - Other: 0.600 1.000 - Other: 260.000 300.000 - Google: 0.215 0.215 + www.google.com: 0.215 0.215 recursive_b: 0.110 0.114 recursive_a: 0.110 0.114 recursive_b: 0.008 0.008
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js index 5da8ad9..bb86ad7f 100644 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-aggregated-details.js
@@ -8,9 +8,6 @@ await TestRunner.loadModule('network_test_runner'); await TestRunner.showPanel('timeline'); - await ProductRegistry.instance(); - NetworkTestRunner.resetProductRegistry(); - NetworkTestRunner.addProductRegistryEntry('*.google.com', 'Google'); TestRunner.addResult(''); var sessionId = '6.23'; @@ -565,7 +562,6 @@ var timeline = UI.panels.timeline; timeline._setModel(PerformanceTestRunner.createPerformanceModelWithEvents(rawTraceEvents)); - await ProductRegistry.instance(); var groupByEnum = Timeline.AggregatedTimelineTreeView.GroupBy; for (var grouping of Object.values(groupByEnum)) { testEventTree('CallTree', grouping);
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details-expected.txt deleted file mode 100644 index d1fb6c55..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -Checks the Product property in details pane for a node with URL. - -Cleared ProductRegistryImpl -Adding entry: *.google.com - -Script: www.google.com:1337 -: Google -
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details.js deleted file mode 100644 index 755159dd..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-details.js +++ /dev/null
@@ -1,75 +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. - -(async function() { - TestRunner.addResult(`Checks the Product property in details pane for a node with URL.\n`); - await TestRunner.loadModule('performance_test_runner'); - await TestRunner.loadModule('network_test_runner'); - await TestRunner.showPanel('timeline'); - - await ProductRegistry.instance(); - NetworkTestRunner.resetProductRegistry(); - NetworkTestRunner.addProductRegistryEntry('*.google.com', 'Google'); - TestRunner.addResult(''); - - var sessionId = '6.23'; - var rawTraceEvents = [ - { - 'args': {'name': 'Renderer'}, - 'cat': '__metadata', - 'name': 'process_name', - 'ph': 'M', - 'pid': 17851, - 'tid': 23, - 'ts': 0 - }, - { - 'args': {'name': 'CrRendererMain'}, - 'cat': '__metadata', - 'name': 'thread_name', - 'ph': 'M', - 'pid': 17851, - 'tid': 23, - 'ts': 0 - }, - { - 'args': {'data': {'sessionId': sessionId, 'frames': [ - {'frame': 'frame1', 'url': 'frameurl', 'name': 'frame-name'} - ]}}, - 'cat': 'disabled-by-default-devtools.timeline', - 'name': 'TracingStartedInPage', - 'ph': 'I', - 'pid': 17851, - 'tid': 23, - 'ts': 100000, - 'tts': 606543 - }, - { - 'cat': 'disabled-by-default-devtools.timeline', - 'name': 'EvaluateScript', - 'ph': 'X', - 'pid': 17851, - 'tid': 23, - 'ts': 101000, - 'dur': 10000, - 'args': {'data': {'url': 'https://www.google.com', 'lineNumber': 1337}} - } - ]; - - var badgeRendered = Promise.resolve(); - TestRunner.addSniffer( - ProductRegistry.BadgePool.prototype, '_renderBadge', (arg, result) => badgeRendered = result, true); - Common.settings.moduleSetting('product_registry.badges-visible').set(true); - var model = PerformanceTestRunner.createPerformanceModelWithEvents(rawTraceEvents).timelineModel(); - var linkifier = new Components.Linkifier(); - var badgePool = new ProductRegistry.BadgePool(); - for (var event of PerformanceTestRunner.mainTrackEvents()) { - var node = await Timeline.TimelineUIUtils.buildTraceEventDetails(event, model, linkifier, badgePool); - await badgeRendered; - for (var child of node.querySelectorAll('.timeline-details-view-row')) - TestRunner.addResult( - TestRunner.deepTextContent(child.firstChild) + ': ' + TestRunner.deepTextContent(child.lastChild)); - } - TestRunner.completeTest(); -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js index 0435720e..ea443157 100644 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js
@@ -27,10 +27,9 @@ var model = PerformanceTestRunner.timelineModel(); var linkifier = new Components.Linkifier(); - var badgePool = new ProductRegistry.BadgePool(); for (var request of model.networkRequests()) { - var element = await Timeline.TimelineUIUtils.buildNetworkRequestDetails(request, model, linkifier, badgePool); + var element = await Timeline.TimelineUIUtils.buildNetworkRequestDetails(request, model, linkifier); printElement(element); } TestRunner.completeTest();
diff --git a/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity-expected.txt b/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity-expected.txt deleted file mode 100644 index f2f01b9..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This tests product registry impl's register function. -Cleared ProductRegistryImpl -Testing: example.com -> example.(com|org) -Testing: wild.example.com -> *.example.com -Testing: test-1.example.com -> test-*.example.com -Testing: subdomain.example.com -> subdomain.example.com -Testing: example.org -> example.(com|org) -Testing: chromium.org -> null -
diff --git a/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity.js b/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity.js deleted file mode 100644 index 2437250..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/unit/product-registry-impl-register-sanity.js +++ /dev/null
@@ -1,62 +0,0 @@ -(async function(){ - await TestRunner.loadModule('product_registry_impl'); - TestRunner.addResult("This tests product registry impl's register function."); - - resetProductRegistry(); - ProductRegistryImpl.register([ - "example.(com|org)", - "*.example.com", - "test-*.example.com", - "subdomain.example.com" - ], [ - { - hash: "0caaf24ab1a0c334", // Result of: sha1('example.com').substr(0, 16). - prefixes: { - "": { - product: 0 // Reference to index of first argument of ProductRegistryImpl.register. - }, - "*": { - product: 1 - }, - "test-": { - product: 2 - } - } - }, - { - hash: "20116dfd6774a9e7", // Result of: sha1('example.org').substr(0, 16). - prefixes: { - "": { - product: 0 - } - } - }, - { - hash: "e3d90251f85e2064", // Result of: sha1('subdomain.example.com').substr(0, 16). - prefixes: { - "": { - product: 3 - } - } - } - ]); - var instance = new ProductRegistryImpl.Registry(); - - logDomainEntry('example.com'); - logDomainEntry('wild.example.com'); - logDomainEntry('test-1.example.com'); - logDomainEntry('subdomain.example.com'); - logDomainEntry('example.org'); - logDomainEntry('chromium.org'); - - TestRunner.completeTest(); - - function logDomainEntry(domainStr) { - TestRunner.addResult("Testing: " + domainStr + " -> " + instance.nameForUrl(('http://' + domainStr).asParsedURL())); - } - - function resetProductRegistry() { - TestRunner.addResult("Cleared ProductRegistryImpl"); - ProductRegistryImpl._productsByDomainHash.clear(); - } -})();
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn index bd2de53..225a6bae 100644 --- a/third_party/breakpad/BUILD.gn +++ b/third_party/breakpad/BUILD.gn
@@ -384,7 +384,7 @@ "breakpad/src/client/mac/handler/dynamic_images.cc", "breakpad/src/client/mac/handler/minidump_generator.cc", "breakpad/src/client/minidump_file_writer.cc", - "breakpad/src/common/convert_UTF.c", + "breakpad/src/common/convert_UTF.cc", "breakpad/src/common/mac/MachIPC.mm", "breakpad/src/common/mac/arch_utilities.cc", "breakpad/src/common/mac/bootstrap_compat.cc", @@ -598,7 +598,7 @@ "breakpad/src/client/minidump_file_writer-inl.h", "breakpad/src/client/minidump_file_writer.cc", "breakpad/src/client/minidump_file_writer.h", - "breakpad/src/common/convert_UTF.c", + "breakpad/src/common/convert_UTF.cc", "breakpad/src/common/convert_UTF.h", "breakpad/src/common/linux/elf_core_dump.cc", "breakpad/src/common/linux/elf_core_dump.h", @@ -1017,7 +1017,7 @@ "breakpad/src/client/minidump_file_writer-inl.h", "breakpad/src/client/minidump_file_writer.cc", "breakpad/src/client/minidump_file_writer.h", - "breakpad/src/common/convert_UTF.c", + "breakpad/src/common/convert_UTF.cc", "breakpad/src/common/convert_UTF.h", "breakpad/src/common/long_string_dictionary.cc", "breakpad/src/common/mac/HTTPMultipartUpload.m",
diff --git a/third_party/crashpad/crashpad/util/linux/proc_stat_reader_test.cc b/third_party/crashpad/crashpad/util/linux/proc_stat_reader_test.cc index bc0d65b..1a8a1afb9 100644 --- a/third_party/crashpad/crashpad/util/linux/proc_stat_reader_test.cc +++ b/third_party/crashpad/crashpad/util/linux/proc_stat_reader_test.cc
@@ -19,6 +19,7 @@ #include <unistd.h> #include "base/logging.h" +#include "build/build_config.h" #include "gtest/gtest.h" #include "test/linux/fake_ptrace_connection.h" #include "util/thread/thread.h" @@ -74,7 +75,13 @@ timeval* start_time_; }; -TEST(ProcStatReader, Threads) { +// TODO(https://crbug.com/1016765): Flaky on Linux. +#if defined(OS_LINUX) +#define MAYBE_Threads DISABLED_Threads +#else +#define MAYBE_Threads Threads +#endif +TEST(ProcStatReader, MAYBE_Threads) { timeval main_time; ASSERT_NO_FATAL_FAILURE(GetStartTime(&main_time));
diff --git a/third_party/protobuf/proto_library.gni b/third_party/protobuf/proto_library.gni index 0e90809..570165e 100644 --- a/third_party/protobuf/proto_library.gni +++ b/third_party/protobuf/proto_library.gni
@@ -107,6 +107,16 @@ import("//build/config/sanitizers/sanitizers.gni") +if (host_os == "win") { + _host_executable_suffix = ".exe" +} else { + _host_executable_suffix = "" +} + +_protoc_label = "//third_party/protobuf:protoc($host_toolchain)" +_protoc_path = get_label_info(_protoc_label, "root_out_dir") + "/protoc" + + _host_executable_suffix + template("proto_library") { assert(defined(invoker.sources), "Need sources for proto_library") proto_sources = invoker.sources @@ -117,12 +127,6 @@ # this template shouldn't re-apply the filter. set_sources_assignment_filter([]) - if (host_os == "win") { - host_executable_suffix = ".exe" - } else { - host_executable_suffix = "" - } - if (defined(invoker.generate_cc)) { generate_cc = invoker.generate_cc } else { @@ -143,7 +147,7 @@ plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)" plugin_path = get_label_info(plugin_host_label, "root_out_dir") + "/" + - get_label_info(plugin_host_label, "name") + host_executable_suffix + get_label_info(plugin_host_label, "name") + _host_executable_suffix generate_with_plugin = true } else if (defined(invoker.generator_plugin_script)) { plugin_path = invoker.generator_plugin_script @@ -244,15 +248,12 @@ outputs = get_path_info(protogens + protogens_cc, "abspath") args = protos - protoc_label = "//third_party/protobuf:protoc($host_toolchain)" - protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" + - host_executable_suffix args += [ # Wrapper should never pick a system protoc. # Path should be rebased because |root_build_dir| for current toolchain # may be different from |root_out_dir| of protoc built on host toolchain. "--protoc", - "./" + rebase_path(protoc_path, root_build_dir), + "./" + rebase_path(_protoc_path, root_build_dir), "--proto-in-dir", rebase_path(proto_in_dir, root_build_dir), ] @@ -306,10 +307,10 @@ # System protoc is not used so it's necessary to build a chromium one. inputs = [ - protoc_path, + _protoc_path, ] deps = [ - protoc_label, + _protoc_label, ] if (generate_with_plugin) { @@ -480,7 +481,7 @@ inputs = invoker.inputs deps = [ - "//third_party/protobuf:protoc", + _protoc_label, ] if (defined(invoker.deps)) { deps += invoker.deps @@ -492,7 +493,7 @@ args = [ "--protoc", - rebase_path("$root_out_dir/protoc"), + "./" + rebase_path(_protoc_path, root_build_dir), "--infile", "{{source}}", "--outfile",
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py index 6a8e862..cfb49ab 100755 --- a/tools/binary_size/diagnose_bloat.py +++ b/tools/binary_size/diagnose_bloat.py
@@ -39,8 +39,8 @@ _SRC_ROOT, 'build', 'android', 'resource_sizes.py') _LLVM_TOOLS_DIR = os.path.join( _SRC_ROOT, 'third_party', 'llvm-build', 'Release+Asserts', 'bin') -_DOWNLOAD_OBJDUMP_PATH = os.path.join( - _SRC_ROOT, 'tools', 'clang', 'scripts', 'download_objdump.py') +_CLANG_UPDATE_PATH = os.path.join(_SRC_ROOT, 'tools', 'clang', 'scripts', + 'update.py') _GN_PATH = os.path.join(_SRC_ROOT, 'third_party', 'depot_tools', 'gn') _NINJA_PATH = os.path.join(_SRC_ROOT, 'third_party', 'depot_tools', 'ninja') @@ -767,9 +767,9 @@ shutil.copytree(_BINARY_SIZE_DIR, bs_dir) # We also copy the tools supersize needs, but only if they exist. tool_prefix = None - if os.path.exists(_DOWNLOAD_OBJDUMP_PATH): + if os.path.exists(_CLANG_UPDATE_PATH): if not os.path.exists(os.path.join(_LLVM_TOOLS_DIR, 'llvm-readelf')): - _RunCmd([_DOWNLOAD_OBJDUMP_PATH]) + _RunCmd([_CLANG_UPDATE_PATH, '--package=objdump']) tools_dir = os.path.join(bs_dir, 'bintools') tool_prefix = os.path.join(tools_dir, 'llvm-') shutil.copytree(_LLVM_TOOLS_DIR, tools_dir)
diff --git a/tools/binary_size/libsupersize/linker_map_parser.py b/tools/binary_size/libsupersize/linker_map_parser.py index dc3988aa..826bff2 100755 --- a/tools/binary_size/libsupersize/linker_map_parser.py +++ b/tools/binary_size/libsupersize/linker_map_parser.py
@@ -495,11 +495,11 @@ # PROVIDE_HIDDEN lines. if level == 1: # Ignore sections that belong to feature library partitions. Seeing a - # library name is an indicator that we've entered a list of feature + # partition name is an indicator that we've entered a list of feature # partitions. After these, a single .part.end section will follow to # reserve memory at runtime. Seeing the .part.end section also marks the # end of partition sections in the map file. - if tok.startswith('lib') and tok.endswith('.so'): + if tok.endswith('_partition'): in_partitions = True elif tok == '.part.end': # Note that we want to retain .part.end section, so it's fine to
diff --git a/tools/binary_size/libsupersize/path_util.py b/tools/binary_size/libsupersize/path_util.py index 0a16c6e..356d0ff 100644 --- a/tools/binary_size/libsupersize/path_util.py +++ b/tools/binary_size/libsupersize/path_util.py
@@ -112,7 +112,7 @@ err_lines = ['tool-prefix not found: %s' % ret] if ret.endswith('llvm-'): err_lines.append('Probably need to run: ' - 'tools/clang/scripts/download_objdump.py') + 'tools/clang/scripts/update.py --package=objdump') raise Exception('\n'.join(err_lines)) from_path = distutils.spawn.find_executable(_SAMPLE_TOOL_SUFFIX) if from_path:
diff --git a/tools/binary_size/libsupersize/testdata/linker_map_parser/Tokenize.golden b/tools/binary_size/libsupersize/testdata/linker_map_parser/Tokenize.golden index cc142f5..f796a65 100644 --- a/tools/binary_size/libsupersize/testdata/linker_map_parser/Tokenize.golden +++ b/tools/binary_size/libsupersize/testdata/linker_map_parser/Tokenize.golden
@@ -226,8 +226,8 @@ 2F56008 4 (3) 0 WebRtcSpl_MaxAbsValueW16 2F56008 4 (3) 0 WebRtcSpl_MaxAbsValueW16 2F56008 4 (3) 4 WebRtcSpl_MaxAbsValueW16 - 34BE000 34 (1) -------- libvr.so - 34BE000 34 (2) -------- <internal>:(libvr.so) + 34BE000 34 (1) -------- vr_partition + 34BE000 34 (2) -------- <internal>:(vr_partition) 34BE034 140 (1) -------- .phdrs 34BE034 140 (2) -------- <internal>:(.phdrs) 34BE174 13 (1) -------- .interp
diff --git a/tools/binary_size/libsupersize/testdata/linker_map_parser/test_lld-lto_v1.map b/tools/binary_size/libsupersize/testdata/linker_map_parser/test_lld-lto_v1.map index ff0713f..9658718 100644 --- a/tools/binary_size/libsupersize/testdata/linker_map_parser/test_lld-lto_v1.map +++ b/tools/binary_size/libsupersize/testdata/linker_map_parser/test_lld-lto_v1.map
@@ -353,8 +353,8 @@ # Partitions should be ignored at this point. Otherwise, their .text, .rodata, # etc. sections will overwrite those of the main partition. - 34be000 34be000 34 1 libvr.so - 34be000 34be000 34 1 <internal>:(libvr.so) + 34be000 34be000 34 1 vr_partition + 34be000 34be000 34 1 <internal>:(vr_partition) 34be034 34be034 140 1 .phdrs 34be034 34be034 140 1 <internal>:(.phdrs) 34be174 34be174 13 1 .interp
diff --git a/tools/clang/scripts/download_lld_mac.py b/tools/clang/scripts/download_lld_mac.py index 3bb2b68..a2af710 100755 --- a/tools/clang/scripts/download_lld_mac.py +++ b/tools/clang/scripts/download_lld_mac.py
@@ -5,34 +5,12 @@ """Script to download lld/mac from google storage.""" -import os -import re -import subprocess import sys import update -LLVM_BUILD_DIR = update.LLVM_BUILD_DIR -LLD_LINK_PATH = os.path.join(LLVM_BUILD_DIR, 'bin', 'lld-link') - - -def AlreadyUpToDate(): - if not os.path.exists(LLD_LINK_PATH): - return False - lld_rev = subprocess.check_output([LLD_LINK_PATH, '--version']) - # Version output example: - # LLD 9.0.0 (https://github.com/llvm/llvm-project/ 342571e8d6eb1afb151ae1103431798e3d24054f) - return (re.match(r'LLD.*\(.*git.*llvm.* ([0-9a-f]+)\)', lld_rev).group(1) == - update.CLANG_REVISION) - - -def main(): - if AlreadyUpToDate(): - return 0 - remote_path = '%s/Mac/lld-%s.tgz' % (update.CDS_URL, update.PACKAGE_VERSION) - update.DownloadAndUnpack(remote_path, update.LLVM_BUILD_DIR) - return 0 - - +# TODO(hans): Remove this forwarding hack after all callers of this script have +# been updated to call update.py instead. if __name__ == '__main__': - sys.exit(main()) + sys.argv = [sys.argv[0], '--package=lld_mac'] + sys.exit(update.main())
diff --git a/tools/clang/scripts/download_objdump.py b/tools/clang/scripts/download_objdump.py index f892227..9ecae96 100755 --- a/tools/clang/scripts/download_objdump.py +++ b/tools/clang/scripts/download_objdump.py
@@ -3,47 +3,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Script to download llvm-objdump and related utils from google storage.""" - -from __future__ import print_function - -import os -import re -import subprocess import sys -import urllib2 import update -LLVM_BUILD_DIR = update.LLVM_BUILD_DIR -OBJDUMP_PATH = os.path.join(LLVM_BUILD_DIR, 'bin', 'llvm-objdump') -STAMP_FILE = os.path.normpath( - os.path.join(LLVM_BUILD_DIR, 'llvmobjdump_build_revision')) - - -def AlreadyUpToDate(): - if not os.path.exists(OBJDUMP_PATH) or not os.path.exists(STAMP_FILE): - return False - stamp = update.ReadStampFile(STAMP_FILE) - return stamp.rstrip() == update.PACKAGE_VERSION - - -def DownloadAndUnpackLlvmObjDumpPackage(platform): - cds_file = 'llvmobjdump-%s.tgz' % update.PACKAGE_VERSION - cds_full_url = update.GetPlatformUrlPrefix(platform) + cds_file - try: - update.DownloadAndUnpack(cds_full_url, update.LLVM_BUILD_DIR) - except urllib2.URLError: - print('Failed to download prebuilt utils %s' % cds_file) - print('Use --force-local-build if you want to build locally.') - print('Exiting.') - sys.exit(1) - - -def main(): - if not AlreadyUpToDate(): - DownloadAndUnpackLlvmObjDumpPackage(sys.platform) - return 0 - +# TODO(hans): Remove this forwarding hack after all callers of this script have +# been updated to call update.py instead. if __name__ == '__main__': - sys.exit(main()) + sys.argv = [sys.argv[0], '--package=objdump'] + sys.exit(update.main())
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 2bc1145..ad4d99e 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -9,7 +9,9 @@ It can also be run stand-alone as a convenient way of installing a well-tested near-tip-of-tree clang version: - $ curl -s https://raw.githubusercontent.com/chromium/chromium/master/tools/clang/scripts/update.py | python - --clang-dir=. + $ curl -s https://raw.githubusercontent.com/chromium/chromium/master/tools/clang/scripts/update.py | python - --output-dir=/tmp/clang + +(Note that the output dir may be deleted and re-created if it exists.) """ # TODO: Running stand-alone won't work on Windows due to the dia dll copying. @@ -167,14 +169,29 @@ return CDS_URL + '/Linux_x64/' -def DownloadAndUnpackClangPackage(platform, output_dir, path_prefixes=None): +def DownloadAndUnpackPackage(package_file, output_dir): + cds_file = "%s-%s.tgz" % (package_file, PACKAGE_VERSION) + cds_full_url = GetPlatformUrlPrefix(sys.platform) + cds_file + try: + DownloadAndUnpack(cds_full_url, output_dir) + except URLError: + print('Failed to download prebuilt clang package %s' % cds_file) + print('Use build.py if you want to build locally.') + print('Exiting.') + sys.exit(1) + + +# TODO(hans): Create a clang-win-runtime package instead. +def DownloadAndUnpackClangWinRuntime(output_dir): cds_file = "clang-%s.tgz" % PACKAGE_VERSION - cds_full_url = GetPlatformUrlPrefix(platform) + cds_file + cds_full_url = GetPlatformUrlPrefix('win32') + cds_file + path_prefixes = [ 'lib/clang/' + RELEASE_VERSION + '/lib/', + 'bin/llvm-symbolizer.exe' ] try: DownloadAndUnpack(cds_full_url, output_dir, path_prefixes) except URLError: print('Failed to download prebuilt clang %s' % cds_file) - print('Use --force-local-build if you want to build locally.') + print('Use build.py if you want to build locally.') print('Exiting.') sys.exit(1) @@ -231,19 +248,46 @@ CopyFile(dia_dll, target_dir) -def UpdateClang(): - GCLIENT_CONFIG = os.path.join(os.path.dirname(CHROMIUM_DIR), '.gclient') +def UpdatePackage(package_name): + stamp_file = None + package_file = None - # Read target_os from .gclient so we know which non-native runtimes we need. - # TODO(pcc): See if we can download just the runtimes instead of the entire - # clang package, and do that from DEPS instead of here. + stamp_file = os.path.join(LLVM_BUILD_DIR, package_name + '_revision') + if package_name == 'clang': + stamp_file = STAMP_FILE + package_file = 'clang' + elif package_name == 'lld_mac': + package_file = 'lld' + if sys.platform != 'darwin': + print('The lld_mac package cannot be downloaded on non-macs.') + print('On non-mac, lld is included in the clang package.') + return 1 + elif package_name == 'objdump': + package_file = 'llvmobjdump' + elif package_name == 'translation_unit': + package_file = 'translation_unit' + elif package_name == 'coverage_tools': + stamp_file = os.path.join(LLVM_BUILD_DIR, 'cr_coverage_revision') + package_file = 'llvm-code-coverage' + elif package_name == 'libclang': + package_file = 'libclang' + else: + print('Unknown package: "%s".' % package_name) + return 1 + + assert stamp_file is not None + assert package_file is not None + + # TODO(hans): Create a clang-win-runtime package and use separate DEPS hook. target_os = [] - try: - env = {} - execfile(GCLIENT_CONFIG, env, env) - target_os = env.get('target_os', target_os) - except: - pass + if package_name == 'clang': + try: + GCLIENT_CONFIG = os.path.join(os.path.dirname(CHROMIUM_DIR), '.gclient') + env = {} + execfile(GCLIENT_CONFIG, env, env) + target_os = env.get('target_os', target_os) + except: + pass if os.path.exists(OLD_STAMP_FILE): # Delete the old stamp file so it doesn't look like an old version of clang @@ -252,34 +296,35 @@ os.remove(OLD_STAMP_FILE) expected_stamp = ','.join([PACKAGE_VERSION] + target_os) - if ReadStampFile(STAMP_FILE) == expected_stamp: + if ReadStampFile(stamp_file) == expected_stamp: return 0 - if os.path.exists(LLVM_BUILD_DIR): + # Updating the main clang package nukes the output dir. Any other packages + # need to be updated *after* the clang package. + if package_name == 'clang' and os.path.exists(LLVM_BUILD_DIR): RmTree(LLVM_BUILD_DIR) - DownloadAndUnpackClangPackage(sys.platform, LLVM_BUILD_DIR) - if 'win' in target_os: - # When doing win/cross builds on other hosts, get the Windows runtime - # libraries, and llvm-symbolizer.exe (needed in asan builds). - path_prefixes = [ 'lib/clang/' + RELEASE_VERSION + '/lib/', - 'bin/llvm-symbolizer.exe' ] - DownloadAndUnpackClangPackage('win32', LLVM_BUILD_DIR, - path_prefixes=path_prefixes) - if sys.platform == 'win32': - CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin')) - WriteStampFile(expected_stamp, STAMP_FILE) + DownloadAndUnpackPackage(package_file, LLVM_BUILD_DIR) + if package_name == 'clang': + if sys.platform == 'win32': + CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin')) + if 'win' in target_os: + # When doing win/cross builds on other hosts, get the Windows runtime + # libraries, and llvm-symbolizer.exe (needed in asan builds). + DownloadAndUnpackClangWinRuntime(LLVM_BUILD_DIR) + + WriteStampFile(expected_stamp, stamp_file) return 0 def main(): - # TODO: Add an argument to download optional packages and remove the various - # download_ scripts we currently have for that. - parser = argparse.ArgumentParser(description='Update clang.') - parser.add_argument('--clang-dir', - help='Where to extract the clang package.') + parser.add_argument('--output-dir', + help='Where to extract the package.') + parser.add_argument('--package', + help='What package to update (default: clang)', + default='clang') parser.add_argument('--force-local-build', action='store_true', help='(no longer used)') parser.add_argument('--print-revision', action='store_true', @@ -324,12 +369,12 @@ print('--llvm-force-head-revision can only be used for --print-revision') return 1 - if args.clang_dir: + if args.output_dir: global LLVM_BUILD_DIR, STAMP_FILE - LLVM_BUILD_DIR = os.path.abspath(args.clang_dir) + LLVM_BUILD_DIR = os.path.abspath(args.output_dir) STAMP_FILE = os.path.join(LLVM_BUILD_DIR, 'cr_build_revision') - return UpdateClang() + return UpdatePackage(args.package) if __name__ == '__main__':
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py index 8573b1aa..126f48c 100755 --- a/tools/code_coverage/coverage.py +++ b/tools/code_coverage/coverage.py
@@ -84,7 +84,7 @@ os.path.join( os.path.dirname(__file__), os.path.pardir, os.path.pardir, 'tools', 'clang', 'scripts')) -from update import LLVM_BUILD_DIR +import update sys.path.append( os.path.join( @@ -93,11 +93,10 @@ from collections import defaultdict import coverage_utils -import update_clang_coverage_tools # Absolute path to the code coverage tools binary. These paths can be # overwritten by user specified coverage tool paths. -LLVM_BIN_DIR = os.path.join(LLVM_BUILD_DIR, 'bin') +LLVM_BIN_DIR = os.path.join(update.LLVM_BUILD_DIR, 'bin') LLVM_COV_PATH = os.path.join(LLVM_BIN_DIR, 'llvm-cov') LLVM_PROFDATA_PATH = os.path.join(LLVM_BIN_DIR, 'llvm-profdata') @@ -158,7 +157,7 @@ LLVM_COV_PATH = os.path.join(llvm_bin_dir, 'llvm-cov') LLVM_PROFDATA_PATH = os.path.join(llvm_bin_dir, 'llvm-profdata') else: - update_clang_coverage_tools.DownloadCoverageToolsIfNeeded() + update.UpdatePackage('coverage_tools') coverage_tools_exist = ( os.path.exists(LLVM_COV_PATH) and os.path.exists(LLVM_PROFDATA_PATH)) @@ -932,7 +931,7 @@ # Setup coverage binaries even when script is called with empty params. This # is used by coverage bot for initial setup. if len(sys.argv) == 1: - update_clang_coverage_tools.DownloadCoverageToolsIfNeeded() + update.UpdatePackage('coverage_tools') print(__doc__) return
diff --git a/tools/code_coverage/update_clang_coverage_tools.py b/tools/code_coverage/update_clang_coverage_tools.py deleted file mode 100755 index d98988cd..0000000 --- a/tools/code_coverage/update_clang_coverage_tools.py +++ /dev/null
@@ -1,93 +0,0 @@ -#!/usr/bin/env python -# 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. -"""Download clang coverage tools (llvm-cov + llvm-profdata)""" - -import os -import sys -import urllib2 - -sys.path.append( - os.path.join( - os.path.dirname(__file__), os.path.pardir, os.path.pardir, - 'third_party')) -import coverage_utils - -sys.path.append( - os.path.join( - os.path.dirname(__file__), os.path.pardir, os.path.pardir, 'tools', - 'clang', 'scripts')) -import update as clang_update - - -# TODO(crbug.com/759794): remove this function once tools get included to -# Clang bundle: -# https://chromium-review.googlesource.com/c/chromium/src/+/688221 -def DownloadCoverageToolsIfNeeded(): - """Temporary solution to download llvm-profdata and llvm-cov tools.""" - - def _GetRevisionFromStampFile(stamp_file_path): - """Returns revision by reading the build stamp file. - - Args: - stamp_file_path: A path the build stamp file created by - tools/clang/scripts/update.py. - Returns: - A string represeting the revision of the tool, such as 361212-67510fac-2. - """ - if not os.path.exists(stamp_file_path): - return '' - - with open(stamp_file_path) as stamp_file: - stamp_file_line = stamp_file.readline() - if ',' in stamp_file_line: - package_version = stamp_file_line.rstrip().split(',')[0] - else: - package_version = stamp_file_line.rstrip() - - return package_version - - cov_path = os.path.join(clang_update.LLVM_BUILD_DIR, 'bin', 'llvm-cov') - profdata_path = os.path.join( - clang_update.LLVM_BUILD_DIR, 'bin', 'llvm-profdata') - - host_platform = coverage_utils.GetHostPlatform() - clang_revision = _GetRevisionFromStampFile(clang_update.STAMP_FILE) - coverage_revision_stamp_file = os.path.join( - os.path.dirname(clang_update.STAMP_FILE), 'cr_coverage_revision') - coverage_revision = _GetRevisionFromStampFile(coverage_revision_stamp_file) - has_coverage_tools = ( - os.path.exists(cov_path) and os.path.exists(profdata_path)) - - if (has_coverage_tools and clang_revision == coverage_revision): - # LLVM coverage tools are up to date, bail out. - return - - package_version = clang_revision - coverage_tools_file = 'llvm-code-coverage-%s.tgz' % package_version - - # The code below follows the code from tools/clang/scripts/update.py. - if host_platform == 'mac': - coverage_tools_url = clang_update.CDS_URL + '/Mac/' + coverage_tools_file - elif host_platform == 'linux': - coverage_tools_url = ( - clang_update.CDS_URL + '/Linux_x64/' + coverage_tools_file) - else: - assert host_platform == 'win' - coverage_tools_url = (clang_update.CDS_URL + '/Win/' + coverage_tools_file) - - try: - clang_update.DownloadAndUnpack(coverage_tools_url, - clang_update.LLVM_BUILD_DIR) - with open(coverage_revision_stamp_file, 'w') as file_handle: - file_handle.write('%s,%s' % (package_version, host_platform)) - file_handle.write('\n') - except urllib2.URLError: - raise Exception( - 'Failed to download coverage tools: %s.' % coverage_tools_url) - - -if __name__ == '__main__': - DownloadCoverageToolsIfNeeded() - sys.exit(0)
diff --git a/tools/cygprofile/symbol_extractor.py b/tools/cygprofile/symbol_extractor.py index b0dc2a8..01fe126 100644 --- a/tools/cygprofile/symbol_extractor.py +++ b/tools/cygprofile/symbol_extractor.py
@@ -236,8 +236,8 @@ def CheckLlvmNmExists(): assert os.path.exists(_NM_PATH), ( - 'llvm-nm not found. Please run //tools/clang/scripts/download_objdump.py' - ' to install it.') + 'llvm-nm not found. Please run ' + '//tools/clang/scripts/update.py --package=objdump to install it.') def SymbolNamesFromLlvmBitcodeFile(filename):
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index c32d6745..be8989c 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -56,6 +56,12 @@ 'ppapi_nacl_tests_pnacl_newlib_x32.nexe', 'ppapi_nacl_tests_pnacl_newlib_x64.nexe', + # https://crbug.com/429358 + 'nacl_test_data/extension_vcache_test/glibc/extension_validation_cache_libs/lib32/libppapi_cpp_lib.dll', + 'nacl_test_data/glibc/pm_exit_status_test_libs/lib32/libppapi_cpp_lib.dll', + 'nacl_test_data/glibc/simple_libs/lib32/libppapi_cpp_lib.dll', + 'nacl_test_data/glibc/sysconf_nprocessors_onln_test_libs/lib32/libppapi_cpp_lib.dll', + # TODO(thakis): Figure out what's up with these three (and their isolate). 'mini_installer.exe', 'mini_installer.exe.pdb',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 99b4647..77057115 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -964,8 +964,10 @@ 'tryserver.webrtc': { 'win_chromium_compile': 'gpu_tests_release_trybot_resource_whitelisting', + 'win_chromium_compile_dbg': 'gpu_tests_debug_trybot_x86_compile_only', 'mac_chromium_compile': 'gpu_tests_release_trybot', 'linux_chromium_compile': 'release_trybot', + 'linux_chromium_compile_dbg': 'debug_trybot', 'android_chromium_compile': 'android_release_trybot', }, },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 47d18dcc..779d458c 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -62121,7 +62121,7 @@ </enum> <enum name="UkmResetReason"> - <int value="0" label="OnSyncPrefsChanged"/> + <int value="0" label="OnUkmAllowedStateChanged"/> <int value="1" label="UpdatePermissions"/> </enum>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 6415f4dac..a319a6e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -166,7 +166,7 @@ </histogram> <histogram name="Accessibility.CrosCursorHighlight" enum="BooleanEnabled" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>dmazzoni@chromium.org</owner> <summary> Whether the Chrome OS cursor highlighting is on (logged once 45 secs after @@ -358,7 +358,7 @@ </histogram> <histogram name="Accessibility.CrosVirtualKeyboard" enum="BooleanEnabled" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <summary> @@ -675,7 +675,7 @@ </histogram> <histogram name="Accessibility.WinScreenReader2" enum="BooleanEnabled" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <!-- expires-never: usage drives a11y prioritization in browser and content. --> <owner>aleventhal@chromium.org</owner> @@ -1273,7 +1273,7 @@ </histogram> <histogram name="AnchorElementMetrics.Clicked.OnDSE.SameHost" - enum="BooleanAnchorElementSameHost" expires_after="2020-03-01"> + enum="BooleanAnchorElementSameHost" expires_after="2020-05-03"> <owner>tbansal@chromium.org</owner> <summary> True if the target link of the anchor element has the same host as the root @@ -1282,7 +1282,7 @@ </histogram> <histogram name="AnchorElementMetrics.Clicked.OnNonDSE.SameHost" - enum="BooleanAnchorElementSameHost" expires_after="2020-03-01"> + enum="BooleanAnchorElementSameHost" expires_after="2020-05-03"> <owner>tbansal@chromium.org</owner> <summary> True if the target link of the anchor element has the same host as the root @@ -2464,7 +2464,7 @@ </histogram> <histogram name="Android.DownloadManager.OpenSource.Video" - enum="AndroidDownloadOpenSource" expires_after="2020-02-02"> + enum="AndroidDownloadOpenSource" expires_after="2020-05-03"> <owner>xingliu@chromium.org</owner> <owner>clank-downloads@google.com</owner> <summary>Records how users open video download files on Android.</summary> @@ -2629,7 +2629,7 @@ </histogram> <histogram base="true" name="Android.FeatureModules.AvailabilityStatus" - enum="FeatureModuleAvailabilityStatus" expires_after="2020-03-01"> + enum="FeatureModuleAvailabilityStatus" expires_after="2020-05-03"> <!-- Name completed by histogram_suffixes name="AndroidFeatureModuleName" --> @@ -2919,7 +2919,7 @@ </histogram> <histogram name="Android.Language.WrongLanguageAfterResume" enum="Boolean" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>tiborg@chromium.org</owner> <owner>heamy@chromium.org</owner> <summary> @@ -3688,7 +3688,7 @@ </histogram> <histogram name="Android.SeccompStatus.RendererSandbox" - enum="AndroidSeccompSandboxStatus" expires_after="2020-03-01"> + enum="AndroidSeccompSandboxStatus" expires_after="2020-05-03"> <owner>rsesek@chromium.org</owner> <summary> Reports the status of the seccomp-bpf sandbox in renderer processes. @@ -4556,7 +4556,7 @@ </histogram> <histogram name="AppBanners.BeforeInstallEvent" - enum="AppBannersBeforeInstallEvent" expires_after="2020-03-01"> + enum="AppBannersBeforeInstallEvent" expires_after="2020-05-03"> <owner>dominickn@chromium.org</owner> <summary> App banners promote an application related to the current website, and are @@ -4569,7 +4569,7 @@ </histogram> <histogram name="AppBanners.DismissEvent" enum="AppBannersDismissEvent" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>pjmclachlan@google.com</owner> <owner>pcovell@google.com</owner> <summary> @@ -4975,7 +4975,7 @@ </histogram> <histogram name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerLoadingTime" - units="ms" expires_after="2020-03-01"> + units="ms" expires_after="2020-05-03"> <owner>jennyz@chriomium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -4986,7 +4986,7 @@ <histogram name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerNavigationTime" - units="ms" expires_after="2020-03-01"> + units="ms" expires_after="2020-05-03"> <owner>jennyz@chriomium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -4996,7 +4996,7 @@ </histogram> <histogram name="Apps.AppList.AppSearchProvider.QueryTime" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5006,7 +5006,7 @@ </histogram> <histogram name="Apps.AppList.AppSearchProvider.ZeroStateLatency" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5026,7 +5026,7 @@ </histogram> <histogram name="Apps.AppList.DriveQuickAccessProvider.ApiResults" - units="count"> + units="count" expires_after="2020-05-03"> <owner>tby@chromium.org</owner> <owner>wrong@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -5060,7 +5060,7 @@ </histogram> <histogram name="Apps.AppList.DriveQuickAccessProvider.FileError" - enum="DriveFileError"> + enum="DriveFileError" expires_after="2020-05-03"> <owner>tby@chromium.org</owner> <owner>wrong@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -5126,7 +5126,7 @@ </histogram> <histogram name="Apps.AppList.OmniboxProvider.QueryTime" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chriomium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5137,7 +5137,7 @@ </histogram> <histogram name="Apps.AppList.OmniboxProvider.ZeroStateLatency" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chriomium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5309,7 +5309,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateSearchResultRemovalDecision" - enum="AppListZeroStateResultRemovalConfirmation" expires_after="2020-03-01"> + enum="AppListZeroStateResultRemovalConfirmation" expires_after="2020-05-03"> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5321,7 +5321,7 @@ <histogram name="Apps.AppList.ZeroStateSearchResultUserActionType" enum="AppListZeroStateSearchResultUserActionType" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5565,7 +5565,7 @@ </histogram> <histogram name="Apps.AppListPlayStoreAppLaunchedIndex" units="indices" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> @@ -5590,7 +5590,7 @@ </histogram> <histogram name="Apps.AppListRecommendedImpResultCountAfterOpen" units="shows" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>napper@chromium.org</owner> <owner>robsc@chromium.org</owner> <summary> @@ -5666,7 +5666,7 @@ </histogram> <histogram name="Apps.AppListSearchCommenced" units="searches" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>tapted@chromium.org</owner> <summary> The number of searches that are started in the app list. This is gathered @@ -5758,7 +5758,7 @@ </histogram> <histogram name="Apps.AppListSearchResultOpenTypeV2" enum="AppListSearchResult" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <!-- Name completed by histogram_suffixes name="TabletOrClamshellMode" --> <owner>newcomer@chromium.org</owner> @@ -5781,7 +5781,7 @@ </histogram> <histogram name="Apps.AppListShowSource" enum="AppListShowSource" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>newcomer@chromium.org</owner> <summary> The number of times the different sources for showing the app list are used. @@ -6201,7 +6201,7 @@ </histogram> <histogram name="Apps.LogDisplayTypeClickedResultZeroState" - enum="AppListSearchResultDisplayType" expires_after="2020-03-01"> + enum="AppListSearchResultDisplayType" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <owner>thanhdng@chromium.org</owner> <owner>tby@chromium.org</owner> @@ -6686,7 +6686,7 @@ </histogram> <histogram name="Arc.FirstAppLaunchDelay.TimeDelta" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yusukes@google.com</owner> <owner>khmel@google.com</owner> <summary> @@ -6840,7 +6840,7 @@ </histogram> <histogram name="Arc.NativeBridge" enum="ArcNativeBridgeType" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>elijahtaylor@google.com</owner> <owner>levarum@google.com</owner> <summary> @@ -6923,7 +6923,7 @@ </histogram> <histogram name="Arc.PlayAutoInstallRequest.State" - enum="ArcPlayAutoInstallRequestState" expires_after="2019-12-31"> + enum="ArcPlayAutoInstallRequestState" expires_after="2020-05-03"> <!-- Name completed by histogram_suffixes name="ArcUserTypes" --> <owner>jhorwich@google.com</owner> @@ -8016,7 +8016,7 @@ </histogram> <histogram name="Ash.Shelf.NumberOfItems" units="Icons" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>bruthig@google.com</owner> <owner>tdanderson@google.com</owner> <summary> @@ -8200,7 +8200,7 @@ </histogram> <histogram name="Ash.ShelfAlignmentOverTime" enum="ShelfAlignmentValue" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>kuscher@google.com</owner> <summary> The current state of the shelf (alignment) tracked over time by logging on a @@ -8499,7 +8499,7 @@ </histogram> <histogram name="Ash.TouchView.TouchViewInactive" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>girard@chromium.org</owner> <summary>The length of time between TouchView activations.</summary> </histogram> @@ -13251,7 +13251,7 @@ </histogram> <histogram name="AutoScreenBrightness.AlsReaderStatus" - enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2020-03-01"> + enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2020-05-03"> <owner>tby@chromium.org</owner> <summary> Whether the ALS is enabled or the error otherwise. Chrome OS only. @@ -13259,13 +13259,13 @@ </histogram> <histogram name="AutoScreenBrightness.BrightnessChange.Cause" - enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-03-01"> + enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary>Reason for the model to change brightness. Chrome OS only.</summary> </histogram> <histogram name="AutoScreenBrightness.BrightnessChange.ElapsedTime" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> The time between two consecutive auto brightness changes. Chrome OS only. @@ -13307,7 +13307,7 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.Eve" units="count" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on an Eve device @@ -13321,7 +13321,7 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.NoAls" units="count" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a device @@ -13351,7 +13351,7 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.SupportedAls" - units="count" expires_after="2020-03-01"> + units="count" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a device with @@ -13389,7 +13389,7 @@ <histogram name="AutoScreenBrightness.ElapsedTimeBetweenModelAndUserAdjustments" - units="ms" expires_after="2020-03-01"> + units="ms" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> The elapsed time from a model brightness adjustment to the next user manual @@ -13500,7 +13500,7 @@ </histogram> <histogram name="AutoScreenBrightness.NewCurveSaved.Success" - enum="BooleanSuccess" expires_after="2020-03-01"> + enum="BooleanSuccess" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> Whether a new curve was successfully saved to disk. Only reported if a new @@ -13509,7 +13509,7 @@ </histogram> <histogram name="AutoScreenBrightness.Opposite.UserModelBrightnessAdjustments" - units="count" expires_after="2020-03-01"> + units="count" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> When user changes brightness manually, if the previous change was caused by @@ -13557,7 +13557,7 @@ </histogram> <histogram name="AutoScreenBrightness.TrainingCompleteDuration.NoNewCurve" - units="ms" expires_after="2020-03-01"> + units="ms" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> The time elapsed to complete training after which no new curve was @@ -13575,7 +13575,7 @@ </histogram> <histogram name="AutoScreenBrightness.UserAdjustmentEffect" - enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2020-03-01"> + enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2020-05-03"> <owner>jiameng@chromium.org</owner> <summary> How user manual screen brightness adjustment changes the model. Chrome OS @@ -14434,7 +14434,7 @@ </histogram> <histogram name="Blink.Animate.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent processing main frame animations during a main frame update. @@ -15688,7 +15688,7 @@ </histogram> <histogram name="Blink.ForcedStyleAndLayout.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent computing layouts due to Javascript value requests. Specifically, @@ -15797,7 +15797,7 @@ </histogram> <histogram name="Blink.IntersectionObservation.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent computing IntersectionObserver observations in the Blink document @@ -15818,7 +15818,7 @@ </histogram> <histogram name="Blink.Layout.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>layout-dev@chromium.org</owner> <summary> @@ -15866,7 +15866,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.AnimateRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15878,7 +15878,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.CompositingCommitRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15890,7 +15890,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.CompositingRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15902,7 +15902,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.ForcedStyleAndLayoutRatio" - units="%" expires_after="2020-3-1"> + units="%" expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15915,7 +15915,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.HandleInputEventsRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15927,7 +15927,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.IntersectionObservationRatio" - units="%" expires_after="2020-3-1"> + units="%" expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15939,7 +15939,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.LayoutRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15951,7 +15951,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.PaintRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15963,7 +15963,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.PrePaintRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15975,7 +15975,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.ProxyCommitRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -15987,7 +15987,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.ScrollingCoordinatorRatio" - units="%" expires_after="2020-3-1"> + units="%" expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -16012,7 +16012,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.StyleRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -16024,7 +16024,7 @@ </histogram> <histogram base="true" name="Blink.MainFrame.UpdateLayersRatio" units="%" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" --> @@ -16036,7 +16036,7 @@ </histogram> <histogram name="Blink.MainFrame.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -16223,7 +16223,7 @@ </histogram> <histogram name="Blink.Paint.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent updating paint in the Blink document lifecycle. @@ -16247,7 +16247,7 @@ </histogram> <histogram name="Blink.PrePaint.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent updating paint properties and paint invalidation in the Blink @@ -16260,7 +16260,7 @@ </histogram> <histogram name="Blink.ProxyCommit.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>paint-dev@chromium.org</owner> <summary> Time spent commiting the layer tree to the impl thread in a main frame @@ -16551,7 +16551,7 @@ </histogram> <histogram name="Blink.ScrollingCoordinator.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>pdr@chromium.org</owner> <summary> The time it took to update scrolling coordinator data (scroll gesture @@ -16717,7 +16717,7 @@ </histogram> <histogram name="Blink.Style.UpdateTime" units="microseconds" - expires_after="2020-3-1"> + expires_after="2020-05-03"> <owner>schenney@chromium.org</owner> <owner>layout-dev@chromium.org</owner> <summary> @@ -16879,7 +16879,7 @@ </histogram> <histogram name="Blink.UseCounter.FeaturePolicy.Header" - enum="FeaturePolicyFeature" expires_after="2020-02-16"> + enum="FeaturePolicyFeature" expires_after="2020-05-03"> <owner>iclelland@chromium.org</owner> <summary> Counts the use of a specific feature policy via the @@ -17033,7 +17033,7 @@ </histogram> <histogram name="Blink.UseCounter.File.Features" enum="FeatureObserver" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yhirano@chromium.org</owner> <owner>mkwst@chromium.org</owner> <summary> @@ -17835,7 +17835,7 @@ </histogram> <histogram name="Bluetooth.ConnectedDeviceCount" units="devices" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>adlr@chromium.org</owner> <summary> Counts the number of simulataneously connected Bluetooth devices. Used to @@ -17898,7 +17898,7 @@ </histogram> <histogram name="Bluetooth.PairingMethod" enum="BluetoothPairingMethod" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>adlr@chromium.org</owner> <summary> Records the method used to pair each Bluetooth Device. Used to direct our @@ -18303,7 +18303,7 @@ </histogram> <histogram name="Bluetooth.Web.RequestDevice.OptionalServices.Services" - enum="GATTServiceHash" expires_after="2020-03-01"> + enum="GATTServiceHash" expires_after="2020-05-03"> <owner>odejesush@chromium.org</owner> <owner>ortuno@chromium.org</owner> <owner>reillyg@chromium.org</owner> @@ -18388,7 +18388,7 @@ </histogram> <histogram name="Bluetooth.Web.RequestDevice.UnionOfServices.Services" - enum="GATTServiceHash" expires_after="2020-03-01"> + enum="GATTServiceHash" expires_after="2020-05-03"> <owner>odejesush@chromium.org</owner> <owner>ortuno@chromium.org</owner> <owner>reillyg@chromium.org</owner> @@ -18400,7 +18400,7 @@ </summary> </histogram> -<histogram name="BlueZ.AdapterLost" units="seconds" expires_after="2020-03-01"> +<histogram name="BlueZ.AdapterLost" units="seconds" expires_after="2020-05-03"> <owner>mcchou@chromium.org</owner> <summary> This is specific to Chrome OS. Records a duration of a Bluetooth adapter @@ -18463,7 +18463,7 @@ </histogram> <histogram name="BlueZ.ResultOfConnection" enum="BlueZResultOfConnection" - expires_after="2020-02-02"> + expires_after="2020-05-03"> <owner>mcchou@chromium.org</owner> <summary> This is specific to Chrome OS. Records the outcomes of connection requests @@ -19057,7 +19057,7 @@ </histogram> <histogram name="BrowserRenderProcessHost.ChildCrashes" enum="RendererType" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>wfh@chromium.org</owner> <summary>Count of renderer process crashes grouped by type.</summary> </histogram> @@ -19782,7 +19782,7 @@ </histogram> <histogram name="CaptivePortal.DetectResult" enum="CaptivePortalDetectResult" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>meacer@chromium.org</owner> <summary>Records the result of a captive portal probe.</summary> </histogram> @@ -20109,7 +20109,7 @@ </histogram> <histogram name="Cast.Sender.VideoEncodeAcceleratorInitializeSuccess" - enum="BooleanSuccess" expires_after="2020-03-01"> + enum="BooleanSuccess" expires_after="2020-05-03"> <owner>posciak@chromium.org</owner> <summary> Indicates whether initialization of a video encode accelerator for Cast @@ -20502,7 +20502,7 @@ </histogram> <histogram name="ChildProcess.Killed2.OOM" enum="ProcessType2" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>oshima@chromium.org</owner> <summary> Out of ChildProcess.Killled, number of kills due to SIGKILL, which is a @@ -20849,7 +20849,7 @@ </histogram> <histogram name="ChromeColors.AppliedColor" enum="ChromeColorsInfo" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>gayane@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <summary> @@ -20858,7 +20858,7 @@ </histogram> <histogram name="ChromeColors.ChangesConfirmed" - enum="BooleanChromeColorsChangesConfirmed" expires_after="2020-03-01"> + enum="BooleanChromeColorsChangesConfirmed" expires_after="2020-05-03"> <owner>gayane@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <summary> @@ -20868,7 +20868,7 @@ </histogram> <histogram name="ChromeColors.ColorOnLoad" enum="ChromeColorsInfo" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>gayane@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <summary> @@ -20878,7 +20878,7 @@ </histogram> <histogram name="ChromeColors.RevertReason" enum="ChromeColorsRevertReason" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>gayane@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <summary> @@ -21041,7 +21041,7 @@ </histogram> <histogram name="ChromeOS.Apps.IntentPickerDestinationPlatform" - enum="ArcIntentHandlerDestinationPlatform" expires_after="2020-03-01"> + enum="ArcIntentHandlerDestinationPlatform" expires_after="2020-05-03"> <owner>elijahtaylor@google.com</owner> <owner>dominickn@chromium.org</owner> <owner>shihuis@google.com</owner> @@ -21199,7 +21199,7 @@ </histogram> <histogram name="ChromeOS.CWP.UploadPerf" units="reports" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>aalexand@google.com</owner> <owner>gmx@chromium.org</owner> <summary> @@ -23714,7 +23714,7 @@ </histogram> <histogram name="ContentCapture.CaptureContentTime" units="microseconds" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>michaelbai@chromium.org</owner> <summary>The time taken to capture the on-screen content.</summary> </histogram> @@ -23745,7 +23745,7 @@ </histogram> <histogram name="ContentCapture.SentContentCount" units="count" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>michaelbai@chromium.org</owner> <summary>The total number of content captures sent for a document.</summary> </histogram> @@ -25595,7 +25595,7 @@ </histogram> <histogram name="Cookie.CookieSourceScheme" enum="CookieSourceScheme" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>estark@chromium.org</owner> <summary> For each cookie added to the store, record whether its source URL has a @@ -25771,7 +25771,7 @@ </histogram> <histogram name="Cookie.NetworkSecurity" enum="CookieNetworkSecurity" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <obsolete> Deprecated 2019-10-31 as part of cookie histogram cleanup (https://crbug.com/993120). @@ -26781,7 +26781,7 @@ </histogram> <histogram name="Cras.StreamCallbackThreshold" units="frames" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yuhsuan@chromium.org</owner> <owner>chromeos-audio@google.com</owner> <summary> @@ -27108,7 +27108,7 @@ </histogram> <histogram name="CrosDisksClient.MountCompletedError" - enum="CrosDisksClientMountError" expires_after="2020-02-02"> + enum="CrosDisksClientMountError" expires_after="2020-05-03"> <owner>amistry@chromium.org</owner> <summary> The error code of disk mount signals received from the Chrome OS cros-disks @@ -27126,7 +27126,7 @@ </histogram> <histogram name="CrosDisksClient.MountTime" units="ms" - expires_after="2020-02-16"> + expires_after="2020-05-03"> <owner>amistry@chromium.org</owner> <summary> Time taken by the Chrome OS cros-disks daemon to perform a Mount operation. @@ -27143,7 +27143,7 @@ </histogram> <histogram name="CrosDisksClient.UnmountTime" units="ms" - expires_after="2020-02-16"> + expires_after="2020-05-03"> <owner>amistry@chromium.org</owner> <summary> Time taken by the Chrome OS cros-disks daemon to perform an Unmount @@ -27844,7 +27844,7 @@ </histogram> <histogram name="Cryptohome.AsyncDBusRequest" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>zuan@chromium.org</owner> <owner>cros-hwsec+uma@chromium.org</owner> <summary> @@ -35786,7 +35786,7 @@ </histogram> <histogram name="Download.Service.Files.FreeDiskSpace" units="%" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>xingliu@chromium.org</owner> <summary> The percentage of free disk space to total disk space. Recorded during @@ -35852,7 +35852,7 @@ </histogram> <histogram name="Download.Service.Finish.Type" - enum="Download.Service.CompletionType" expires_after="2020-03-01"> + enum="Download.Service.CompletionType" expires_after="2020-05-03"> <owner>xingliu@chromium.org</owner> <summary>The completion type for downloads in download service.</summary> </histogram> @@ -36082,7 +36082,7 @@ </histogram> <histogram name="Download.Start.ContentType.InsecureChain" - enum="DownloadContentType" expires_after="2020-03-01"> + enum="DownloadContentType" expires_after="2020-05-03"> <owner>cthomp@chromium.org</owner> <owner>estark@chromium.org</owner> <summary> @@ -36104,7 +36104,7 @@ </histogram> <histogram name="Download.Start.ContentType.SecureChain" - enum="DownloadContentType" expires_after="2020-03-01"> + enum="DownloadContentType" expires_after="2020-05-03"> <owner>cthomp@chromium.org</owner> <owner>estark@chromium.org</owner> <summary> @@ -37797,7 +37797,7 @@ </histogram> <histogram name="Enterprise.FCMInvalidationService.DevicePolicyInvalidations" - enum="EnterprisePolicyInvalidations" expires_after="2020-03-01"> + enum="EnterprisePolicyInvalidations" expires_after="2020-05-03"> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -38085,7 +38085,7 @@ </histogram> <histogram name="Enterprise.PolicyInvalidations" - enum="EnterprisePolicyInvalidations" expires_after="2020-03-01"> + enum="EnterprisePolicyInvalidations" expires_after="2020-05-03"> <owner>mnissler@chromium.org</owner> <summary> Events for counting user policy invalidations received with and without @@ -38299,7 +38299,7 @@ </histogram> <histogram name="Enterprise.TiclInvalidationService.DevicePolicyInvalidations" - enum="EnterprisePolicyInvalidations" expires_after="2020-03-01"> + enum="EnterprisePolicyInvalidations" expires_after="2020-05-03"> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -38651,7 +38651,7 @@ </histogram> <histogram name="EnterpriseCheck.IsDomainJoined" enum="BooleanEnabled" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>mad@chromium.org</owner> <summary> Whether the machine is joined to an AD domain. This check is performed once @@ -40065,7 +40065,7 @@ </histogram> <histogram name="Event.Latency.EndToEnd.Mouse" units="microseconds" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>input-dev@chromium.org</owner> <summary> Time between the OS receiving a mouse event and the resulting GPU frame @@ -51870,7 +51870,7 @@ </histogram> <histogram name="GPU.D3DShaderModel" enum="ShaderModel" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>jmadill@chromium.org</owner> <summary> ANGLE's currently active D3D shader model version. Logged once every startup @@ -52467,7 +52467,7 @@ </histogram> <histogram name="GPU.GPUProcessDetailedExitStatus" - enum="ProcessDetailedExitStatus" expires_after="2020-03-01"> + enum="ProcessDetailedExitStatus" expires_after="2020-05-03"> <owner>wnwen@chromium.org</owner> <summary> Breakdown of exit status for gpu processes. Only recorded on Android. @@ -52475,7 +52475,7 @@ </histogram> <histogram name="GPU.GPUProcessExitCode" enum="GPUProcessExitCode" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jbauman@chromium.org</owner> <summary> Counts for the exit codes returned by the GPU process when it terminated. @@ -52634,7 +52634,7 @@ </histogram> <histogram name="GPU.IOSurface.TexImageTime" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>ccameron@chromium.org</owner> <summary> The time that it took for a call to CGLTexImageIOSurface2D to complete. @@ -52751,7 +52751,7 @@ </summary> </histogram> -<histogram name="GPU.Output.HDR" enum="Boolean" expires_after="2020-02-23"> +<histogram name="GPU.Output.HDR" enum="Boolean" expires_after="2020-05-03"> <owner>hubbe@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -53394,7 +53394,7 @@ </histogram> <histogram base="true" name="GridTabSwitcher.DirtySpan" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yusufo@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary> @@ -53405,7 +53405,7 @@ </histogram> <histogram base="true" name="GridTabSwitcher.FramePerSecond" units="frame/sec" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yusufo@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary> @@ -53415,7 +53415,7 @@ </histogram> <histogram base="true" name="GridTabSwitcher.MaxFrameInterval" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>yusufo@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary> @@ -53425,7 +53425,7 @@ </histogram> <histogram name="GridTabSwitcher.ThumbnailFetchingResult" - enum="GridTabSwitcherThumbnailFetchingResult" expires_after="2020-03-01"> + enum="GridTabSwitcherThumbnailFetchingResult" expires_after="2020-05-03"> <owner>yusufo@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary> @@ -54925,7 +54925,7 @@ </summary> </histogram> -<histogram name="HttpCache.BeforeSend" units="ms" expires_after="2020-03-01"> +<histogram name="HttpCache.BeforeSend" units="ms" expires_after="2020-05-03"> <owner>morlovich@chromium.org</owner> <summary> For http cache transactions in which a network request was sent, the time @@ -58563,7 +58563,7 @@ </histogram> <histogram name="IOS.WKWebViewClobberedHistory" enum="Boolean" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>danyao@chromium.org</owner> <summary> Measures the number of main frame navigations in slim navigation manager @@ -72456,7 +72456,7 @@ <histogram name="MultiDevice.SecureChannel.BLE.Performance.StartScanToReceiveAdvertisementDuration.Background" - units="ms" expires_after="2020-03-01"> + units="ms" expires_after="2020-05-03"> <owner>hansberry@chromium.org</owner> <owner>khorimoto@chromium.org</owner> <summary> @@ -93455,7 +93455,7 @@ </histogram> <histogram name="NQE.WifiSignalStrength.LevelAvailable" enum="BooleanAvailable" - expires_after="2020-02-16"> + expires_after="2020-05-03"> <owner>tbansal@chromium.org</owner> <owner>bengr@chromium.org</owner> <summary> @@ -93572,7 +93572,7 @@ </histogram> <histogram name="OAuth2Login.MergeSessionFailure" enum="GoogleServiceAuthError" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>tbarzic@chromium.org</owner> <summary> Failure reason of MergeSession call during Chrome OS login, Chrome Signin or @@ -98113,7 +98113,7 @@ </histogram> <histogram name="Overscroll.Navigated3" enum="OverscrollNavigationType" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>nzolghadr@chromium.org</owner> <summary> Navigations that were triggered due to completed overscroll gesture. Note @@ -111213,7 +111213,7 @@ </summary> </histogram> -<histogram name="Power.BacklightLevelOnAC" units="%" expires_after="2020-03-01"> +<histogram name="Power.BacklightLevelOnAC" units="%" expires_after="2020-05-03"> <owner>tbroch@chromium.org</owner> <summary> The level of the backlight as a percentage when the user is on AC. Sampled @@ -112134,7 +112134,7 @@ </histogram> <histogram name="Power.UserBrightnessAdjustmentsPerSessionOnBattery" - units="units" expires_after="2020-03-01"> + units="units" expires_after="2020-05-03"> <owner>tbroch@chromium.org</owner> <owner>jiameng@chromium.org</owner> <summary> @@ -115433,7 +115433,7 @@ </histogram> <histogram name="Privacy.DoNotTrackSetting" enum="BooleanEnabled" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>mkwst@chromium.org</owner> <owner>msramek@chromium.org</owner> <summary> @@ -116292,7 +116292,7 @@ </histogram> <histogram name="Profile.TriggeredReset" enum="BooleanReset" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>robertshield@chromium.org</owner> <summary> Indicates whether a profile had a reset trigger that caused it to launch a @@ -116780,7 +116780,7 @@ </histogram> <histogram name="PushMessaging.QueuedMessagesCount" units="units" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>mamir@chromium.org</owner> <summary> When a message arrives for a lazy subscription and Chrome isn't in the @@ -124939,7 +124939,7 @@ </histogram> <histogram name="SB2.RemoteCall.CanCheckUrl" enum="BooleanCanCheckUrl" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -135538,7 +135538,7 @@ </histogram> <histogram name="Sharing.DeviceRegistrationResult" - enum="SharingDeviceRegistrationResult" expires_after="2020-04-19"> + enum="SharingDeviceRegistrationResult" expires_after="M84"> <owner>alexchau@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -135548,7 +135548,7 @@ </histogram> <histogram name="Sharing.DeviceUnregistrationResult" - enum="SharingDeviceRegistrationResult" expires_after="2020-04-19"> + enum="SharingDeviceRegistrationResult" expires_after="M84"> <owner>alexchau@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -135557,7 +135557,7 @@ </summary> </histogram> -<histogram name="Sharing.MessageAckTime" units="ms" expires_after="2020-04-19"> +<histogram name="Sharing.MessageAckTime" units="ms" expires_after="M84"> <!-- Name completed by histogram_suffixes name="SharingMessage" --> <owner>mvanouwerkerk@chromium.org</owner> @@ -135569,7 +135569,7 @@ </histogram> <histogram name="Sharing.MessageReceivedType" enum="SharingMessageType" - expires_after="2020-04-19"> + expires_after="M84"> <!-- Name completed by histogram_suffixes name="SharingMessage" --> <owner>mvanouwerkerk@chromium.org</owner> @@ -135582,7 +135582,7 @@ </histogram> <histogram name="Sharing.SendAckMessageResult" enum="SharingSendMessageResult" - expires_after="M80"> + expires_after="M84"> <!-- Name completed by histogram_suffixes name="SharingMessage" --> <owner>alexchau@chromium.org</owner> @@ -135607,7 +135607,7 @@ </histogram> <histogram name="Sharing.SendMessageResult" enum="SharingSendMessageResult" - expires_after="M80"> + expires_after="M84"> <!-- Name completed by histogram_suffixes name="SharingMessage" --> <owner>alexchau@chromium.org</owner> @@ -135678,7 +135678,7 @@ </histogram> <histogram name="Sharing.VapidKeyCreationResult" - enum="SharingVapidKeyCreationResult" expires_after="2020-04-19"> + enum="SharingVapidKeyCreationResult" expires_after="M84"> <owner>alexchau@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -142130,7 +142130,7 @@ </histogram> <histogram name="Startup.ColdStartWithExternalURLTime" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>jif@chromium.org</owner> <summary> The duration of all initializations in a cold start triggered by an external @@ -145948,7 +145948,7 @@ </histogram> <histogram name="Sync.Local.Enabled" enum="BooleanEnabled" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>pastarmovj@chromium.org</owner> <summary> Tracks the number of times the local sync backend was enabled by the user. @@ -146619,7 +146619,7 @@ </histogram> <histogram name="Sync.PostedClientToServerMessageLatency" units="ms" - expires_after="2020-02-02"> + expires_after="2020-05-03"> <owner>mastiz@chromium.org</owner> <summary> Time taken for a client-initiated request to be sent over the network and @@ -152537,6 +152537,32 @@ </summary> </histogram> +<histogram name="UKM.ConsentObserver.AllowedForAllProfiles" enum="Boolean" + expires_after="2020-07-01"> + <owner>bcwhite@chromium.org</owner> + <owner>rkaplow@chromium.org</owner> + <owner>ukm-team@google.com</owner> + <summary> + Logged in UpdateUkmAllowedForAllProfiles from the UkmConsentStateObserver + which is called when UkmConsentStateObserver starts observing a new profile + and every time a URL-keyed anonymized data collection state changes or a + sync service state changes. This records whether UKM is allowed for all + profiles. + </summary> +</histogram> + +<histogram name="UKM.ConsentObserver.Purge" enum="Boolean" + expires_after="2020-07-01"> + <owner>bcwhite@chromium.org</owner> + <owner>rkaplow@chromium.org</owner> + <owner>ukm-team@google.com</owner> + <summary> + Logged in the UpdateProfileState call from the UkmConsentStateObserver. This + records if the UKM allowed change will trigger a purge of the local UKM + data. + </summary> +</histogram> + <histogram name="UKM.Entries.Dropped" enum="UkmDataDroppedReason" expires_after="2020-07-01"> <owner>rkaplow@chromium.org</owner> @@ -152716,25 +152742,30 @@ </histogram> <histogram name="UKM.SyncDisable.Info" enum="UkmSyncDisableInfo" - expires_after="2020-07-01"> + expires_after="M79"> + <obsolete> + Deprecated 11/2018 for UKM.ConsentObserver.AllowedForAllProfiles. + </obsolete> <owner>bcwhite@chromium.org</owner> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> - Information about the determination by the SyncDisableObserver on why it - enabled or disabled UKM based on Sync status. This is recorded every time a - change is detected in Sync (which may be several just at startup). + Information about the determination by the UkmConsentStateObserver on why it + enabled or disabled UKM. </summary> </histogram> -<histogram name="UKM.SyncDisable.Purge" enum="Boolean" - expires_after="2020-07-01"> +<histogram name="UKM.SyncDisable.Purge" enum="Boolean" expires_after="M79"> + <obsolete> + Deprecated 11/2018 for UKM.ConsentObserver.Purge. + </obsolete> <owner>bcwhite@chromium.org</owner> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> - Logged in the UpdateSyncState call from the UKM Sync observer. This records - if the Sync change will trigger a purge of the local UKM data. + Logged in the UpdateSyncState call from the UkmConsentStateObserver. This + records if the UKM allowed change will trigger a purge of the local UKM + data. </summary> </histogram> @@ -153812,7 +153843,7 @@ </histogram> <histogram name="UMA.TruncatedEvents.UserAction" units="events" - expires_after="2020-04-26"> + expires_after="2020-05-03"> <owner>rkaplow@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> @@ -155229,7 +155260,7 @@ </histogram> <histogram name="V8.CompileDeserializeMicroSeconds" units="microseconds" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>vogelheim@chromium.org</owner> <summary> Time spent deseriailzing code, used by V8 code caching. @@ -155623,7 +155654,7 @@ </summary> </histogram> -<histogram name="V8.GCBackgroundMarking" units="ms" expires_after="2020-02-16"> +<histogram name="V8.GCBackgroundMarking" units="ms" expires_after="2020-05-03"> <owner>ulan@chromium.org</owner> <summary> Time spent in background tasks doing marking in one GC cycle. It is recorded @@ -158592,7 +158623,7 @@ </histogram> <histogram name="WebApk.Install.InstallDuration" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>hanxi@chromium.org</owner> <owner>pkotwicz@chromium.org</owner> <owner>yfriedman@chromium.org</owner> @@ -158863,7 +158894,7 @@ </histogram> <histogram base="true" name="WebApk.Uninstall" enum="BooleanHit" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>pkotwicz@chromium.org</owner> <owner>yfriedman@chromium.org</owner> <summary>Records that a WebAPK was uninstalled.</summary> @@ -159609,7 +159640,7 @@ </histogram> <histogram name="WebAuthentication.GetAssertionRequestTransport" - enum="WebAuthenticationFidoTransport" expires_after="2020-03-01"> + enum="WebAuthenticationFidoTransport" expires_after="2020-05-03"> <owner>kenrb@chromium.org</owner> <owner>kpaulhamus@chromium.org</owner> <summary> @@ -159651,7 +159682,7 @@ </histogram> <histogram name="WebAuthentication.MakeCredentialResponseTransport" - enum="WebAuthenticationFidoTransport" expires_after="2020-03-01"> + enum="WebAuthenticationFidoTransport" expires_after="2020-05-03"> <owner>kenrb@chromium.org</owner> <owner>kpaulhamus@chromium.org</owner> <summary> @@ -160167,7 +160198,7 @@ </histogram> <histogram name="WebCore.IndexedDB.LevelDBOpenErrors.Corruption" - enum="LevelDBCorruptionTypes" expires_after="2020-02-23"> + enum="LevelDBCorruptionTypes" expires_after="2020-05-03"> <owner>dgrogan@chromium.org</owner> <summary> Types of corruption that LevelDB encounters when opening a database. @@ -160273,7 +160304,7 @@ </histogram> <histogram name="WebCore.IndexedDB.LevelDBWriteErrors.BFE" - enum="PlatformFileError" expires_after="2020-02-23"> + enum="PlatformFileError" expires_after="2020-05-03"> <owner>cmumford@chromium.org</owner> <summary> Errors (base::File::Error) encountered by a single LevelDBEnv method when @@ -160430,7 +160461,7 @@ </histogram> <histogram name="WebCore.IndexedDB.PutBlobsCount" units="blobs" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>dmurph@chromium.org</owner> <summary> The number of blobs being saved in an IndexedDB object store 'put' @@ -160439,7 +160470,7 @@ </histogram> <histogram name="WebCore.IndexedDB.PutBlobsTotalSize" units="KB" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>dmurph@chromium.org</owner> <summary> The total size of the blobs being saved in an IndexedDB object store 'put' @@ -160575,7 +160606,7 @@ </histogram> <histogram name="WebCore.IndexedDB.SchemaVersion" units="version" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>dmurph@chromium.org</owner> <summary> Records the schema version of the IndexedDB database read from disk. @@ -160589,7 +160620,7 @@ </histogram> <histogram name="WebCore.IndexedDB.SchemaVersion.Docs" units="version" - expires_after="2020-02-23"> + expires_after="2020-05-03"> <owner>dmurph@chromium.org</owner> <summary> Records the schema version of the IndexedDB database read from disk. @@ -160826,7 +160857,7 @@ </histogram> <histogram name="WebCore.IndexedDB.TransactionAbortReason" enum="IDBException" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>dmurph@chromium.org</owner> <summary> Recorded on the browser side (back end) when an IndexedDB transaction is @@ -161692,7 +161723,7 @@ </histogram> <histogram name="WebP.DecodedImageFormat" enum="WebpDecodedFormat" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>droger@chromium.org</owner> <summary> Histogram for the format of decoded WebP images on iOS, as Chrome re-encodes @@ -163237,7 +163268,7 @@ </histogram> <histogram name="WebRTC.PeerConnection.SdpSemanticNegotiated" - enum="PeerConnectionSdpSemanticNegotiated" expires_after="2020-03-01"> + enum="PeerConnectionSdpSemanticNegotiated" expires_after="2020-05-03"> <owner>hta@chromium.org</owner> <summary> What SDP semantic (Unified Plan or Plan B) was detected when completing @@ -163349,7 +163380,7 @@ </histogram> <histogram name="WebRTC.PeerConnection.TimeToConnect" units="ms" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>qingsi@google.com</owner> <owner>jeroendb@google.com</owner> <summary>Time to setup a peer to peer call with PeerConnection.</summary> @@ -165327,7 +165358,7 @@ </histogram> <histogram name="WebUsb.NotificationClosed" enum="WebUsbNotificationClosed" - expires_after="2020-03-01"> + expires_after="2020-05-03"> <owner>reillyg@chromium.org</owner> <owner>juncai@chromium.org</owner> <summary> @@ -181437,7 +181468,11 @@ </obsolete> </suffix> <suffix name="MANAGED_USER_WHITELIST" label="MANAGED_USER_WHITELIST"/> - <suffix name="MOUNTAIN_SHARE" label="MOUNTAIN_SHARE"/> + <suffix name="MOUNTAIN_SHARE" label="MOUNTAIN_SHARE"> + <obsolete> + Removed 11/2019. + </obsolete> + </suffix> <suffix name="NIGORI" label="NIGORI"/> <suffix name="OS_PREFERENCE" label="OS_PREFERENCE"/> <suffix name="OS_PRIORITY_PREFERENCE" label="OS_PRIORITY_PREFERENCE"/>
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml index 8c142334..2ef2cf27 100644 --- a/tools/metrics/rappor/rappor.xml +++ b/tools/metrics/rappor/rappor.xml
@@ -110,15 +110,6 @@ </summary> </rappor-metric> -<rappor-metric name="Cast.Sender.MediaFrameUrl" type="ETLD_PLUS_ONE"> - <owner>avayvod@chromium.org</owner> - <owner>aberent@chromium.org</owner> - <summary> - The domain and registry of the frame URL that the user is trying to cast the - media from. Recorded every time the user casts the media. - </summary> -</rappor-metric> - <rappor-metric name="ContentSettings.Plugins.AddedAllowException" type="ETLD_PLUS_ONE"> <owner>tommycli@chromium.org</owner> @@ -178,73 +169,6 @@ </summary> </rappor-metric> -<rappor-metric name="Media.Controls.Cast" type="ETLD_PLUS_ONE"> - <owner>beccahughes@chromium.org</owner> - <owner>media-team@chromium.org</owner> - <summary> - The URL of the page when the user casts media using the normal button. - </summary> -</rappor-metric> - -<rappor-metric name="Media.Controls.CastOverlay" type="ETLD_PLUS_ONE"> - <owner>beccahughes@chromium.org</owner> - <owner>media-team@chromium.org</owner> - <summary> - The URL of the page when the user casts media using the overlay button. - </summary> -</rappor-metric> - -<rappor-metric name="Media.Session.APIUsage.Origin" type="ETLD_PLUS_ONE"> - <owner>avayvod@chromium.org</owner> - <owner>mlamouri@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - The eTLD+1 of the URL of frames using the Media Session API. - </summary> -</rappor-metric> - -<rappor-metric name="Media.Video.Autoplay.Muted.Attribute.Frame" - type="ETLD_PLUS_ONE"> - <owner>avayvod@chromium.org</owner> - <owner>mlamouri@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - The eTLD+1 of the frame URL that has an autoplay muted video by attribute. - </summary> -</rappor-metric> - -<rappor-metric name="Media.Video.Autoplay.Muted.DualSource.Frame" - type="ETLD_PLUS_ONE"> - <owner>avayvod@chromium.org</owner> - <owner>mlamouri@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - The eTLD+1 of the frame URL that has an autoplay muted video by both - attribute and play() method. - </summary> -</rappor-metric> - -<rappor-metric name="Media.Video.Autoplay.Muted.PlayMethod.Frame" - type="ETLD_PLUS_ONE"> - <owner>avayvod@chromium.org</owner> - <owner>mlamouri@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - The eTLD+1 of the frame URL that has an autoplay muted video by play() - method. - </summary> -</rappor-metric> - -<rappor-metric name="Media.VideoPersistence.TopFrame" type="ETLD_PLUS_ONE"> - <owner>mlamouri@chromium.org</owner> - <owner>peconn@chromium.org</owner> - <owner>zqzhang@chromium.org</owner> - <summary> - The eTLD+1 of the top frame of the tab when a video persistence session is - initialized. - </summary> -</rappor-metric> - <rappor-metric name="NTP.ExplicitUserAction.PageNavigation.NTPTileClick" type="UMA_RAPPOR_TYPE"> <owner>knn@chromium.org</owner>
diff --git a/tools/perf/core/results_processor/processor.py b/tools/perf/core/results_processor/processor.py index 3d1ddb1..d8e8e43 100644 --- a/tools/perf/core/results_processor/processor.py +++ b/tools/perf/core/results_processor/processor.py
@@ -203,8 +203,9 @@ if name in [compute_metrics.HISTOGRAM_DICTS_FILE, MEASUREMENTS_NAME]: continue remote_name = '/'.join([run_identifier, test_result['testPath'], name]) + urlsafe_remote_name = re.sub(r'[^A-Za-z0-9/.-]+', '_', remote_name) artifact['remoteUrl'] = cloud_storage.Insert( - upload_bucket, remote_name, artifact['filePath']) + upload_bucket, urlsafe_remote_name, artifact['filePath']) logging.info('Uploaded %s of %s to %s', name, test_result['testPath'], artifact['remoteUrl'])
diff --git a/tools/perf/run_gtest_benchmark.py b/tools/perf/run_gtest_benchmark.py index 5f349031..ca6a098b 100755 --- a/tools/perf/run_gtest_benchmark.py +++ b/tools/perf/run_gtest_benchmark.py
@@ -82,7 +82,8 @@ parser.add_argument('executable', help='The name of the executable to run.') options, leftover_args = parser.parse_known_args(args) - results_processor.ProcessOptions(options, standalone=True) + options.test_path_format = 'gtest' + results_processor.ProcessOptions(options) run_return_code = RunGTest(options, leftover_args) process_return_code = ProcessResults(options)
diff --git a/tools/perf/testdata/dummy_luci_test_result_template.json b/tools/perf/testdata/dummy_luci_test_result_template.json index 66ed6fa..bf2bc798 100644 --- a/tools/perf/testdata/dummy_luci_test_result_template.json +++ b/tools/perf/testdata/dummy_luci_test_result_template.json
@@ -1,5 +1,6 @@ { "testResult": { + "testPath" : "DummySuite.DummyCase", "status": "PASS", "expected": true, "outputArtifacts":{
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc index da3aff75f..5949a56 100644 --- a/ui/aura/window_event_dispatcher.cc +++ b/ui/aura/window_event_dispatcher.cc
@@ -86,10 +86,8 @@ //////////////////////////////////////////////////////////////////////////////// // WindowEventDispatcher, public: -WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host, - bool are_events_in_pixels) +WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host) : host_(host), - are_events_in_pixels_(are_events_in_pixels), observer_manager_(this), event_targeter_(std::make_unique<WindowTargeter>()) { Env::GetInstance()->gesture_recognizer()->AddGestureEventHelper(this); @@ -480,10 +478,8 @@ // The held events are already in |window()|'s coordinate system. So it is // not necessary to apply the transform to convert from the host's // coordinate system to |window()|'s coordinate system. - if (event->IsLocatedEvent() && !is_dispatched_held_event(*event) && - are_events_in_pixels_) { + if (event->IsLocatedEvent() && !is_dispatched_held_event(*event)) TransformEventForDeviceScaleFactor(static_cast<ui::LocatedEvent*>(event)); - } observer_notifiers_.push(std::make_unique<ObserverNotifier>(this, *event)); }
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h index f1a1bcad5..cde5da9e 100644 --- a/ui/aura/window_event_dispatcher.h +++ b/ui/aura/window_event_dispatcher.h
@@ -57,14 +57,9 @@ public WindowObserver, public EnvObserver { public: - // |are_events_in_pixels| indicates if events are - // received in pixels. If |are_events_in_pixels| is false, events are - // received in DIPs. - WindowEventDispatcher(WindowTreeHost* host, bool are_events_in_pixels); + explicit WindowEventDispatcher(WindowTreeHost* host); ~WindowEventDispatcher() override; - bool are_events_in_pixels() const { return are_events_in_pixels_; } - // Stops dispatching/synthesizing mouse events. void Shutdown(); @@ -289,8 +284,6 @@ WindowTreeHost* host_; - const bool are_events_in_pixels_; - Window* mouse_pressed_handler_ = nullptr; Window* mouse_moved_handler_ = nullptr; Window* touchpad_pinch_handler_ = nullptr;
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index ed2748e..7f4bd21 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc
@@ -419,7 +419,6 @@ void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id, bool force_software_compositor, bool use_external_begin_frame_control, - bool are_events_in_pixels, const char* trace_environment_name) { Env* env = Env::GetInstance(); ui::ContextFactory* context_factory = env->context_factory(); @@ -441,8 +440,7 @@ window()->Init(ui::LAYER_NOT_DRAWN); window()->set_host(this); window()->SetName("RootWindow"); - dispatcher_ = - std::make_unique<WindowEventDispatcher>(this, are_events_in_pixels); + dispatcher_ = std::make_unique<WindowEventDispatcher>(this); } }
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h index dc5ddf20..91c49ad 100644 --- a/ui/aura/window_tree_host.h +++ b/ui/aura/window_tree_host.h
@@ -272,14 +272,12 @@ void DestroyDispatcher(); // If frame_sink_id is not passed in, one will be grabbed from - // ContextFactoryPrivate. |are_events_in_pixels| indicates if events are - // received in pixels. If |are_events_in_pixels| is false, events are - // received in DIPs. See Compositor() for details on |trace_environment_name|. + // ContextFactoryPrivate. See Compositor() for details on + // |trace_environment_name|. void CreateCompositor( const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId(), bool force_software_compositor = false, bool use_external_begin_frame_control = false, - bool are_events_in_pixels = true, const char* trace_environment_name = nullptr); void InitCompositor();
diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc index 40c6bc90..34155943 100644 --- a/ui/aura/window_tree_host_platform.cc +++ b/ui/aura/window_tree_host_platform.cc
@@ -59,8 +59,7 @@ bounds_in_pixels_ = properties.bounds; CreateCompositor(viz::FrameSinkId(), /* force_software_compositor */ false, - use_external_begin_frame_control, - /* are_events_in_pixels */ true, trace_environment_name); + use_external_begin_frame_control, trace_environment_name); CreateAndSetPlatformWindow(std::move(properties)); }
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 64bbe296..be0034a 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -132,6 +132,10 @@ const base::Feature kFormControlsRefresh = {"FormControlsRefresh", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable WebUI accessibility enhancements for review and testing. +const base::Feature kWebUIA11yEnhancements{"WebUIA11yEnhancements", + base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsFormControlsRefreshEnabled() { return base::FeatureList::IsEnabled(features::kFormControlsRefresh); }
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 6217c9fb..eed578b 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -89,6 +89,9 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kHandwritingGesture; #endif + +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kWebUIA11yEnhancements; } // namespace features #endif // UI_BASE_UI_BASE_FEATURES_H_
diff --git a/ui/base/webui/web_ui_util.cc b/ui/base/webui/web_ui_util.cc index 74bdb41f..e1fc68b 100644 --- a/ui/base/webui/web_ui_util.cc +++ b/ui/base/webui/web_ui_util.cc
@@ -7,6 +7,7 @@ #include <vector> #include "base/base64.h" +#include "base/feature_list.h" #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" @@ -20,6 +21,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/template_expressions.h" +#include "ui/base/ui_base_features.h" #include "ui/base/window_open_disposition.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/font.h" @@ -188,6 +190,7 @@ void SetLoadTimeDataDefaults(const std::string& app_locale, base::DictionaryValue* localized_strings) { + localized_strings->SetString("a11yenhanced", GetA11yEnhanced()); localized_strings->SetString("fontfamily", GetFontFamily()); localized_strings->SetString("fontsize", GetFontSize()); localized_strings->SetString("language", l10n_util::GetLanguage(app_locale)); @@ -196,6 +199,7 @@ void SetLoadTimeDataDefaults(const std::string& app_locale, ui::TemplateReplacements* replacements) { + (*replacements)["a11yenhanced"] = GetA11yEnhanced(); (*replacements)["fontfamily"] = GetFontFamily(); (*replacements)["fontsize"] = GetFontSize(); (*replacements)["language"] = l10n_util::GetLanguage(app_locale); @@ -222,6 +226,12 @@ html->append("</style>"); } +std::string GetA11yEnhanced() { + return base::FeatureList::IsEnabled(features::kWebUIA11yEnhancements) + ? "a11y-enhanced" + : ""; +} + std::string GetFontFamily() { std::string font_family = l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY);
diff --git a/ui/base/webui/web_ui_util.h b/ui/base/webui/web_ui_util.h index 53a0c275..138061c 100644 --- a/ui/base/webui/web_ui_util.h +++ b/ui/base/webui/web_ui_util.h
@@ -83,6 +83,7 @@ // inline stylesheet. UI_BASE_EXPORT void AppendWebUiCssTextDefaults(std::string* html); +UI_BASE_EXPORT std::string GetA11yEnhanced(); // Get some common font styles for all of WebUI. UI_BASE_EXPORT std::string GetFontFamily(); UI_BASE_EXPORT std::string GetFontSize();
diff --git a/ui/base/x/x11_window.cc b/ui/base/x/x11_window.cc index c2cd003..05d9c28c 100644 --- a/ui/base/x/x11_window.cc +++ b/ui/base/x/x11_window.cc
@@ -1559,6 +1559,10 @@ has_pointer_barriers_ = true; } +void XWindow::LowerWindow() { + XLowerWindow(xdisplay_, xwindow_); +} + bool XWindow::ContainsPointInRegion(const gfx::Point& point) const { if (!shape()) return true;
diff --git a/ui/base/x/x11_window.h b/ui/base/x/x11_window.h index 804a189..91a828ea 100644 --- a/ui/base/x/x11_window.h +++ b/ui/base/x/x11_window.h
@@ -139,6 +139,7 @@ void CancelResize(); void NotifySwapAfterResize(); void ConfineCursorTo(const gfx::Rect& bounds); + void LowerWindow(); // Returns if the point is within XWindow shape. If shape is not set, always // returns true.
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index 0339ff3f..faae281d 100644 --- a/ui/gfx/render_text_harfbuzz.cc +++ b/ui/gfx/render_text_harfbuzz.cc
@@ -87,10 +87,16 @@ UMA_HISTOGRAM_ENUMERATION("RenderTextHarfBuzz.ShapeRunsFallback", fallback); } -// Returns true if characters of |block_code| may trigger font fallback. -bool IsUnusualBlockCode(UBlockCode block_code) { - return block_code == UBLOCK_GEOMETRIC_SHAPES || - block_code == UBLOCK_MISCELLANEOUS_SYMBOLS; +// Returns whether the codepoint has the 'extended pictographic' property. +bool IsExtendedPictographicCodepoint(UChar32 codepoint) { + return u_hasBinaryProperty(codepoint, UCHAR_EXTENDED_PICTOGRAPHIC); +} + +// Returns whether the codepoint has emoji properties. +bool IsEmojiRelatedCodepoint(UChar32 codepoint) { + return u_hasBinaryProperty(codepoint, UCHAR_EMOJI) || + u_hasBinaryProperty(codepoint, UCHAR_EMOJI_PRESENTATION) || + u_hasBinaryProperty(codepoint, UCHAR_REGIONAL_INDICATOR); } // Returns true if |codepoint| is a bracket. This is used to avoid "matching" @@ -115,7 +121,8 @@ } // Intersects the script extensions set of |codepoint| with |result| and writes -// to |result|, reading and updating |result_size|. +// to |result|, reading and updating |result_size|. The output |result| will be +// a subset of the input |result| (thus |result_size| can only be smaller). void ScriptSetIntersect(UChar32 codepoint, UScriptCode* result, size_t* result_size) { @@ -169,62 +176,111 @@ *result_size = out_size; } -// Returns true if |first_char| and |current_char| both have "COMMON" script -// property but only one of them is an ASCII character. By doing this ASCII -// characters will be put into a separate run and be rendered using its default -// font. See crbug.com/530021 and crbug.com/533721 for more details. -bool AsciiBreak(UChar32 first_char, UChar32 current_char) { - if (isascii(first_char) == isascii(current_char)) - return false; +struct GraphemeProperties { + bool has_control = false; + bool has_bracket = false; + bool has_pictographic = false; + bool has_emoji = false; + UBlockCode block = UBLOCK_NO_BLOCK; +}; - size_t scripts_size = 1; - UScriptCode scripts[kMaxScripts] = { USCRIPT_COMMON }; - ScriptSetIntersect(first_char, scripts, &scripts_size); - if (scripts_size == 0) - return false; - ScriptSetIntersect(current_char, scripts, &scripts_size); - return scripts_size != 0; +// Returns the properties for the codepoints part of the given text. +GraphemeProperties RetrieveGraphemeProperties(const base::StringPiece16& text, + bool retrieve_block) { + GraphemeProperties properties; + bool first_char = true; + base::i18n::UTF16CharIterator iter(text.data(), text.length()); + while (!iter.end()) { + const UChar32 codepoint = iter.get(); + + if (first_char) { + first_char = false; + if (retrieve_block) + properties.block = ublock_getCode(codepoint); + } + + if (codepoint == '\n' || codepoint == ' ') + properties.has_control = true; + if (IsBracket(codepoint)) + properties.has_bracket = true; + if (IsExtendedPictographicCodepoint(codepoint)) + properties.has_pictographic = true; + if (IsEmojiRelatedCodepoint(codepoint)) + properties.has_emoji = true; + + iter.Advance(); + } + + return properties; } -// When a string of "unusual" characters ends, the run usually breaks. However, -// variation selectors should still attach to the run of unusual characters. -// Detect this situation so that FindRunBreakingCharacter() can continue -// tracking the unusual block. Otherwise, just returns |current|. -UBlockCode MaybeCombineUnusualBlock(UBlockCode preceding, UBlockCode current) { - return IsUnusualBlockCode(preceding) && current == UBLOCK_VARIATION_SELECTORS - ? preceding - : current; +// Return whether the grapheme properties are compatible and the grapheme can +// be merge together in the same grapheme cluster. +bool AreGraphemePropertiesCompatible(const GraphemeProperties& first, + const GraphemeProperties& second) { + // There are 5 constrains to grapheme to be compatible. + // 1) The newline character and control characters should form a single run so + // that the line breaker can handle them easily. + // 2) Parentheses should be put in a separate run to avoid using different + // fonts while rendering matching parentheses (see http://crbug.com/396776). + // 3) Pictographic graphemes should be put in separate run to avoid altering + // fonts selection while rendering adjacent text (see + // http://crbug.com/278913). + // 4) Emoji graphemes should be put in separate run (see + // http://crbug.com/530021 and http://crbug.com/533721). + // 5) The 'COMMON' script needs to be split by unicode block. Codepoints are + // spread across blocks and supported with different fonts. + return !first.has_control && !second.has_control && + first.has_bracket == second.has_bracket && + first.has_pictographic == second.has_pictographic && + first.has_emoji == second.has_emoji && first.block == second.block; } -// Returns the boundary between a special and a regular character. Special -// characters are brackets or characters that satisfy |IsUnusualBlockCode|. +// Returns the end of the current grapheme cluster. This function is finding the +// breaking point where grapheme properties are no longer compatible. +// (see: UNICODE TEXT SEGMENTATION (http://unicode.org/reports/tr29/) size_t FindRunBreakingCharacter(const base::string16& text, + UScriptCode script, size_t run_start, size_t run_break) { - const int32_t run_length = static_cast<int32_t>(run_break - run_start); - base::i18n::UTF16CharIterator iter(text.c_str() + run_start, run_length); - const UChar32 first_char = iter.get(); - // The newline character should form a single run so that the line breaker - // can handle them easily. - if (first_char == '\n') + const size_t run_length = run_break - run_start; + const base::StringPiece16 run_text(text.c_str() + run_start, run_length); + const bool is_common_script = (script == USCRIPT_COMMON); + + DCHECK(!run_text.empty()); + + // Create an iterator to split the text in graphemes. + base::i18n::BreakIterator grapheme_iterator( + run_text, base::i18n::BreakIterator::BREAK_CHARACTER); + if (!grapheme_iterator.Init() || !grapheme_iterator.Advance()) { + // In case of error, isolate the first character in a separate run. + NOTREACHED(); return run_start + 1; + } - const UBlockCode first_block = ublock_getCode(first_char); - const bool first_block_unusual = IsUnusualBlockCode(first_block); - const bool first_bracket = IsBracket(first_char); + // Retrieve the first grapheme and its codepoint properties. + const base::StringPiece16 first_grapheme_text = + grapheme_iterator.GetStringPiece(); + const GraphemeProperties first_grapheme_properties = + RetrieveGraphemeProperties(first_grapheme_text, is_common_script); - while (iter.Advance() && iter.array_pos() < run_length) { - const UChar32 current_char = iter.get(); - const UBlockCode current_block = - MaybeCombineUnusualBlock(first_block, ublock_getCode(current_char)); - const bool block_break = current_block != first_block && - (first_block_unusual || IsUnusualBlockCode(current_block)); - if (block_break || current_char == '\n' || - first_bracket != IsBracket(current_char) || - AsciiBreak(first_char, current_char)) { - return run_start + iter.array_pos(); + // Append subsequent graphemes in this grapheme cluster if they are + // compatible, otherwise break the current run. + while (grapheme_iterator.Advance()) { + const base::StringPiece16 current_grapheme_text = + grapheme_iterator.GetStringPiece(); + const GraphemeProperties current_grapheme_properties = + RetrieveGraphemeProperties(current_grapheme_text, is_common_script); + + if (!AreGraphemePropertiesCompatible(first_grapheme_properties, + current_grapheme_properties)) { + const size_t current_breaking_position = + run_start + grapheme_iterator.prev(); + return current_breaking_position; } } + + // Do not break this run, returns end of the text. return run_break; } @@ -1909,7 +1965,7 @@ CommonizedRunsMap* out_commonized_run_map) { TRACE_EVENT1("ui", "RenderTextHarfBuzz::ItemizeTextToRuns", "text_length", text.length()); - DCHECK_NE(0U, text.length()); + DCHECK(!text.empty()); const Font& primary_font = font_list().GetPrimaryFont(); // If ICU fails to itemize the text, we create a run that spans the entire @@ -1970,10 +2026,10 @@ breaking_run_start < script_run_end;) { // Break runs at certain characters that need to be rendered separately // to prevent either an unusual character from forcing a fallback font - // on the entire run, or brackets from being affected by a fallback - // font. http://crbug.com/278913, http://crbug.com/396776 - size_t breaking_char_end = - FindRunBreakingCharacter(text, breaking_run_start, script_run_end); + // on the entire run. After script intersection, many codepoints end up + // in the script COMMON but can't be rendered together. + size_t breaking_char_end = FindRunBreakingCharacter( + text, script, breaking_run_start, script_run_end); // Break runs at style boundaries. style.UpdatePosition(DisplayIndexToTextIndex(breaking_run_start));
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index 247cef3..5198cbb 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -935,16 +935,16 @@ {"simpleRTL", L"ښڛڜ", "[2<-0]"}, {"asc_arb", L"abcښڛڜdef", "[0->2][5<-3][6->8]"}, {"asc_dev_asc", L"abcऔकखdefڜ", "[0->2][3->5][6->8][9]"}, - {"phone", L"1-(800)-xxx-xxxx", "[0->1][2][3->5][6][7][8->10][11][12->15]"}, + {"phone", L"1-(800)-xxx-xxxx", "[0][1][2][3->5][6][7][8->10][11][12->15]"}, {"dev_ZWS", L"क\u200Bख", "[0][1][2]"}, - {"numeric", L"1 2 3 4", "[0->6]"}, - {"joiners", L"1\u200C2\u200C3\u200C4", "[0][1][2][3][4][5][6]"}, + {"numeric", L"1 2 3 4", "[0][1][2][3][4][5][6]"}, + {"joiners", L"1\u200C2\u200C3\u200C4", "[0->6]"}, {"combining_accents1", L"a\u0300e\u0301", "[0->3]"}, {"combining_accents2", L"\u0065\u0308\u0435\u0308", "[0->1][2->3]"}, {"picto_title", L"☞☛test☚☜", "[0->1][2->5][6->7]"}, {"picto_LTR", L"☺☺☺!", "[0->2][3]"}, {"picto_RTL", L"☺☺☺ښ", "[3][2<-0]"}, - {"paren_picto", L"(☾☹☽)", "[0][1->3][4]"}, + {"paren_picto", L"(☾☹☽)", "[0][1][2][3][4]"}, {"emoji_asc", L"\U0001F6281234", "[0->1][2->5]"}, // http://crbug.com/530021 {"emoji_title", L"▶Feel goods", @@ -989,11 +989,12 @@ {"neutral_RLM_post", L"\u2026\u2026\u200F", "[2<-0]"}, {"brackets_ltr", L"aa(ڭڭ)\u2026\u2026", "[0->1][2][4<-3][5][6->7]"}, {"brackets_rtl", L"ڭڭ(aa)\u2026\u2026", "[7<-6][5][3->4][2][1<-0]"}, - {"mixed_with_punct", L"aa \"ڭڭ!\", aa", "[0->1][2->3][5<-4][6->9][10->11]"}, + {"mixed_with_punct", L"aa \"ڭڭ!\", aa", + "[0->1][2][3][5<-4][6->8][9][10->11]"}, {"mixed_with_punct_RLI", L"aa \"\u2067ڭڭ!\u2069\", aa", - "[0->1][2->3][4][7][6<-5][8][9->11][12->13]"}, + "[0->1][2][3][4][7][6<-5][8][9->10][11][12->13]"}, {"mixed_with_punct_RLM", L"aa \"ڭڭ!\u200F\", aa", - "[0->1][2->3][7][6][5<-4][8->10][11->12]"}, + "[0->1][2][3][7][6][5<-4][8->9][10][11->12]"}, }; INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsBidi, @@ -1072,7 +1073,7 @@ {"blocks_lat_smallcap", L"ꟺM", "[0->1]"}, {"blocks_lat_small_letter", L"ᶓᶍᶓᴔᴟ", "[0->4]"}, {"blocks_lat_acc", L"eéěĕȩɇḕẻếⱻꞫ", "[0->10]"}, - {"blocks_com", L"⟦ℳ¥¾⟾⁸⟧Ⓔ", "[0][1->5][6][7]"}, + {"blocks_com", L"⟦ℳ¥¾⟾⁸⟧Ⓔ", "[0][1][2->3][4][5][6][7]"}, // Latin script. {"latin_numbers", L"a1b2c3", "[0][1][2][3][4][5]"}, @@ -1083,9 +1084,9 @@ // Common script. {"common_tm", L"•bug™", "[0][1->3][4]"}, {"common_copyright", L"chromium©", "[0->7][8]"}, - {"common_math1", L"ℳ: ¬ƒ(x)=½×¾", "[0][1->2][3][4][5][6][7][8][9->11]"}, - {"common_math2", L"𝟏×𝟑", "[0->4]"}, - {"common_numbers", L"🄀𝟭𝟐⒓¹²", "[0->8]"}, + {"common_math1", L"ℳ: ¬ƒ(x)=½×¾", "[0][1][2][3][4][5][6][7][8][9->11]"}, + {"common_math2", L"𝟏×𝟑", "[0->1][2][3->4]"}, + {"common_numbers", L"🄀𝟭𝟐⒓¹²", "[0->1][2->5][6][7->8]"}, {"common_puncts", L",.\u0083!", "[0->1][2][3]"}, // Arabic script. @@ -1124,7 +1125,7 @@ {"telugu_lat", L"aaఉయ!", "[0->1][2->3][4]"}, {"telugu_numbers", L"123౦౧౨456౩౪౫", "[0->2][3->5][6->8][9->11]"}, {"telugu_puncts", L"కురుచ, చిఱుత, చేరువ, చెఱువు!", - "[0->4][5->6][7->11][12->13][14->18][19->20][21->26][27]"}, + "[0->4][5][6][7->11][12][13][14->18][19][20][21->26][27]"}, // Control Pictures. {"control_pictures", L"␑␒␓␔␕␖␗␘␙␚␛", "[0->10]"}, @@ -1136,6 +1137,109 @@ ::testing::ValuesIn(kScriptsRunListCases), RenderTextTestWithRunListCase::ParamInfoToString); +// Test cases to ensure ItemizeTextToRuns is splitting emoji correctly. +// see: http://www.unicode.org/reports/tr51 +// see: http://www.unicode.org/emoji/charts/full-emoji-list.html +const RunListCase kEmojiRunListCases[] = { + // Samples from + // https://www.unicode.org/Public/emoji/12.0/emoji-data.txt + {"number_sign", L"\u0023", "[0]"}, + {"keyboard", L"\u2328", "[0]"}, + {"aries", L"\u2648", "[0]"}, + {"candle", L"\U0001F56F", "[0->1]"}, + {"anchor", L"\u2693", "[0]"}, + {"grinning_face", L"\U0001F600", "[0->1]"}, + {"face_with_monocle", L"\U0001F9D0", "[0->1]"}, + {"light_skin_tone", L"\U0001F3FB", "[0->1]"}, + {"index_pointing_up", L"\u261D", "[0]"}, + {"horse_racing", L"\U0001F3C7", "[0->1]"}, + {"kiss", L"\U0001F48F", "[0->1]"}, + {"couple_with_heart", L"\U0001F491", "[0->1]"}, + {"people_wrestling", L"\U0001F93C", "[0->1]"}, + {"eject_button", L"\u23CF", "[0]"}, + + // Samples from + // https://unicode.org/Public/emoji/12.0/emoji-sequences.txt + {"watch", L"\u231A", "[0]"}, + {"cross_mark", L"\u274C", "[0]"}, + {"copyright", L"\u00A9\uFE0F", "[0->1]"}, + {"stop_button", L"\u23F9\uFE0F", "[0->1]"}, + {"passenger_ship", L"\U0001F6F3\uFE0F", "[0->2]"}, + {"keycap_star", L"\u002A\uFE0F\u20E3", "[0->2]"}, + {"keycap_6", L"\u0036\uFE0F\u20E3", "[0->2]"}, + {"flag_andorra", L"\U0001F1E6\U0001F1E9", "[0->3]"}, + {"flag_egypt", L"\U0001F1EA\U0001F1EC", "[0->3]"}, + {"flag_england", + L"\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F", + "[0->13]"}, + {"index_up_light", L"\u261D\U0001F3FB", "[0->2]"}, + {"person_bouncing_ball_light", L"\u26F9\U0001F3FC", "[0->2]"}, + {"victory_hand_med_light", L"\u270C\U0001F3FC", "[0->2]"}, + {"horse_racing_med_dark", L"\U0001F3C7\U0001F3FE", "[0->3]"}, + {"woman_man_hands_light", L"\U0001F46B\U0001F3FB", "[0->3]"}, + {"person_haircut_med_light", L"\U0001F487\U0001F3FC", "[0->3]"}, + {"pinching_hand_light", L"\U0001F90F\U0001F3FB", "[0->3]"}, + {"love_you_light", L"\U0001F91F\U0001F3FB", "[0->3]"}, + {"leg_dark", L"\U0001F9B5\U0001F3FF", "[0->3]"}, + + // Samples from + // https://unicode.org/Public/emoji/12.0/emoji-variation-sequences.txt + {"number_sign_text", L"\u0023\uFE0E", "[0->1]"}, + {"number_sign_emoji", L"\u0023\uFE0F", "[0->1]"}, + {"digit_eight_text", L"\u0038\uFE0E", "[0->1]"}, + {"digit_eight_emoji", L"\u0038\uFE0F", "[0->1]"}, + {"up_down_arrow_text", L"\u2195\uFE0E", "[0->1]"}, + {"up_down_arrow_emoji", L"\u2195\uFE0F", "[0->1]"}, + {"stopwatch_text", L"\u23F1\uFE0E", "[0->1]"}, + {"stopwatch_emoji", L"\u23F1\uFE0F", "[0->1]"}, + {"thermometer_text", L"\U0001F321\uFE0E", "[0->2]"}, + {"thermometer_emoji", L"\U0001F321\uFE0F", "[0->2]"}, + {"thumbs_up_text", L"\U0001F44D\uFE0E", "[0->2]"}, + {"thumbs_up_emoji", L"\U0001F44D\uFE0F", "[0->2]"}, + {"hole_text", L"\U0001F573\uFE0E", "[0->2]"}, + {"hole_emoji", L"\U0001F573\uFE0F", "[0->2]"}, + + // Samples from + // https://unicode.org/Public/emoji/12.0/emoji-zwj-sequences.txt + {"couple_man_man", L"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F468", + "[0->7]"}, + {"kiss_man_man", + L"\U0001F468\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F468", + "[0->10]"}, + {"family_man_woman_girl_boy", + L"\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466", "[0->10]"}, + {"men_hands_dark_medium", + L"\U0001F468\U0001F3FF\u200D\U0001F91D\u200D\U0001F468\U0001F3FD", + "[0->11]"}, + {"people_hands_dark", + L"\U0001F9D1\U0001F3FF\u200D\U0001F91D\u200D\U0001F9D1\U0001F3FF", + "[0->11]"}, + {"man_pilot", L"\U0001F468\u200D\u2708\uFE0F", "[0->4]"}, + {"man_scientist", L"\U0001F468\u200D\U0001F52C", "[0->4]"}, + {"man_mechanic_light", L"\U0001F468\U0001F3FB\u200D\U0001F527", "[0->6]"}, + {"man_judge_medium", L"\U0001F468\U0001F3FD\u200D\u2696\uFE0F", "[0->6]"}, + {"woman_cane_dark", L"\U0001F469\U0001F3FF\u200D\U0001F9AF", "[0->6]"}, + {"woman_ball_light", L"\u26F9\U0001F3FB\u200D\u2640\uFE0F", "[0->5]"}, + {"woman_running", L"\U0001F3C3\u200D\u2640\uFE0F", "[0->4]"}, + {"woman_running_dark", L"\U0001F3C3\U0001F3FF\u200D\u2640\uFE0F", "[0->6]"}, + {"woman_turban", L"\U0001F473\u200D\u2640\uFE0F", "[0->4]"}, + {"woman_detective", L"\U0001F575\uFE0F\u200D\u2640\uFE0F", "[0->5]"}, + {"man_facepalming", L"\U0001F926\u200D\u2642\uFE0F", "[0->4]"}, + {"man_red_hair", L"\U0001F468\u200D\U0001F9B0", "[0->4]"}, + {"man_medium_curly", L"\U0001F468\U0001F3FD\u200D\U0001F9B1", "[0->6]"}, + {"woman_dark_white_hair", L"\U0001F469\U0001F3FF\u200D\U0001F9B3", + "[0->6]"}, + {"rainbow_flag", L"\U0001F3F3\uFE0F\u200D\U0001F308", "[0->5]"}, + {"pirate_flag", L"\U0001F3F4\u200D\u2620\uFE0F", "[0->4]"}, + {"service_dog", L"\U0001F415\u200D\U0001F9BA", "[0->4]"}, + {"eye_bubble", L"\U0001F441\uFE0F\u200D\U0001F5E8\uFE0F", "[0->6]"}, +}; + +INSTANTIATE_TEST_SUITE_P(ItemizeTextToRunsEmoji, + RenderTextTestWithRunListCase, + ::testing::ValuesIn(kEmojiRunListCases), + RenderTextTestWithRunListCase::ParamInfoToString); + TEST_F(RenderTextTest, ElidedText) { // TODO(skanuj) : Add more test cases for following // - RenderText styles. @@ -3958,7 +4062,7 @@ EXPECT_EQ(ToString16Vec({"סיבית", " ", "–", " ", "ויקיפדיה"}), RunsFor(ascii_space_he)); - EXPECT_EQ(ToString16Vec({"Bit", " - ", "Wikipedia"}), + EXPECT_EQ(ToString16Vec({"Bit", " ", "-", " ", "Wikipedia"}), RunsFor(ascii_space_en)); EXPECT_EQ(ToString16Vec({"ども", " ", "ありがと"}), RunsFor(full_width_space)); @@ -4966,13 +5070,30 @@ TEST_F(RenderTextTest, HarfBuzz_BreakRunsByAscii) { RenderTextHarfBuzz* render_text = GetRenderText(); - // 🐱 (U+1F431, a cat face) and an ASCII period should have separate runs. - // Windows requires wide strings for \Unnnnnnnn universal character names. - render_text->SetText(WideToUTF16(L"\U0001F431.")); - test_api()->EnsureLayout(); + // ▶ (U+25B6, Geometric Shapes) and an ascii character should have + // different runs. + render_text->SetText(WideToUTF16(L"▶z")); + EXPECT_EQ(ToString16Vec({"▶", "z"}), GetRunListStrings()); + EXPECT_EQ("[0][1]", GetRunListStructureString()); + + // ★ (U+2605, Miscellaneous Symbols) and an ascii character should have + // different runs. + render_text->SetText(WideToUTF16(L"★1")); + EXPECT_EQ(ToString16Vec({"★", "1"}), GetRunListStrings()); + EXPECT_EQ("[0][1]", GetRunListStructureString()); + + // 🐱 (U+1F431, a cat face, Miscellaneous Symbols and Pictographs) and an + // ASCII period should have separate runs. + render_text->SetText(WideToUTF16(L"🐱.")); EXPECT_EQ(ToString16Vec({"🐱", "."}), GetRunListStrings()); // U+1F431 is represented as a surrogate pair in UTF-16. EXPECT_EQ("[0->1][2]", GetRunListStructureString()); + + // 🥴 (U+1f974, Supplemental Symbols and Pictographs) and an ascii character + // should have different runs. + render_text->SetText(WideToUTF16(L"🥴$")); + EXPECT_EQ(ToString16Vec({"🥴", "$"}), GetRunListStrings()); + EXPECT_EQ("[0->1][2]", GetRunListStructureString()); } // Test that, on Mac, font fallback mechanisms and Harfbuzz configuration cause @@ -5255,6 +5376,190 @@ ::testing::ValuesIn(kUnicodeDecomposeCases), RenderTextTestWithFallbackFontCase::ParamInfoToString); +// Ensures that RenderText is finding an appropriate font and that every +// codepoint can be rendered by the font. An error here can be by an incorrect +// ItemizeText(...) leading to an invalid fallback font. +const FallbackFontCase kComplexTextCases[] = { + {"simple1", L"test"}, + {"simple2", L"اختبار"}, + {"simple3", L"Δοκιμή"}, + {"simple4", L"परीक्षा"}, + {"simple5", L"تست"}, + {"simple6", L"Փորձարկում"}, + {"mixed1", L"www.اختبار.com"}, + {"mixed2", L"(اختبار)"}, + {"mixed3", L"/ זה (מבחן) /"}, +#if defined(OS_WIN) + {"asc_arb", L"abcښڛڜdef"}, + {"devanagari", L"ञटठडढणतथ"}, + {"ethiopic", L"መጩጪᎅⶹⶼ"}, + {"greek", L"ξοπρς"}, + {"kannada", L"ಠಡಢಣತಥ"}, + {"lao", L"ປຝພຟມ"}, + {"oriya", L"ଔକଖଗଘଙ"}, + {"telugu_lat", L"aaఉయ!"}, + {"common_math", L"ℳ: ¬ƒ(x)=½×¾"}, + {"picto_title", L"☞☛test☚☜"}, + {"common_numbers", L"𝟭𝟐⒓¹²"}, + {"common_puncts", L",.!"}, + {"common_space_math1", L" 𝓐"}, + {"common_space_math2", L" 𝓉"}, + {"common_split_spaces", L"♬ 𝓐"}, + {"common_mixed", L"\U0001d4c9\u24d4\U0001d42c"}, + {"arrows", L"↰↱↲↳↴↵⇚⇛⇜⇝⇞⇟"}, + {"arrows_space", L"↰ ↱ ↲ ↳ ↴ ↵ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟"}, + {"emoji_title", L"▶Feel goods"}, + {"enclosed_alpha", L"ⒶⒷⒸⒹⒺⒻⒼ"}, + {"shapes", L" ▶▷▸▹►▻◀◁◂◃◄◅"}, + {"symbols", L"☂☎☏☝☫☬☭☮☯"}, + {"symbols_space", L"☂ ☎ ☏ ☝ ☫ ☬ ☭ ☮ ☯"}, + {"dingbats", L"✂✃✄✆✇✈"}, + {"cjk_compatibility_ideographs", L"賈滑串句龜"}, + {"lat_dev_ZWNJ", L"a\u200Cक"}, + {"paren_picto", L"(☾☹☽)"}, + {"emoji1", L"This is 💩!"}, + {"emoji2", L"Look [🔝]"}, + {"strange1", L"💔♬ 𝓐 𝓉ⓔ𝐬т FỖ𝕣 c卄尺𝕆ᵐ€ ♘👹"}, + {"strange2", L"˜”*°•.˜”*°• A test for chrome •°*”˜.•°*”˜"}, + {"strange3", L"𝐭єⓢт fσ𝐑 𝔠ʰ𝕣ό𝐌𝔢"}, + {"strange4", L"тẸⓈ𝔱 𝔽𝕠ᖇ 𝕔𝐡ŕ𝔬ⓜẸ"}, + {"url1", L"http://www.google.com"}, + {"url2", L"http://www.nowhere.com/Lörick.html"}, + {"url3", L"http://www.nowhere.com/تسجيل الدخول"}, + {"url4", L"https://xyz.com:8080/تس(1)جيل الدخول"}, + {"url5", L"http://www.script.com/test.php?abc=42&cde=12&f=%20%20"}, + {"punct1", L"This‐is‑a‒test–for—punctuations"}, + {"punct2", L"⁅All ‷magic‴ comes with a ‶price″⁆"}, + {"punct3", L"⍟ Complete my sentence… †"}, + {"parens", L"❝This❞ 「test」 has ((a)) 【lot】 [{of}] 〚parentheses〛"}, + {"games", L"Let play: ♗♘⚀⚁♠♣"}, + {"braille", L"⠞⠑⠎⠞ ⠋⠕⠗ ⠉⠓⠗⠕⠍⠑"}, + {"emoticon1", L"¯\\_(ツ)_/¯"}, + {"emoticon2", L"٩(⁎❛ᴗ❛⁎)۶"}, + {"emoticon3", L"(͡° ͜ʖ ͡°)"}, + {"emoticon4", L"[̲̅$̲̅(̲̅5̲̅)̲̅$̲̅]"}, +#endif +}; + +INSTANTIATE_TEST_SUITE_P(FallbackFontComplexTextCases, + RenderTextTestWithFallbackFontCase, + ::testing::ValuesIn(kComplexTextCases), + RenderTextTestWithFallbackFontCase::ParamInfoToString); + +// Test cases to ensures the COMMON unicode script is split by unicode code +// block. These tests work on Windows and Mac default fonts installation. +// On other platforms, the fonts are mock (see test_fonts). +const FallbackFontCase kCommonScriptCases[] = { +#if defined(OS_WIN) + // The following tests are made to work on win7 and win10. + {"common00", L"\u237b\u2ac1\u24f5\u259f\u2a87\u23ea\u25d4\u2220"}, + {"common01", L"\u2303\u2074\u2988\u32b6\u26a2\u24e5\u2a53\u2219"}, + {"common02", L"\u29b2\u25fc\u2366\u24ae\u2647\u258e\u2654\u25fe"}, + {"common03", L"\u21ea\u22b4\u29b0\u2a84\u0008\u2657\u2731\u2697"}, + {"common04", L"\u2b3c\u2932\u21c8\u23cf\u20a1\u2aa2\u2344\u0011"}, + {"common05", L"\u22c3\u2a56\u2340\u21b7\u26ba\u2798\u220f\u2404"}, + {"common06", L"\u21f9\u25fd\u008e\u21e6\u2686\u21e4\u259f\u29ee"}, + {"common07", L"\u231e\ufe39\u0008\u2349\u2262\u2270\uff09\u2b3b"}, + {"common08", L"\u24a3\u236e\u29b2\u2259\u26ea\u2705\u00ae\u2a23"}, + {"common09", L"\u33bd\u235e\u2018\u32ba\u2973\u02c1\u20b9\u25b4"}, + {"common10", L"\u2245\u2a4d\uff19\u2042\u2aa9\u2658\u276e\uff40"}, + {"common11", L"\u0007\u21b4\u23c9\u2593\u21ba\u00a0\u258f\u23b3"}, + {"common12", L"\u2938\u250c\u2240\u2676\u2297\u2b07\u237e\u2a04"}, + {"common13", L"\u2520\u233a\u20a5\u2744\u2445\u268a\u2716\ufe62"}, + {"common14", L"\ufe4d\u25d5\u2ae1\u2a35\u2323\u273c\u26be\u2a3b"}, + {"common15", L"\u2aa2\u0000\ufe65\u2962\u2573\u21f8\u2651\u02d2"}, + {"common16", L"\u225c\u2283\u2960\u4de7\uff12\uffe1\u0016\u2905"}, + {"common17", L"\uff07\u25aa\u2076\u259e\u226c\u2568\u0026\u2691"}, + {"common18", L"\u2388\u21c2\u208d\u2a7f\u22d0\u2583\u2ad5\u240f"}, + {"common19", L"\u230a\u27ac\u001e\u261e\u259d\u25c3\u33a5\u0011"}, + {"common20", L"\ufe54\u29c7\u2477\u21ed\u2069\u4dfc\u2ae2\u21e8"}, + {"common21", L"\u2131\u2ab7\u23b9\u2660\u2083\u24c7\u228d\u2a01"}, + {"common22", L"\u2587\u2572\u21df\uff3c\u02cd\ufffd\u2404\u22b3"}, + {"common23", L"\u4dc3\u02fe\uff09\u25a3\ufe14\u255c\u2128\u2698"}, + {"common24", L"\u2b36\u3382\u02f6\u2752\uff16\u22cf\u00b0\u21d6"}, + {"common25", L"\u2561\u23db\u2958\u2782\u22af\u2621\u24a3\u29ae"}, + {"common26", L"\u2693\u22e2\u2988\u2987\u33ba\u2a94\u298e\u2328"}, + {"common27", L"\u266c\u2aa5\u2405\uffeb\uff5c\u2902\u291e\u02e6"}, + {"common28", L"\u2634\u32b2\u3385\u2032\u33be\u2366\u2ac7\u23cf"}, + {"common29", L"\u2981\ua721\u25a9\u2320\u21cf\u295a\u2273\u2ac2"}, + {"common30", L"\u22d9\u2465\u2347\u2a94\u4dca\u2389\u23b0\u208d"}, + {"common31", L"\u21cc\u2af8\u2912\u23a4\u2271\u2303\u241e\u33a1"}, +#elif defined(OS_ANDROID) + {"common00", L"\u2497\uff04\u277c\u21b6\u2076\u21e4\u2068\u21b3"}, + {"common01", L"\u2663\u2466\u338e\u226b\u2734\u21be\u3389\u00ab"}, + {"common02", L"\u2062\u2197\u3392\u2681\u33be\u206d\ufe10\ufe34"}, + {"common03", L"\u02db\u00b0\u02d3\u2745\u33d1\u21e4\u24e4\u33d6"}, + {"common04", L"\u21da\u261f\u26a1\u2586\u27af\u2560\u21cd\u25c6"}, + {"common05", L"\ufe51\uff17\u0027\u21fd\u24de\uff5e\u2606\u251f"}, + {"common06", L"\u2493\u2466\u21fc\u226f\u202d\u21a9\u0040\u265d"}, + {"common07", L"\u2103\u255a\u2153\u26be\u27ac\u222e\u2490\u21a4"}, + {"common08", L"\u270b\u2486\u246b\u263c\u27b6\u21d9\u219d\u25a9"}, + {"common09", L"\u002d\u2494\u25fd\u2321\u2111\u2511\u00d7\u2535"}, + {"common10", L"\u2523\u203e\u25b2\ufe18\u2499\u2229\ufd3e\ufe16"}, + {"common11", L"\u2133\u2716\u273f\u2064\u2248\u005c\u265f\u21e6"}, + {"common12", L"\u2060\u246a\u231b\u2726\u25bd\ufe40\u002e\u25ca"}, + {"common13", L"\ufe39\u24a2\ufe18\u254b\u249c\u3396\ua71f\u2466"}, + {"common14", L"\u21b8\u2236\u251a\uff11\u2077\u0035\u27bd\u2013"}, + {"common15", L"\u2668\u2551\u221a\u02bc\u2741\u2649\u2192\u00a1"}, + {"common16", L"\u2211\u21ca\u24dc\u2536\u201b\u21c8\u2530\u25fb"}, + {"common17", L"\u231a\u33d8\u2934\u27bb\u2109\u23ec\u20a9\u3000"}, + {"common18", L"\u2069\u205f\u33d3\u2466\u24a1\u24dd\u21ac\u21e3"}, + {"common19", L"\u2737\u219a\u21f1\u2285\u226a\u00b0\u27b2\u2746"}, + {"common20", L"\u264f\u2539\u2202\u264e\u2548\u2530\u2111\u2007"}, + {"common21", L"\u2799\u0035\u25e4\u265b\u24e2\u2044\u222b\u0021"}, + {"common22", L"\u2728\u00a2\u2533\ufe43\u33c9\u27a2\u02f9\u005d"}, + {"common23", L"\ufe68\u256c\u25b6\u276c\u2771\u33c4\u2712\u24b3"}, + {"common24", L"\ufe5d\ufe31\ufe3d\u205e\u2512\u33b8\u272b\ufe4f"}, + {"common25", L"\u24e7\u25fc\u2582\u2743\u2010\u2474\u2262\u251a"}, + {"common26", L"\u2020\u211c\u24b4\u33c7\u2007\uff0f\u267f\u00b4"}, + {"common27", L"\u266c\u3399\u2570\u33a4\u276e\u00a8\u2506\u24dc"}, + {"common28", L"\u2202\ufe43\u2511\u2191\u339a\u33b0\u02d7\u2473"}, + {"common29", L"\u2517\u2297\u2762\u2460\u25bd\u24a9\u21a7\ufe64"}, + {"common30", L"\u2105\u2722\u275d\u249c\u21a2\u2590\u2260\uff5d"}, + {"common31", L"\u33ba\u21c6\u2706\u02cb\ufe64\u02e6\u0374\u2493"}, +#else + // The following tests are made for the mock fonts (see test_fonts). + {"common00", L"\u2153\u24e0\u2109\u02f0\u2a8f\u25ed\u02c5\u2716"}, + {"common01", L"\u02f0\u208c\u2203\u2518\u2067\u2270\u21f1\ufe66"}, + {"common02", L"\u2686\u2585\u2b15\u246f\u23e3\u21b4\u2394\ufe31"}, + {"common03", L"\u23c1\u2a97\u201e\u2200\u3389\u25d3\u02c2\u259d"}, + {"common04", L"\u2075\u4dec\u252a\uff15\u4df6\u2668\u27fa\ufe17"}, + {"common05", L"\u260b\u2049\u3036\u2a85\u2b15\u23c7\u230a\u2374"}, + {"common06", L"\u2771\u27fa\u255d\uff0b\u2213\u3396\u2a85\u2276"}, + {"common07", L"\u211e\u2b06\u2255\u2727\u26c3\u33cf\u267d\u2ab2"}, + {"common08", L"\u2373\u20b3\u22b8\u2a0f\u02fd\u2585\u3036\ufe48"}, + {"common09", L"\u256d\u2940\u21d8\u4dde\u23a1\u226b\u3374\u2a99"}, + {"common10", L"\u270f\u24e5\u26c1\u2131\u21f5\u25af\u230f\u27fe"}, + {"common11", L"\u27aa\u23a2\u02ef\u2373\u2257\u2749\u2496\ufe31"}, + {"common12", L"\u230a\u25fb\u2117\u3386\u32cc\u21c5\u24c4\u207e"}, + {"common13", L"\u2467\u2791\u3393\u33bb\u02ca\u25de\ua788\u278f"}, + {"common14", L"\ua719\u25ed\u20a8\u20a1\u4dd8\u2295\u24eb\u02c8"}, + {"common15", L"\u22b6\u2520\u2036\uffee\u21df\u002d\u277a\u2b24"}, + {"common16", L"\u21f8\u211b\u22a0\u25b6\u263e\u2704\u221a\u2758"}, + {"common17", L"\ufe10\u2060\u24ac\u3385\u27a1\u2059\u2689\u2278"}, + {"common18", L"\u269b\u211b\u33a4\ufe36\u239e\u267f\u2423\u24a2"}, + {"common19", L"\u4ded\u262d\u225e\u248b\u21df\u279d\u2518\u21ba"}, + {"common20", L"\u225a\uff16\u21d4\u21c6\u02ba\u2545\u23aa\u005e"}, + {"common21", L"\u20a5\u265e\u3395\u2a6a\u2555\u22a4\u2086\u4dd4"}, + {"common22", L"\u203f\u3250\u2240\u24e9\u21cb\u258f\u24b1\u3259"}, + {"common23", L"\u27bd\u263b\uff1f\u2199\u2547\u258d\u201f\u2507"}, + {"common24", L"\u2482\u2548\u02dc\u231f\u24cd\u2198\u220e\u20ad"}, + {"common25", L"\u2ff7\u2540\ufe48\u2197\u276b\u2574\u2062\u3398"}, + {"common26", L"\u2663\u21cd\u263f\u23e5\u22d7\u2518\u21b9\u2628"}, + {"common27", L"\u21fa\ufe66\u2739\u2051\u21f4\u3399\u2599\u25f7"}, + {"common28", L"\u29d3\u25ec\u27a6\u24e0\u2735\u25b4\u2737\u25db"}, + {"common29", L"\u2622\u22e8\u33d2\u21d3\u2502\u2153\u2669\u25f2"}, + {"common30", L"\u2121\u21af\u2729\u203c\u337a\u2464\u2b08\u2e24"}, + {"common31", L"\u33cd\u007b\u02d2\u22cc\u32be\u2ffa\u2787\u02e9"}, + +#endif +}; + +INSTANTIATE_TEST_SUITE_P(FallbackFontCommonScript, + RenderTextTestWithFallbackFontCase, + ::testing::ValuesIn(kCommonScriptCases), + RenderTextTestWithFallbackFontCase::ParamInfoToString); + #if defined(OS_WIN) // Ensures that locale is used for fonts selection. TEST_F(RenderTextTest, CJKFontWithLocale) {
diff --git a/ui/platform_window/platform_window_linux.cc b/ui/platform_window/platform_window_linux.cc index 0e7ed45..af38162 100644 --- a/ui/platform_window/platform_window_linux.cc +++ b/ui/platform_window/platform_window_linux.cc
@@ -37,4 +37,6 @@ void PlatformWindowLinux::SetOpacityForXWindow(float opacity) {} +void PlatformWindowLinux::LowerXWindow() {} + } // namespace ui
diff --git a/ui/platform_window/platform_window_linux.h b/ui/platform_window/platform_window_linux.h index 29808f1..ca92ff6 100644 --- a/ui/platform_window/platform_window_linux.h +++ b/ui/platform_window/platform_window_linux.h
@@ -45,6 +45,10 @@ // X11-specific. Asks X11 to set transparency of the X11 Root Window. Not // used for Wayland as it uses alpha channel to blend a window instead. virtual void SetOpacityForXWindow(float opacity); + + // X11-specific. Asks X11 to lower the Xwindow down the stack so that it does + // not obscure any sibling windows. + virtual void LowerXWindow(); }; } // namespace ui
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc index 1e2e28d..e30189f7 100644 --- a/ui/platform_window/x11/x11_window.cc +++ b/ui/platform_window/x11/x11_window.cc
@@ -443,6 +443,10 @@ return ui::XVisualManager::GetInstance()->ArgbVisualAvailable(); } +void X11Window::LowerXWindow() { + XWindow::LowerWindow(); +} + bool X11Window::HandleAsAtkEvent(XEvent* xev) { #if !BUILDFLAG(USE_ATK) // TODO(crbug.com/1014934): Support ATK in Ozone/X11.
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h index 95540fe..118df36 100644 --- a/ui/platform_window/x11/x11_window.h +++ b/ui/platform_window/x11/x11_window.h
@@ -97,6 +97,7 @@ const gfx::ImageSkia& app_icon) override; void SizeConstraintsChanged() override; bool IsTranslucentWindowOpacitySupported() const override; + void LowerXWindow() override; protected: PlatformWindowDelegateLinux* platform_window_delegate() const {
diff --git a/ui/views/animation/animation_delegate_views.cc b/ui/views/animation/animation_delegate_views.cc index 9bd14c74..3f0c9117 100644 --- a/ui/views/animation/animation_delegate_views.cc +++ b/ui/views/animation/animation_delegate_views.cc
@@ -55,12 +55,6 @@ } void AnimationDelegateViews::UpdateAnimationRunner() { -#if defined(OS_CHROMEOS) - // TODO(crbug.com/969788): Re-enable this function with better ui::Compositor - // switching support. - return; -#endif // defined(OS_CHROMEOS) - if (!container_) return; @@ -74,8 +68,8 @@ if (container_->has_custom_animation_runner()) return; - container_->SetAnimationRunner(std::make_unique<CompositorAnimationRunner>( - view_->GetWidget()->GetCompositor())); + container_->SetAnimationRunner( + std::make_unique<CompositorAnimationRunner>(view_->GetWidget())); } } // namespace views
diff --git a/ui/views/animation/compositor_animation_runner.cc b/ui/views/animation/compositor_animation_runner.cc index f6a35410..2800c92 100644 --- a/ui/views/animation/compositor_animation_runner.cc +++ b/ui/views/animation/compositor_animation_runner.cc
@@ -4,37 +4,22 @@ #include "ui/views/animation/compositor_animation_runner.h" +#include "ui/views/widget/widget.h" + namespace views { //////////////////////////////////////////////////////////////////////////////// -// CompositorAnimationRunner::CompositorChecker -// -CompositorAnimationRunner::CompositorChecker::CompositorChecker( - CompositorAnimationRunner* runner) - : runner_(runner) { - scoped_observer_.Add(runner_->compositor_); -} - -CompositorAnimationRunner::CompositorChecker::~CompositorChecker() = default; - -void CompositorAnimationRunner::CompositorChecker::OnCompositingShuttingDown( - ui::Compositor* compositor) { - runner_->OnCompositingShuttingDown(compositor); - DCHECK(!compositor->HasAnimationObserver(runner_)); - scoped_observer_.Remove(compositor); -} - -//////////////////////////////////////////////////////////////////////////////// // CompositorAnimationRunner // -CompositorAnimationRunner::CompositorAnimationRunner(ui::Compositor* compositor) - : compositor_(compositor) { - DCHECK(compositor_); +CompositorAnimationRunner::CompositorAnimationRunner(Widget* widget) + : widget_(widget) { + widget_->AddObserver(this); } CompositorAnimationRunner::~CompositorAnimationRunner() { // Make sure we're not observing |compositor_|. - Stop(); + if (widget_) + OnWidgetDestroying(widget_); DCHECK(!compositor_ || !compositor_->HasAnimationObserver(this)); } @@ -43,6 +28,7 @@ compositor_->RemoveAnimationObserver(this); min_interval_ = base::TimeDelta::Max(); + compositor_ = nullptr; } void CompositorAnimationRunner::OnAnimationStep(base::TimeTicks timestamp) { @@ -56,14 +42,31 @@ void CompositorAnimationRunner::OnCompositingShuttingDown( ui::Compositor* compositor) { Stop(); - compositor_ = nullptr; +} + +void CompositorAnimationRunner::OnWidgetDestroying(Widget* widget) { + Stop(); + widget_->RemoveObserver(this); + widget_ = nullptr; } void CompositorAnimationRunner::OnStart(base::TimeDelta min_interval, base::TimeDelta elapsed) { - if (!compositor_) + if (!widget_) return; + ui::Compositor* current_compositor = widget_->GetCompositor(); + if (!current_compositor) { + Stop(); + return; + } + + if (current_compositor != compositor_) { + if (compositor_ && compositor_->HasAnimationObserver(this)) + compositor_->RemoveAnimationObserver(this); + compositor_ = current_compositor; + } + last_tick_ = base::TimeTicks::Now() - elapsed; min_interval_ = min_interval; DCHECK(!compositor_->HasAnimationObserver(this));
diff --git a/ui/views/animation/compositor_animation_runner.h b/ui/views/animation/compositor_animation_runner.h index 3833f22..4adbb86 100644 --- a/ui/views/animation/compositor_animation_runner.h +++ b/ui/views/animation/compositor_animation_runner.h
@@ -11,14 +11,19 @@ #include "ui/compositor/compositor_animation_observer.h" #include "ui/compositor/compositor_observer.h" #include "ui/gfx/animation/animation_container.h" +#include "ui/views/widget/widget_observer.h" namespace views { +class Widget; // An animation runner based on ui::Compositor. class CompositorAnimationRunner : public gfx::AnimationRunner, - public ui::CompositorAnimationObserver { + public ui::CompositorAnimationObserver, + public WidgetObserver { public: - explicit CompositorAnimationRunner(ui::Compositor* compositor); + explicit CompositorAnimationRunner(Widget* widget); + CompositorAnimationRunner(CompositorAnimationRunner&) = delete; + CompositorAnimationRunner& operator=(CompositorAnimationRunner&) = delete; ~CompositorAnimationRunner() override; // gfx::AnimationRunner: @@ -28,37 +33,25 @@ void OnAnimationStep(base::TimeTicks timestamp) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override; + // WidgetObserver: + void OnWidgetDestroying(Widget* widget) override; + protected: // gfx::AnimationRunner: void OnStart(base::TimeDelta min_interval, base::TimeDelta elapsed) override; private: - // This observes Compositor's destruction and helps CompositorAnimationRunner - // to stop animation. we need this because CompositorAnimationRunner observes - // the Compositor only when it's animating. - class CompositorChecker : public ui::CompositorObserver { - public: - explicit CompositorChecker(CompositorAnimationRunner* runner); - CompositorChecker(const CompositorChecker& other) = delete; - CompositorChecker& operator=(const CompositorChecker& other) = delete; - ~CompositorChecker() override; + // When |widget_| is nullptr, it means the widget has been destroyed and + // |compositor_| must also be nullptr. + Widget* widget_; - // ui::CompositorObserver: - void OnCompositingShuttingDown(ui::Compositor* compositor) override; - - private: - CompositorAnimationRunner* runner_; - ScopedObserver<ui::Compositor, ui::CompositorObserver> scoped_observer_{ - this}; - }; - - // When |compositor_| is nullptr, it means compositor has been shut down. - ui::Compositor* compositor_; + // When |compositor_| is nullptr, it means either the animation is not + // running, or the compositor or |widget_| associated with the compositor_ has + // been destroyed during animation. + ui::Compositor* compositor_ = nullptr; base::TimeDelta min_interval_ = base::TimeDelta::Max(); base::TimeTicks last_tick_; - - CompositorChecker checker_{this}; }; } // namespace views
diff --git a/ui/views/animation/compositor_animation_runner_unittest.cc b/ui/views/animation/compositor_animation_runner_unittest.cc index 78923d4..1ce2ca5 100644 --- a/ui/views/animation/compositor_animation_runner_unittest.cc +++ b/ui/views/animation/compositor_animation_runner_unittest.cc
@@ -12,22 +12,16 @@ namespace views { namespace test { +namespace { +constexpr base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(100); +} using CompositorAnimationRunnerTest = WidgetTest; -// TODO(crbug.com/969788): Re-enable CompositorAnimationRunner with better -// ui::Compositor switching support. -#if defined(OS_CHROMEOS) -#define MAYBE_BasicCoverageTest DISABLED_BasicCoverageTest -#else -#define MAYBE_BasicCoverageTest BasicCoverageTest -#endif -TEST_F(CompositorAnimationRunnerTest, MAYBE_BasicCoverageTest) { +TEST_F(CompositorAnimationRunnerTest, BasicCoverageTest) { WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget()); widget->Show(); - constexpr base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(100); - AnimationDelegateViews delegate(widget->GetContentsView()); gfx::LinearAnimation animation( kDuration, gfx::LinearAnimation::kDefaultFrameRate, &delegate); @@ -50,5 +44,67 @@ run_loop.Run(); } +// No DesktopAura on ChromeOS. +// Each widget on MACOSX has its own ui::Compositor. +#if !defined(OS_CHROMEOS) && !(OS_MACOSX) +using CompositorAnimationRunnerDesktopTest = DesktopWidgetTest; + +TEST_F(CompositorAnimationRunnerDesktopTest, SwitchCompositor) { + WidgetAutoclosePtr widget1(CreateTopLevelNativeWidget()); + widget1->Show(); + + WidgetAutoclosePtr widget2(CreateTopLevelNativeWidget()); + widget2->Show(); + + ASSERT_NE(widget1->GetCompositor(), widget2->GetCompositor()); + + Widget* child = CreateChildNativeWidgetWithParent(widget1.get()); + child->Show(); + AnimationDelegateViews delegate(child->GetContentsView()); + gfx::LinearAnimation animation( + kDuration, gfx::LinearAnimation::kDefaultFrameRate, &delegate); + + base::RepeatingTimer interval_timer; + + animation.Start(); + EXPECT_TRUE(animation.is_animating()); + EXPECT_TRUE(delegate.container()->has_custom_animation_runner()); + { + base::RunLoop run_loop; + interval_timer.Start(FROM_HERE, kDuration, + base::BindLambdaForTesting([&]() { + if (animation.is_animating()) + return; + interval_timer.Stop(); + run_loop.Quit(); + })); + run_loop.Run(); + } + + EXPECT_FALSE(animation.is_animating()); + + Widget::ReparentNativeView(child->GetNativeView(), widget2->GetNativeView()); + widget1.reset(); + + animation.Start(); + EXPECT_TRUE(animation.is_animating()); + EXPECT_TRUE(delegate.container()->has_custom_animation_runner()); + + { + base::RunLoop run_loop; + interval_timer.Start(FROM_HERE, kDuration, + base::BindLambdaForTesting([&]() { + if (animation.is_animating()) + return; + + interval_timer.Stop(); + run_loop.Quit(); + })); + + run_loop.Run(); + } +} +#endif + } // namespace test } // namespace views
diff --git a/ui/views/animation/installable_ink_drop.cc b/ui/views/animation/installable_ink_drop.cc index b4f5bbf37..2afeb76 100644 --- a/ui/views/animation/installable_ink_drop.cc +++ b/ui/views/animation/installable_ink_drop.cc
@@ -76,8 +76,7 @@ // Using CompositorAnimationRunner keeps our animation updates in sync with // compositor frames and avoids jank. animation_container_->SetAnimationRunner( - std::make_unique<CompositorAnimationRunner>( - view_->GetWidget()->GetCompositor())); + std::make_unique<CompositorAnimationRunner>(view_->GetWidget())); } }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc index 7b64e90..830255f 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -132,6 +132,10 @@ return GetPlatformWindowLinux()->ContainsPointInXRegion(point); } +void DesktopWindowTreeHostLinux::LowerXWindow() { + GetPlatformWindowLinux()->LowerXWindow(); +} + base::OnceClosure DesktopWindowTreeHostLinux::DisableEventListening() { // Allows to open multiple file-pickers. See https://crbug.com/678982 modal_dialog_counter_++;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h index e15b869c..653fa59 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
@@ -65,6 +65,11 @@ // Wayland. bool ContainsPointInXRegion(const gfx::Point& point) const; + // Tells the X server to lower the |platform_window()| owned by this host down + // the stack so that it does not obscure any sibling windows. Not in use for + // Wayland. + void LowerXWindow(); + // Disables event listening to make |dialog| modal. base::OnceClosure DisableEventListening();
diff --git a/ui/views/widget/desktop_aura/window_event_filter_linux.cc b/ui/views/widget/desktop_aura/window_event_filter_linux.cc index a0646f0..f1729e53 100644 --- a/ui/views/widget/desktop_aura/window_event_filter_linux.cc +++ b/ui/views/widget/desktop_aura/window_event_filter_linux.cc
@@ -149,7 +149,9 @@ desktop_window_tree_host_->Maximize(); } -void WindowEventFilterLinux::LowerWindow() {} +void WindowEventFilterLinux::LowerWindow() { + desktop_window_tree_host_->LowerXWindow(); +} void WindowEventFilterLinux::MaybeDispatchHostWindowDragMovement( int hittest,
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 83a2512a..670250d 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -12,7 +12,6 @@ #include "base/base64.h" #include "base/bind.h" -#include "base/lazy_instance.h" #include "base/mac/scoped_nsobject.h" #include "base/no_destructor.h" #include "base/strings/sys_string_conversions.h" @@ -43,9 +42,6 @@ namespace { -base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky - g_gesture_recognizer_instance = LAZY_INSTANCE_INITIALIZER; - static base::RepeatingCallback<void(NativeWidgetMac*)>* g_init_native_widget_callback = nullptr; @@ -732,7 +728,8 @@ } ui::GestureRecognizer* NativeWidgetMac::GetGestureRecognizer() { - return g_gesture_recognizer_instance.Pointer(); + static base::NoDestructor<ui::GestureRecognizerImplMac> recognizer; + return recognizer.get(); } void NativeWidgetMac::OnSizeConstraintsChanged() { @@ -963,7 +960,7 @@ for (auto* child : widgets) child->NotifyNativeViewHierarchyWillChange(); - // Update |brige_host|'s parent only if + // Update |bridge_host|'s parent only if // NativeWidgetNSWindowBridge::ReparentNativeView will. if (native_view == bridge_view) { window_host->SetParent(parent_window_host);
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html index 2a06b18..b6c3856 100644 --- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html +++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html
@@ -111,17 +111,18 @@ #cameraControls cr-icon-button { --cr-icon-button-color: white; + --cr-icon-button-focus-color: var(--google-blue-500); --cr-icon-button-icon-size: 20px; --cr-icon-button-size: 28px; margin: 0; } #takePhoto { - background-image: url(camera_shutter_icon.svg); + --cr-icon-image: url(camera_shutter_icon.svg); } :host([videomode]) #takePhoto { - background-image: url(videocam_shutter_icon.svg); + --cr-icon-image: url(videocam_shutter_icon.svg); } :host-context([dir=rtl]) #switchMode { @@ -129,11 +130,11 @@ } #switchMode { - background-image: url(videocam_icon.svg); + --cr-icon-image: url(videocam_icon.svg); } :host([videomode]) #switchMode { - background-image: url(camera_alt_icon.svg); + --cr-icon-image: url(camera_alt_icon.svg); } </style> <div id="perspectiveBox">
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html index afefb94..6cc40e37 100644 --- a/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html +++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.html
@@ -58,6 +58,7 @@ cr-icon-button { --cr-icon-button-color: white; + --cr-icon-button-focus-color: var(--google-blue-500); --cr-icon-button-icon-size: 24px; --cr-icon-button-size: 28px; margin: 0;
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html index 12dfc7f..f889e4bb 100644 --- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html +++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
@@ -13,12 +13,10 @@ --cr-icon-button-icon-size: 20px; --cr-icon-button-size: 36px; --cr-icon-button-height: var(--cr-icon-button-size); + --cr-icon-button-transition: 150ms ease-in-out; --cr-icon-button-width: var(--cr-icon-button-size); /* Copied from paper-fab.html. Prevents square touch highlight. */ -webkit-tap-highlight-color: transparent; - background-position: center; - background-repeat: no-repeat; - background-size: var(--cr-icon-button-icon-size); border-radius: 4px; color: var(--cr-icon-button-color); cursor: pointer; @@ -40,25 +38,29 @@ pointer-events: none; } + :host(.no-overlap) { + --cr-icon-button-margin-end: 0; + --cr-icon-button-margin-start: 0; + } + :host-context([dir=rtl]) { transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ } - @media (prefers-color-scheme: dark) { - :host { - --cr-icon-button-color: var(--google-grey-refresh-500); - } + :host(:not([iron-icon])) #maskedImage { + -webkit-mask-image: var(--cr-icon-image); + -webkit-mask-position: center; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: var(--cr-icon-button-icon-size); + background-color: var(--cr-icon-button-color); + height: 100%; + transition: background-color var(--cr-icon-button-transition); + width: 100%; + z-index: 1; } - :host paper-ripple { - /* GG900 .15 is about GG700 .21 */ - --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .21); - } - - @media (prefers-color-scheme: dark) { - :host paper-ripple { - --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .4); - } + :host-context([a11y-enhanced]):host([ripple-showing_]) #maskedImage { + background-color: var(--cr-icon-button-focus-color, white); } #icon { @@ -74,11 +76,61 @@ } iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-color); --iron-icon-height: var(--cr-icon-button-icon-size); --iron-icon-width: var(--cr-icon-button-icon-size); + transition: fill var(--cr-icon-button-transition); + z-index: 1; + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-focus-color, white); + } + + paper-ripple { + /* GG900 .15 is about GG700 .21 */ + --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .21); + } + + + :host-context([a11y-enhanced]) paper-ripple { + --paper-ripple-opacity: 1; + opacity: 0; + transition: opacity var(--cr-icon-button-transition); + } + + @media (prefers-color-scheme: dark) { + :host { + --cr-icon-button-color: var(--google-grey-refresh-500); + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-focus-color, + var(--google-grey-900)); + } + + :host(:not([iron-icon])) #maskedImage { + background-color: var(--cr-icon-button-color, + var(--google-grey-refresh-500)); + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) #maskedImage { + background-color: var(--cr-icon-button-focus-color, + var(--google-grey-900)); + } + + paper-ripple { + --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .4); + } + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) paper-ripple { + opacity: 1; } </style> - <div id="icon"></div> + <div id="icon"> + <div id="maskedImage"></div> + </div> </template> <script src="cr_icon_button.js"></script> </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js index 5f103f62..d86cd00 100644 --- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js +++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
@@ -44,6 +44,14 @@ ironIcon: { type: String, observer: 'onIronIconChanged_', + reflectToAttribute: true, + }, + + /** @private */ + rippleShowing_: { + type: Boolean, + value: false, + reflectToAttribute: true, }, }, @@ -56,6 +64,7 @@ listeners: { blur: 'hideRipple_', click: 'onClick_', + down: 'showRipple_', focus: 'showRipple_', keydown: 'onKeyDown_', keyup: 'onKeyUp_', @@ -67,6 +76,7 @@ hideRipple_: function() { if (this.hasRipple()) { this.getRipple().clear(); + this.rippleShowing_ = false; } }, @@ -74,6 +84,7 @@ showRipple_: function() { if (!this.noink && !this.disabled) { this.getRipple().showAndHoldDown(); + this.rippleShowing_ = true; } },
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html index f3fdcfb..aeddcc3c 100644 --- a/ui/webui/resources/cr_elements/cr_icons_css.html +++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -4,166 +4,95 @@ <dom-module id="cr-icons"> <template> <style> - :host-context([dir=rtl]) .cr-icon { - transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ + .icon-arrow-back { + --cr-icon-image: url(../images/icon_arrow_back.svg); + } + + .icon-arrow-dropdown { + --cr-icon-image: url(../images/icon_arrow_dropdown.svg); + } + + .icon-cancel { + --cr-icon-image: url(../images/icon_cancel.svg); + } + + .icon-clear { + --cr-icon-image: url(../images/icon_clear.svg); + } + + .icon-delete-gray { + --cr-icon-image: url(../images/icon_delete_gray.svg); + } + + .icon-picture-delete { + --cr-icon-image: url(../images/icon_picture_delete.svg); + } + + .icon-expand-less { + --cr-icon-image: url(../images/icon_expand_less.svg); + } + + .icon-expand-more { + --cr-icon-image: url(../images/icon_expand_more.svg); + } + + .icon-external { + --cr-icon-image: url(../images/open_in_new.svg); + } + + .icon-more-vert { + --cr-icon-image: url(../images/icon_more_vert.svg); + } + + .icon-refresh { + --cr-icon-image: url(../images/icon_refresh.svg); + } + + .icon-search { + --cr-icon-image: url(../images/icon_search.svg); + } + + .icon-settings { + --cr-icon-image: url(../images/icon_settings.svg); + } + + .icon-visibility { + --cr-icon-image: url(../images/icon_visibility.svg); + } + + .icon-visibility-off { + --cr-icon-image: url(../images/icon_visibility_off.svg); + } + + .subpage-arrow { + --cr-icon-image: url(../images/arrow_right.svg); } .cr-icon { @apply --cr-paper-icon-button-margin; - background-position: center; - background-repeat: no-repeat; - background-size: var(--cr-icon-size); + -webkit-mask-image: var(--cr-icon-image); + -webkit-mask-position: center; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: var(--cr-icon-size); + background-color: var(--google-grey-refresh-700); flex-shrink: 0; height: var(--cr-icon-ripple-size); user-select: none; width: var(--cr-icon-ripple-size); } - :-webkit-any(cr-icon-button, .cr-icon).no-overlap { + :host-context([dir=rtl]) .cr-icon { + transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ + } + + .cr-icon.no-overlap { margin-inline-end: 0; margin-inline-start: 0; } - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-back { - background-image: url(../images/icon_arrow_back.svg); - } @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-back { - background-image: url(../images/dark/icon_arrow_back.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-cancel { - background-image: url(../images/icon_cancel.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-cancel { - background-image: url(../images/dark/icon_cancel.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-clear { - background-image: url(../images/icon_clear.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-clear { - background-image: url(../images/dark/icon_clear.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-delete-gray { - background-image: url(../images/icon_delete_gray.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-delete-gray { - background-image: url(../images/dark/icon_delete_gray.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-picture-delete { - background-image: url(../images/icon_picture_delete.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-picture-delete { - background-image: url(../images/dark/icon_picture_delete.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-less { - background-image: url(../images/icon_expand_less.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-less { - background-image: url(../images/dark/icon_expand_less.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-more { - background-image: url(../images/icon_expand_more.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-more { - background-image: url(../images/dark/icon_expand_more.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-external { - background-image: url(../images/open_in_new.svg); - } - /* Open in new is the same for light and dark mode. */ - - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert { - background-image: url(../images/icon_more_vert.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert { - background-image: url(../images/dark/icon_more_vert.svg); - } - } - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert-light-mode { - background-image: url(../images/icon_more_vert.svg); - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-refresh { - background-image: url(../images/icon_refresh.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-refresh { - background-image: url(../images/dark/icon_refresh.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-settings { - background-image: url(../images/icon_settings.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-settings { - background-image: url(../images/dark/icon_settings.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-search { - background-image: url(../images/icon_search.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-search { - background-image: url(../images/dark/icon_search.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-dropdown { - background-image: url(../images/icon_arrow_dropdown.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-dropdown { - background-image: url(../images/dark/icon_arrow_dropdown.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).subpage-arrow { - background-image: url(../images/arrow_right.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).subpage-arrow { - background-image: url(../images/dark/arrow_right.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility { - background-image: url(../images/icon_visibility.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility { - background-image: url(../images/dark/icon_visibility.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility-off { - background-image: url(../images/icon_visibility_off.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility-off { - background-image: url(../images/dark/icon_visibility_off.svg); + .cr-icon { + background-color: var(--google-grey-refresh-500); } } </style>
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html index 034bffd..a899d48 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
@@ -12,6 +12,7 @@ <template> <style include="cr-icons cr-hidden-style"> :host { + --cr-icon-button-focus-color: var(--google-blue-700); align-items: center; background-color: var(--google-blue-700); color: #fff; @@ -21,6 +22,9 @@ @media (prefers-color-scheme: dark) { :host { + /* Toolbar background color rgba(255, 255, 255, .04) added to body + background color --google-grey-900. */ + --cr-icon-button-focus-color: #28292c; background-color: rgba(255, 255, 255, .04); border-bottom: var(--cr-separator-line); box-sizing: border-box;
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html index 7d4d186..3eb5dbd 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -31,15 +31,14 @@ @media (prefers-color-scheme: light) { cr-icon-button { - --cr-icon-button-color: currentColor; - --iron-icon-fill-color: - var(--cr-toolbar-search-field-input-color, white); + --cr-icon-button-color: var(--cr-toolbar-search-field-input-color, + white); } } @media (prefers-color-scheme: dark) { cr-icon-button { - --iron-icon-fill-color: var(--cr-toolbar-search-field-input-color, + --cr-icon-button-color: var(--cr-toolbar-search-field-input-color, var(--google-grey-refresh-500)); } }
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html index 292378f..8b18b8e 100644 --- a/ui/webui/resources/cr_elements/shared_style_css.html +++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -25,16 +25,6 @@ cursor: pointer; } - .subpage-arrow, - .icon-external { - display: none; - } - - [actionable] :-webkit-any(.subpage-arrow, .icon-external), - [actionable]:-webkit-any(.subpage-arrow, .icon-external) { - display: block; - } - /* Horizontal rule line. */ .hr { border-top: var(--cr-separator-line);
diff --git a/ui/webui/resources/cr_elements_images.grdp b/ui/webui/resources/cr_elements_images.grdp index 7c12c157..1f0b8227 100644 --- a/ui/webui/resources/cr_elements_images.grdp +++ b/ui/webui/resources/cr_elements_images.grdp
@@ -9,46 +9,8 @@ file="images/arrow_right.svg" type="BINDATA" compress="gzip" /> <include name="IDR_WEBUI_IMAGES_DARK_ARROW_DOWN" file="images/dark/arrow_down.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ARROW_RIGHT" - file="images/dark/arrow_right.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_ARROW_BACK" - file="images/dark/icon_arrow_back.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_ARROW_DROPDOWN" - file="images/dark/icon_arrow_dropdown.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_CANCEL" - file="images/dark/icon_cancel.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_CLEAR" - file="images/dark/icon_clear.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_DELETE_GRAY" - file="images/dark/icon_delete_gray.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_EXPAND_LESS" - file="images/dark/icon_expand_less.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_EXPAND_MORE" - file="images/dark/icon_expand_more.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_MORE_VERT" - file="images/dark/icon_more_vert.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_PICTURE_DELETE" - file="images/dark/icon_picture_delete.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_REFRESH" - file="images/dark/icon_refresh.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_SETTINGS" - file="images/dark/icon_settings.svg" type="BINDATA" - compress="gzip" /> <include name="IDR_WEBUI_IMAGES_DARK_ICON_SEARCH" file="images/dark/icon_search.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_VISIBILITY" - file="images/dark/icon_visibility.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_VISIBILITY_OFF" - file="images/dark/icon_visibility_off.svg" type="BINDATA" - compress="gzip" /> <include name="IDR_WEBUI_IMAGES_ICON_ARROW_BACK" file="images/icon_arrow_back.svg" type="BINDATA" compress="gzip" /> <include name="IDR_WEBUI_IMAGES_ICON_ARROW_DROPDOWN"
diff --git a/ui/webui/resources/images/dark/arrow_right.svg b/ui/webui/resources/images/dark/arrow_right.svg deleted file mode 100644 index a1e71de..0000000 --- a/ui/webui/resources/images/dark/arrow_right.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M10 7l5 5-5 5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_arrow_back.svg b/ui/webui/resources/images/dark/icon_arrow_back.svg deleted file mode 100644 index 5747b495..0000000 --- a/ui/webui/resources/images/dark/icon_arrow_back.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_arrow_dropdown.svg b/ui/webui/resources/images/dark/icon_arrow_dropdown.svg deleted file mode 100644 index e68ecf14..0000000 --- a/ui/webui/resources/images/dark/icon_arrow_dropdown.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M7 10l5 5 5-5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_cancel.svg b/ui/webui/resources/images/dark/icon_cancel.svg deleted file mode 100644 index 8cc110e8..0000000 --- a/ui/webui/resources/images/dark/icon_cancel.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 2 4" fill="#9aa0a6"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_clear.svg b/ui/webui/resources/images/dark/icon_clear.svg deleted file mode 100644 index e54b804..0000000 --- a/ui/webui/resources/images/dark/icon_clear.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_delete_gray.svg b/ui/webui/resources/images/dark/icon_delete_gray.svg deleted file mode 100644 index fe178de..0000000 --- a/ui/webui/resources/images/dark/icon_delete_gray.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_expand_less.svg b/ui/webui/resources/images/dark/icon_expand_less.svg deleted file mode 100644 index 2ff69ede..0000000 --- a/ui/webui/resources/images/dark/icon_expand_less.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="#9aa0a6" width="24" height="24"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_expand_more.svg b/ui/webui/resources/images/dark/icon_expand_more.svg deleted file mode 100644 index 9ae4310..0000000 --- a/ui/webui/resources/images/dark/icon_expand_more.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="#9aa0a6" width="24" height="24"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_more_vert.svg b/ui/webui/resources/images/dark/icon_more_vert.svg deleted file mode 100644 index 1e86d68ec..0000000 --- a/ui/webui/resources/images/dark/icon_more_vert.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_picture_delete.svg b/ui/webui/resources/images/dark/icon_picture_delete.svg deleted file mode 100644 index f582d05..0000000 --- a/ui/webui/resources/images/dark/icon_picture_delete.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#e8eaed"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_refresh.svg b/ui/webui/resources/images/dark/icon_refresh.svg deleted file mode 100644 index 6542cec..0000000 --- a/ui/webui/resources/images/dark/icon_refresh.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_settings.svg b/ui/webui/resources/images/dark/icon_settings.svg deleted file mode 100644 index 33a55b9e6..0000000 --- a/ui/webui/resources/images/dark/icon_settings.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65A.488.488 0 0 0 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_visibility.svg b/ui/webui/resources/images/dark/icon_visibility.svg deleted file mode 100644 index 2352cc47..0000000 --- a/ui/webui/resources/images/dark/icon_visibility.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_visibility_off.svg b/ui/webui/resources/images/dark/icon_visibility_off.svg deleted file mode 100644 index 9cd712c..0000000 --- a/ui/webui/resources/images/dark/icon_visibility_off.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46A11.804 11.804 0 0 0 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></svg> \ No newline at end of file
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index eb275a5b..ec32a39 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -122,6 +122,7 @@ "//components/security_interstitials/content:security_interstitial_page", "//components/security_interstitials/content/renderer:security_interstitial_page_controller", "//components/security_interstitials/core", + "//components/web_cache/browser", "//content:resources", "//content/app/resources", "//content/public/app:both",
diff --git a/weblayer/browser/DEPS b/weblayer/browser/DEPS index 777968d1..772cf5b 100644 --- a/weblayer/browser/DEPS +++ b/weblayer/browser/DEPS
@@ -4,6 +4,7 @@ "+components/embedder_support", "+components/safe_browsing", "+components/security_interstitials", + "+components/web_cache/browser", "+content/public", "+mojo/public", "+net",
diff --git a/weblayer/browser/browser_controller_impl.cc b/weblayer/browser/browser_controller_impl.cc index 8d86ee68..d818a323 100644 --- a/weblayer/browser/browser_controller_impl.cc +++ b/weblayer/browser/browser_controller_impl.cc
@@ -119,8 +119,10 @@ } BrowserControllerImpl::~BrowserControllerImpl() { - // Destruct this now to avoid it calling back when this object is partially - // destructed. + // Destruct WebContents now to avoid it calling back when this object is + // partially destructed. DidFinishNavigation can be called while destroying + // WebContents, so stop observing first. + Observe(nullptr); web_contents_.reset(); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index 099498f7..0b28558a 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -17,6 +17,7 @@ import org.chromium.base.ContentUriUtils; import org.chromium.base.ContextUtils; import org.chromium.base.PathUtils; +import org.chromium.base.StrictModeContext; import org.chromium.base.annotations.UsedByReflection; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; @@ -98,13 +99,21 @@ "org.chromium.weblayer.ChildProcessService$Sandboxed"); if (!CommandLine.isInitialized()) { - CommandLine.initFromFile(COMMAND_LINE_FILE); + // This disk read in the critical path is for development purposes only. + // TODO: Move it to debug-only (similar to WebView), or allow clients to configure the + // command line. + try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { + CommandLine.initFromFile(COMMAND_LINE_FILE); + } } DeviceUtils.addDeviceSpecificUserAgentSwitch(); ContentUriUtils.setFileProviderUtil(new FileProviderHelper()); - LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_WEBLAYER); + // TODO: Validate that doing this disk IO on the main thread is necessary. + try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { + LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_WEBLAYER); + } GmsBridge.getInstance().setSafeBrowsingHandler(); final ValueCallback<Boolean> loadedCallback = (ValueCallback<Boolean>) ObjectWrapper.unwrap(
diff --git a/weblayer/browser/profile_impl.cc b/weblayer/browser/profile_impl.cc index ac2d3b6..fdac4a1 100644 --- a/weblayer/browser/profile_impl.cc +++ b/weblayer/browser/profile_impl.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/callback_forward.h" #include "build/build_config.h" +#include "components/web_cache/browser/web_cache_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/download_manager_delegate.h" @@ -192,6 +193,10 @@ }; ProfileImpl::ProfileImpl(const base::FilePath& path) : path_(path) { + // Ensure WebCacheManager is created so that it starts observing + // OnRenderProcessHostCreated events. + web_cache::WebCacheManager::GetInstance(); + browser_context_ = std::make_unique<BrowserContextImpl>(path_); } @@ -225,6 +230,7 @@ break; case BrowsingDataType::CACHE: remove_mask |= content::BrowsingDataRemover::DATA_TYPE_CACHE; + ClearRendererCache(); break; default: NOTREACHED(); @@ -233,6 +239,19 @@ clearer->ClearData(remove_mask, from_time, to_time); } +void ProfileImpl::ClearRendererCache() { + for (content::RenderProcessHost::iterator iter = + content::RenderProcessHost::AllHostsIterator(); + !iter.IsAtEnd(); iter.Advance()) { + content::RenderProcessHost* render_process_host = iter.GetCurrentValue(); + if (render_process_host->GetBrowserContext() == browser_context_.get() && + render_process_host->IsInitializedAndNotDead()) { + web_cache::WebCacheManager::GetInstance()->ClearCacheForProcess( + render_process_host->GetID()); + } + } +} + std::unique_ptr<Profile> Profile::Create(const base::FilePath& path) { return std::make_unique<ProfileImpl>(path); }
diff --git a/weblayer/browser/profile_impl.h b/weblayer/browser/profile_impl.h index 1646769..f9a10e9 100644 --- a/weblayer/browser/profile_impl.h +++ b/weblayer/browser/profile_impl.h
@@ -49,6 +49,8 @@ class BrowserContextImpl; class DataClearer; + void ClearRendererCache(); + base::FilePath path_; std::unique_ptr<BrowserContextImpl> browser_context_;
diff --git a/weblayer/grit_strings_whitelist.txt b/weblayer/grit_strings_whitelist.txt index 9233f3d..907d69c 100644 --- a/weblayer/grit_strings_whitelist.txt +++ b/weblayer/grit_strings_whitelist.txt
@@ -1,7 +1,13 @@ IDS_SSL_OPEN_DETAILS_BUTTON IDS_SSL_CLOSE_DETAILS_BUTTON +IDS_SSL_NONOVERRIDABLE_HSTS +IDS_SSL_NONOVERRIDABLE_INVALID +IDS_SSL_NONOVERRIDABLE_MORE +IDS_SSL_NONOVERRIDABLE_PINNED +IDS_SSL_NONOVERRIDABLE_REVOKED IDS_SSL_OVERRIDABLE_SAFETY_BUTTON IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH +IDS_SSL_RELOAD IDS_SSL_V2_TITLE IDS_SSL_V2_HEADING IDS_SSL_V2_PRIMARY_PARAGRAPH
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn index a371f2eb..4d5dfdb 100644 --- a/weblayer/shell/android/BUILD.gn +++ b/weblayer/shell/android/BUILD.gn
@@ -217,7 +217,7 @@ "javatests/src/org/chromium/weblayer/test/EventUtils.java", "javatests/src/org/chromium/weblayer/test/EventUtils.java", "javatests/src/org/chromium/weblayer/test/ExecuteScriptTest.java", - "javatests/src/org/chromium/weblayer/test/FragmentRestoreTest.java", + "javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java", "javatests/src/org/chromium/weblayer/test/FullscreenCallbackTest.java", "javatests/src/org/chromium/weblayer/test/InputTypesTest.java", "javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java",
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java new file mode 100644 index 0000000..e8795f8 --- /dev/null +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java
@@ -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. + +package org.chromium.weblayer.test; + +import android.net.Uri; +import android.support.test.filters.SmallTest; +import android.support.v4.app.FragmentManager; + +import androidx.annotation.NonNull; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.weblayer.BrowserController; +import org.chromium.weblayer.Navigation; +import org.chromium.weblayer.NavigationCallback; +import org.chromium.weblayer.NavigationController; +import org.chromium.weblayer.shell.InstrumentationActivity; + +import java.util.concurrent.CountDownLatch; + +@RunWith(BaseJUnit4ClassRunner.class) +public class BrowserFragmentLifecycleTest { + @Rule + public InstrumentationActivityTestRule mActivityTestRule = + new InstrumentationActivityTestRule(); + + @Test + @SmallTest + public void successfullyLoadsUrlAfterRecreation() { + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); + BrowserController controller = TestThreadUtils.runOnUiThreadBlockingNoException( + () -> activity.getBrowserController()); + + String url = "data:text,foo"; + mActivityTestRule.navigateAndWait(controller, url, false); + + mActivityTestRule.recreateActivity(); + + InstrumentationActivity newActivity = mActivityTestRule.getActivity(); + controller = TestThreadUtils.runOnUiThreadBlockingNoException( + () -> newActivity.getBrowserController()); + url = "data:text,bar"; + mActivityTestRule.navigateAndWait(controller, url, false); + } + + // https://crbug.com/1021041 + @Test + @SmallTest + public void handlesFragmentDestroyWhileNavigating() throws InterruptedException { + CountDownLatch latch = new CountDownLatch(1); + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); + TestThreadUtils.runOnUiThreadBlocking(() -> { + NavigationController navigationController = + activity.getBrowserController().getNavigationController(); + navigationController.registerNavigationCallback(new NavigationCallback() { + @Override + public void readyToCommitNavigation(@NonNull Navigation navigation) { + FragmentManager fm = activity.getSupportFragmentManager(); + fm.beginTransaction() + .remove(fm.getFragments().get(0)) + .runOnCommit(latch::countDown) + .commit(); + } + }); + navigationController.navigate(Uri.parse("data:text,foo")); + }); + latch.await(); + } +}
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/FragmentRestoreTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/FragmentRestoreTest.java deleted file mode 100644 index e99195a..0000000 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/FragmentRestoreTest.java +++ /dev/null
@@ -1,42 +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. - -package org.chromium.weblayer.test; - -import android.support.test.filters.SmallTest; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.weblayer.BrowserController; -import org.chromium.weblayer.shell.InstrumentationActivity; - -@RunWith(BaseJUnit4ClassRunner.class) -public class FragmentRestoreTest { - @Rule - public InstrumentationActivityTestRule mActivityTestRule = - new InstrumentationActivityTestRule(); - - @Test - @SmallTest - public void successfullyLoadsUrlAfterRotation() { - InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); - BrowserController controller = TestThreadUtils.runOnUiThreadBlockingNoException( - () -> activity.getBrowserController()); - - String url = "data:text,foo"; - mActivityTestRule.navigateAndWait(controller, url, false); - - mActivityTestRule.recreateActivity(); - - InstrumentationActivity newActivity = mActivityTestRule.getActivity(); - controller = TestThreadUtils.runOnUiThreadBlockingNoException( - () -> newActivity.getBrowserController()); - url = "data:text,bar"; - mActivityTestRule.navigateAndWait(controller, url, false); - } -}
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InputTypesTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InputTypesTest.java index a3aaa4c..6f33f8d 100644 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InputTypesTest.java +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InputTypesTest.java
@@ -30,8 +30,10 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.InMemorySharedPreferencesContext; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.weblayer.shell.InstrumentationActivity; @@ -49,6 +51,7 @@ private EmbeddedTestServer mTestServer; private File mTempFile; + private int mCameraPermission = PackageManager.PERMISSION_GRANTED; private class FileIntentInterceptor implements InstrumentationActivity.IntentInterceptor { public Intent mLastIntent; @@ -94,9 +97,7 @@ new Handler().post(() -> { int[] results = new int[permissions.length]; Arrays.fill(results, mResult); - if (mResult == PackageManager.PERMISSION_GRANTED) { - grantCameraPermission(); - } + mCameraPermission = mResult; activity.onRequestPermissionsResult(requestCode, permissions, results); mCallbackHelper.notifyCalled(); }); @@ -132,8 +133,22 @@ mTestServer.addDefaultHandlers("weblayer/test/data"); Assert.assertTrue(mTestServer.start(0)); - InstrumentationActivity activity = - mActivityTestRule.launchShellWithUrl(mTestServer.getURL("/input_types.html")); + InstrumentationActivity activity = mActivityTestRule.launchShell(new Bundle()); + TestThreadUtils.runOnUiThreadBlocking(() -> { + activity.createWebLayer( + new InMemorySharedPreferencesContext(activity.getApplication()) { + @Override + public int checkPermission(String permission, int pid, int uid) { + if (permission.equals(Manifest.permission.CAMERA)) { + return mCameraPermission; + } + return getBaseContext().checkPermission(permission, pid, uid); + } + }, + null) + .get(); + }); + mActivityTestRule.navigateAndWait(mTestServer.getURL("/input_types.html")); mTempFile = File.createTempFile("file", null); activity.setIntentInterceptor(mIntentInterceptor); ActivityCompat.setPermissionCompatDelegate(mPermissionCompatDelegate); @@ -146,8 +161,6 @@ @After public void tearDown() { mTempFile.delete(); - // The test may have revoked camera permission, so grant it back now. - grantCameraPermission(); ActivityCompat.setPermissionCompatDelegate(null); } @@ -165,9 +178,9 @@ @Test @SmallTest - @MinAndroidSdkLevel(Build.VERSION_CODES.P) - public void testFileInputCameraPermissionGranted() { - revokeCameraPermission(); + @MinAndroidSdkLevel(Build.VERSION_CODES.M) + public void testFileInputCameraPermissionGranted() throws Exception { + mCameraPermission = PackageManager.PERMISSION_DENIED; mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_GRANTED); String id = "input_file"; @@ -184,9 +197,9 @@ @Test @SmallTest - @MinAndroidSdkLevel(Build.VERSION_CODES.P) - public void testFileInputCameraPermissionDenied() { - revokeCameraPermission(); + @MinAndroidSdkLevel(Build.VERSION_CODES.M) + public void testFileInputCameraPermissionDenied() throws Exception { + mCameraPermission = PackageManager.PERMISSION_DENIED; mPermissionCompatDelegate.setResult(PackageManager.PERMISSION_DENIED); String id = "input_file"; @@ -326,20 +339,4 @@ Assert.assertNotNull(contentIntent); return contentIntent; } - - @TargetApi(Build.VERSION_CODES.P) - private void revokeCameraPermission() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return; - String packageName = InstrumentationRegistry.getTargetContext().getPackageName(); - InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission( - packageName, Manifest.permission.CAMERA); - } - - @TargetApi(Build.VERSION_CODES.P) - private void grantCameraPermission() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return; - String packageName = InstrumentationRegistry.getTargetContext().getPackageName(); - InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( - packageName, Manifest.permission.CAMERA); - } }
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java index bcb1865..4e375e47 100644 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
@@ -125,10 +125,10 @@ } /** - * Starts the WebLayer activity with the given extras Bundle and completely loads the given URL - * (this calls navigateAndWait()). + * Starts the WebLayer activity with the given extras Bundle. This does not create and load + * WebLayer. */ - public InstrumentationActivity launchShellWithUrl(String url, Bundle extras) { + public InstrumentationActivity launchShell(Bundle extras) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.putExtras(extras); intent.addCategory(Intent.CATEGORY_LAUNCHER); @@ -136,8 +136,18 @@ intent.setComponent( new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(), InstrumentationActivity.class)); - InstrumentationActivity activity = launchActivity(intent); + return launchActivity(intent); + } + + /** + * Starts the WebLayer activity with the given extras Bundle and completely loads the given URL + * (this calls navigateAndWait()). + */ + public InstrumentationActivity launchShellWithUrl(String url, Bundle extras) { + InstrumentationActivity activity = launchShell(extras); Assert.assertNotNull(activity); + TestThreadUtils.runOnUiThreadBlocking( + () -> { activity.createWebLayer(activity.getApplication(), null).get(); }); if (url != null) navigateAndWait(url); return activity; }
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/TopControlsTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/TopControlsTest.java index c5812d51..39ea7f9 100644 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/TopControlsTest.java +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/TopControlsTest.java
@@ -16,7 +16,6 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.UrlUtils; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -76,22 +75,12 @@ helper.waitForCallback(0); } - // TODO(https://crbug.com/1020065): fix this test, it's flaky. @Test @SmallTest - @DisabledTest public void testBasic() throws Exception { final String url = UrlUtils.encodeHtmlDataUri("<body><p style='height:5000px'>"); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url); - // Wait for layout to make sure the top contents container is shown. - CallbackHelper helper = new CallbackHelper(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - activity.getTopContentsContainer().getViewTreeObserver().addOnGlobalLayoutListener( - helper::notifyCalled); - }); - helper.waitForCallback(0); - TestThreadUtils.runOnUiThreadBlocking(() -> { mTopControlsHeight = activity.getTopContentsContainer().getHeight(); Assert.assertTrue(mTopControlsHeight > 0);
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java index a619a6f..ec51bcf 100644 --- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java +++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -4,6 +4,7 @@ package org.chromium.weblayer.shell; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -24,6 +25,7 @@ import org.chromium.weblayer.BrowserCallback; import org.chromium.weblayer.BrowserController; import org.chromium.weblayer.BrowserFragmentController; +import org.chromium.weblayer.ListenableFuture; import org.chromium.weblayer.Profile; import org.chromium.weblayer.UnsupportedVersionException; import org.chromium.weblayer.WebLayer; @@ -102,14 +104,20 @@ mTopContentsContainer.addView(mUrlView, new RelativeLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); - - try { - // This ensures asynchronous initialization of WebLayer on first start of activity. + if (savedInstanceState != null) { // If activity is re-created during process restart, FragmentManager attaches // BrowserFragment immediately, resulting in synchronous init. By the time this line // executes, the synchronous init has already happened. - WebLayer.create(getApplication()) - .addCallback(webLayer -> onWebLayerReady(savedInstanceState)); + createWebLayer(getApplication(), savedInstanceState); + } + } + + public ListenableFuture<WebLayer> createWebLayer( + Context appContext, Bundle savedInstanceState) { + try { + ListenableFuture<WebLayer> future = WebLayer.create(appContext); + future.addCallback(webLayer -> onWebLayerReady(savedInstanceState)); + return future; } catch (UnsupportedVersionException e) { throw new RuntimeException("Failed to initialize WebLayer", e); }