diff --git a/AUTHORS b/AUTHORS index d4ec525b..fd4fd13 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -669,6 +669,7 @@ Paul Sapunaru <paul.sapunaru@intel.com> Paul Wicks <pwicks86@gmail.com> Pavan Kumar Emani <pavan.e@samsung.com> +Pavel Golikov <paullo612@ya.ru> Pavel Ivanov <paivanof@gmail.com> Pawel Forysiuk <p.forysiuk@samsung.com> Paweł Hajdan jr <phajdan.jr@gmail.com>
diff --git a/DEPS b/DEPS index 85a87fb..9725d6e 100644 --- a/DEPS +++ b/DEPS
@@ -121,11 +121,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': '8f37ce5b9f2c139e4bad8e14ed6b884c1510dffd', + 'skia_revision': '191e64b6c6c2e791ff4d7dae0209a78eed0376f0', # 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': 'abd39667a5d0a9605b16b053afe18859af116045', + 'v8_revision': 'be1288c9cdfde38689bacccdf804a429d9e9f9c3', # 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. @@ -133,7 +133,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '04ea03e4e1e1575ee576dafe1793f15fa41e5cc4', + 'angle_revision': 'bbdeee914aeb1fa5f6a2ea65b31c879c8af10b30', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -197,7 +197,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. - 'feed_revision': 'e2809cef2bf967cf572527e0944307fd2a9277d0', + 'feed_revision': '84617ef81ded68396acf495e8392266950972223', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. @@ -229,7 +229,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. - 'spv_tools_revision': '64f2750e5dc553baa2922b780f15049023689ef9', + 'spv_tools_revision': '9f36c8bb721d4bd8e5ee311a2677b68829c9832a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1036,7 +1036,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '8a5b9a8ad6fa8d06ac3f63a091303eead859cfd0', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a6ba1795b7bcccd80ee68449bcec172c6cea7b6a', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1199,7 +1199,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a2b35635aaef3e9301d69f77f9a0a3fd99291b08', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'bde71044cd4a011486073ba68ad84e606d25aa2d', + Var('webrtc_git') + '/src.git' + '@' + 'bba675db3eb4eaedd110427b7cf8afdb7409e2e1', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1230,7 +1230,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@96eb27a4c496f74f67ea65f132efc081f878fd7b', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bbd8fc1f9fa45d234881fd681cd867de003c07ff', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_feature_list_creator.cc b/android_webview/browser/aw_feature_list_creator.cc index 6af0f30..cf71dbd9 100644 --- a/android_webview/browser/aw_feature_list_creator.cc +++ b/android_webview/browser/aw_feature_list_creator.cc
@@ -164,6 +164,11 @@ std::vector<std::string>(), /*low_entropy_provider=*/nullptr, std::make_unique<base::FeatureList>(), aw_field_trials_.get(), &ignored_safe_seed_manager); + + // Activate a study which exercises permanent-consistency, to test the launch + // of permanent-consistency support in WebView. + // TODO(crbug/917537): Remove this after m73. + base::FieldTrialList::FindFullName("AndroidWebViewConsistencyTest"); } void AwFeatureListCreator::CreateFeatureListAndFieldTrials() {
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 419fc7f..bb2df95 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwProxyController.java +++ b/android_webview/java/src/org/chromium/android_webview/AwProxyController.java
@@ -16,7 +16,7 @@ public class AwProxyController { public AwProxyController() {} - public void setProxyOverride( + public String setProxyOverride( String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) { int length = (proxyRules == null ? 0 : proxyRules.length); String[] urlSchemes = new String[length]; @@ -31,31 +31,29 @@ // proxy URLs proxyUrls[i] = proxyRules[i][1]; if (proxyUrls[i] == null) { - throw new NullPointerException("Proxy rule " + i + " has a null url"); + return "Proxy rule " + i + " has a null url"; } } length = (bypassRules == null ? 0 : bypassRules.length); for (int i = 0; i < length; i++) { if (bypassRules[i] == null) { - throw new NullPointerException("Bypass rule " + i + " is null"); + return "Bypass rule " + i + " is null"; } } if (executor == null) { - throw new NullPointerException("Executor must not be null"); + return "Executor must not be null"; } - String result = - nativeSetProxyOverride(urlSchemes, proxyUrls, bypassRules, listener, executor); - if (!result.isEmpty()) { - throw new IllegalArgumentException(result); - } + return nativeSetProxyOverride(urlSchemes, proxyUrls, bypassRules, listener, executor); } - public void clearProxyOverride(Runnable listener, Executor executor) { + public String clearProxyOverride(Runnable listener, Executor executor) { if (executor == null) { - throw new NullPointerException("Executor must not be null"); + return "Executor must not be null"; } + nativeClearProxyOverride(listener, executor); + return ""; } @CalledByNativeUnchecked @@ -67,4 +65,4 @@ private native String nativeSetProxyOverride(String[] urlSchemes, String[] proxyUrls, String[] bypassRules, Runnable listener, Executor executor); private native void nativeClearProxyOverride(Runnable listener, Executor executor); -} \ No newline at end of file +}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java index 3df5276..6a165062 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/HttpCacheTest.java
@@ -13,6 +13,7 @@ import org.junit.runner.RunWith; import org.chromium.android_webview.AwContents; +import org.chromium.base.FileUtils; import org.chromium.base.test.util.Feature; import org.chromium.net.test.util.TestWebServer; @@ -40,7 +41,7 @@ .getCacheDir() .getPath(), "org.chromium.android_webview"); - deleteDirectory(webViewCacheDir); + FileUtils.recursivelyDeleteFile(webViewCacheDir); mActivityTestRule.startBrowserProcess(); final TestAwContentsClient contentClient = new TestAwContentsClient(); @@ -66,12 +67,4 @@ Assert.assertTrue(webViewCacheDir.isDirectory()); Assert.assertTrue(webViewCacheDir.list().length > 0); } - - private void deleteDirectory(File dir) throws Exception { - if (!dir.exists()) return; - Assert.assertTrue(dir.isDirectory()); - Process rmrf = Runtime.getRuntime().exec("rm -rf " + dir.getAbsolutePath()); - rmrf.waitFor(); - Assert.assertFalse(dir.exists()); - } }
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 1c3b24b..ebe0f6fc 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
@@ -5,6 +5,8 @@ package org.chromium.support_lib_glue; import org.chromium.android_webview.AwProxyController; +import org.chromium.android_webview.WebViewChromiumRunQueue; +import org.chromium.base.ThreadUtils; import org.chromium.support_lib_boundary.ProxyControllerBoundaryInterface; import java.util.concurrent.Executor; @@ -13,20 +15,47 @@ * Adapter between AwProxyController and ProxyControllerBoundaryInterface. */ public class SupportLibProxyControllerAdapter implements ProxyControllerBoundaryInterface { + private final WebViewChromiumRunQueue mRunQueue; private final AwProxyController mProxyController; - public SupportLibProxyControllerAdapter(AwProxyController proxyController) { + public SupportLibProxyControllerAdapter( + WebViewChromiumRunQueue runQueue, AwProxyController proxyController) { + mRunQueue = runQueue; mProxyController = proxyController; } @Override public void setProxyOverride( String[][] proxyRules, String[] bypassRules, Runnable listener, Executor executor) { - mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor); + String result; + if (checkNeedsPost()) { + result = mRunQueue.runOnUiThreadBlocking(() -> { + return mProxyController.setProxyOverride( + proxyRules, bypassRules, listener, executor); + }); + } else { + result = mProxyController.setProxyOverride(proxyRules, bypassRules, listener, executor); + } + if (!result.isEmpty()) { + throw new IllegalArgumentException(result); + } } @Override public void clearProxyOverride(Runnable listener, Executor executor) { - mProxyController.clearProxyOverride(listener, executor); + String result; + if (checkNeedsPost()) { + result = mRunQueue.runOnUiThreadBlocking( + () -> { return mProxyController.clearProxyOverride(listener, executor); }); + } else { + result = mProxyController.clearProxyOverride(listener, executor); + } + if (!result.isEmpty()) { + throw new IllegalArgumentException(result); + } } -} \ No newline at end of file + + private static boolean checkNeedsPost() { + return !ThreadUtils.runningOnUiThread(); + } +}
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java index 7db638e0..afc132c 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -167,7 +167,8 @@ synchronized (mAwInit.getLock()) { if (mProxyController == null) { mProxyController = BoundaryInterfaceReflectionUtil.createInvocationHandlerFor( - new SupportLibProxyControllerAdapter(mAwInit.getAwProxyController())); + new SupportLibProxyControllerAdapter( + mAwInit.getRunQueue(), mAwInit.getAwProxyController())); } } return mProxyController;
diff --git a/ash/components/tap_visualizer/BUILD.gn b/ash/components/tap_visualizer/BUILD.gn index d9b25db..137d8de 100644 --- a/ash/components/tap_visualizer/BUILD.gn +++ b/ash/components/tap_visualizer/BUILD.gn
@@ -13,6 +13,7 @@ ] deps = [ + "//ash/components/tap_visualizer/public/mojom", "//ash/public/cpp", "//base", "//cc/paint",
diff --git a/ash/components/tap_visualizer/manifest.json b/ash/components/tap_visualizer/manifest.json index 68ed3f22..ccc2753c 100644 --- a/ash/components/tap_visualizer/manifest.json +++ b/ash/components/tap_visualizer/manifest.json
@@ -4,6 +4,9 @@ "sandbox_type": "none", "interface_provider_specs": { "service_manager:connector": { + "provides": { + "tap_visualizer": [ "tap_visualizer.mojom.TapVisualizer" ] + }, "requires": { "*": [ "app" ], "service_manager": [ "service_manager:service_manager" ]
diff --git a/ash/components/tap_visualizer/public/mojom/BUILD.gn b/ash/components/tap_visualizer/public/mojom/BUILD.gn index eaeb9d8..c734e71 100644 --- a/ash/components/tap_visualizer/public/mojom/BUILD.gn +++ b/ash/components/tap_visualizer/public/mojom/BUILD.gn
@@ -4,14 +4,8 @@ import("//mojo/public/tools/bindings/mojom.gni") -group("mojom") { - public_deps = [ - ":constants", - ] -} - -mojom("constants") { +mojom("mojom") { sources = [ - "constants.mojom", + "tap_visualizer.mojom", ] }
diff --git a/ash/components/tap_visualizer/public/mojom/constants.mojom b/ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom similarity index 80% rename from ash/components/tap_visualizer/public/mojom/constants.mojom rename to ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom index b7a33bd6..ecbc4c3 100644 --- a/ash/components/tap_visualizer/public/mojom/constants.mojom +++ b/ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom
@@ -5,3 +5,8 @@ module tap_visualizer.mojom; const string kServiceName = "tap_visualizer_app"; + +interface TapVisualizer { + // Show the UI. + Show(); +};
diff --git a/ash/components/tap_visualizer/tap_visualizer_app.cc b/ash/components/tap_visualizer/tap_visualizer_app.cc index 9b18560..ed6d888 100644 --- a/ash/components/tap_visualizer/tap_visualizer_app.cc +++ b/ash/components/tap_visualizer/tap_visualizer_app.cc
@@ -25,26 +25,16 @@ TapVisualizerApp::TapVisualizerApp( service_manager::mojom::ServiceRequest request) - : service_binding_(this, std::move(request)) {} + : service_binding_(this, std::move(request)) { + registry_.AddInterface<mojom::TapVisualizer>(base::BindRepeating( + &TapVisualizerApp::AddBinding, base::Unretained(this))); +} TapVisualizerApp::~TapVisualizerApp() { display::Screen::GetScreen()->RemoveObserver(this); aura::Env::GetInstance()->RemoveEventObserver(this); } -void TapVisualizerApp::Start() { - // Watches moves so the user can drag around a touch point. - aura::Env* env = aura::Env::GetInstance(); - std::set<ui::EventType> types = {ui::ET_TOUCH_PRESSED, ui::ET_TOUCH_RELEASED, - ui::ET_TOUCH_MOVED, ui::ET_TOUCH_CANCELLED}; - env->AddEventObserver(this, env, types); - display::Screen::GetScreen()->AddObserver(this); - for (const display::Display& display : - display::Screen::GetScreen()->GetAllDisplays()) { - CreateWidgetForDisplay(display.id()); - } -} - void TapVisualizerApp::OnStart() { views::AuraInit::InitParams params; params.connector = service_binding_.GetConnector(); @@ -55,7 +45,31 @@ Terminate(); return; } - Start(); +} + +void TapVisualizerApp::OnBindInterface( + const service_manager::BindSourceInfo& remote_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + registry_.BindInterface(interface_name, std::move(interface_pipe)); +} + +void TapVisualizerApp::Show() { + // Only show the first time. + if (is_showing_) + return; + is_showing_ = true; + + // Watches moves so the user can drag around a touch point. + aura::Env* env = aura::Env::GetInstance(); + std::set<ui::EventType> types = {ui::ET_TOUCH_PRESSED, ui::ET_TOUCH_RELEASED, + ui::ET_TOUCH_MOVED, ui::ET_TOUCH_CANCELLED}; + env->AddEventObserver(this, env, types); + display::Screen::GetScreen()->AddObserver(this); + for (const display::Display& display : + display::Screen::GetScreen()->GetAllDisplays()) { + CreateWidgetForDisplay(display.id()); + } } void TapVisualizerApp::OnEvent(const ui::Event& event) { @@ -106,4 +120,9 @@ std::make_unique<TapRenderer>(std::move(widget)); } +void TapVisualizerApp::AddBinding(mojom::TapVisualizerRequest request) { + tap_visualizer_binding_.Close(); + tap_visualizer_binding_.Bind(std::move(request)); +} + } // namespace tap_visualizer
diff --git a/ash/components/tap_visualizer/tap_visualizer_app.h b/ash/components/tap_visualizer/tap_visualizer_app.h index c8577c2..3763ae2 100644 --- a/ash/components/tap_visualizer/tap_visualizer_app.h +++ b/ash/components/tap_visualizer/tap_visualizer_app.h
@@ -10,7 +10,9 @@ #include <map> #include <memory> +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "base/macros.h" +#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service_binding.h" #include "services/service_manager/public/mojom/service.mojom.h" @@ -28,6 +30,7 @@ // Application that paints touch tap points as circles. Creates a fullscreen // transparent widget on each display to draw the taps. class TapVisualizerApp : public service_manager::Service, + public tap_visualizer::mojom::TapVisualizer, public ui::EventObserver, public display::DisplayObserver { public: @@ -38,11 +41,14 @@ private: friend class TapVisualizerAppTestApi; - // Starts showing touches on all displays. - void Start(); - // service_manager::Service: void OnStart() override; + void OnBindInterface(const service_manager::BindSourceInfo& remote_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + + // mojom::TapVisualizer: + void Show() override; // ui::EventObserver: void OnEvent(const ui::Event& event) override; @@ -54,12 +60,19 @@ // Creates the touch HUD widget for a display. void CreateWidgetForDisplay(int64_t display_id); + void AddBinding(mojom::TapVisualizerRequest request); + service_manager::ServiceBinding service_binding_; + service_manager::BinderRegistry registry_; + mojo::Binding<mojom::TapVisualizer> tap_visualizer_binding_{this}; // Must be released after |display_id_to_renderer_| which indirectly depends // on aura. std::unique_ptr<views::AuraInit> aura_init_; + // True after the first Show(). + bool is_showing_ = false; + // Maps display::Display::id() to the renderer for that display. std::map<int64_t, std::unique_ptr<TapRenderer>> display_id_to_renderer_;
diff --git a/ash/components/tap_visualizer/tap_visualizer_app_unittest.cc b/ash/components/tap_visualizer/tap_visualizer_app_unittest.cc index f8b43eb9..66c9331 100644 --- a/ash/components/tap_visualizer/tap_visualizer_app_unittest.cc +++ b/ash/components/tap_visualizer/tap_visualizer_app_unittest.cc
@@ -26,7 +26,7 @@ explicit TapVisualizerAppTestApi(TapVisualizerApp* app) : app_(app) {} ~TapVisualizerAppTestApi() = default; - void Start() { app_->Start(); } + void Show() { app_->Show(); } bool HasRendererForDisplay(int64_t display_id) { return base::ContainsKey(app_->display_id_to_renderer_, display_id); @@ -83,7 +83,7 @@ // Simulate the service starting. TapVisualizerApp app(nullptr); TapVisualizerAppTestApi test_api(&app); - test_api.Start(); + test_api.Show(); // A fullscreen widget is created. views::Widget* widget = test_api.GetWidgetForDisplay(kFirstDisplayId); @@ -113,7 +113,7 @@ // Simulate the service starting. TapVisualizerApp app(nullptr); TapVisualizerAppTestApi test_api(&app); - test_api.Start(); + test_api.Show(); // Two renderers are created. EXPECT_TRUE(test_api.HasRendererForDisplay(kFirstDisplayId));
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc index 7733074..f1a1bbd 100644 --- a/ash/login/login_screen_controller.cc +++ b/ash/login/login_screen_controller.cc
@@ -505,6 +505,13 @@ ->SetShowGuestButtonInOobe(show); } +void LoginScreenController::SetShowParentAccess(bool show) { + Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()) + ->shelf_widget() + ->login_shelf_view() + ->SetShowParentAccess(show); +} + void LoginScreenController::FocusLoginShelf(bool reverse) { Shelf* shelf = Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()); // Tell the focus direction to the status area or the shelf so they can focus
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h index 07af915..b78ca78 100644 --- a/ash/login/login_screen_controller.h +++ b/ash/login/login_screen_controller.h
@@ -157,6 +157,7 @@ void SetShutdownButtonEnabled(bool enable) override; void SetAllowLoginAsGuest(bool allow_guest) override; void SetShowGuestButtonInOobe(bool show) override; + void SetShowParentAccess(bool show) override; void FocusLoginShelf(bool reverse) override; // Flushes the mojo pipes - to be used in tests.
diff --git a/ash/login/login_screen_test_api.h b/ash/login/login_screen_test_api.h index 4b70664..ed24dee 100644 --- a/ash/login/login_screen_test_api.h +++ b/ash/login/login_screen_test_api.h
@@ -5,7 +5,7 @@ #ifndef ASH_LOGIN_LOGIN_SCREEN_TEST_API_H_ #define ASH_LOGIN_LOGIN_SCREEN_TEST_API_H_ -#include "ash/public/interfaces/login_screen_test_api.mojom.h" +#include "ash/public/interfaces/login_screen_test_api.test-mojom.h" #include "base/macros.h" #include "components/account_id/account_id.h"
diff --git a/ash/main.cc b/ash/main.cc index d9e398f..8aedc9f 100644 --- a/ash/main.cc +++ b/ash/main.cc
@@ -45,12 +45,17 @@ if (!enabled_features.empty()) enabled_features += ","; enabled_features += features::kMash.name; + // Disable SingleProcessMash, even if it's on by default in the test suite. + if (!disabled_features.empty()) + disabled_features += ","; + disabled_features += features::kSingleProcessMash.name; // This code path is really only for testing (production code uses the utility // process to launch AshService), so it's ok to use a for-testing function. base::FeatureList::ClearInstanceForTesting(); CHECK(base::FeatureList::InitializeInstance(enabled_features, disabled_features)); CHECK(base::FeatureList::IsEnabled(features::kMash)); + CHECK(!base::FeatureList::IsEnabled(features::kSingleProcessMash)); ui::MaterialDesignController::Initialize();
diff --git a/ash/media/media_notification_item.cc b/ash/media/media_notification_item.cc index ac44a05..f6b36c5 100644 --- a/ash/media/media_notification_item.cc +++ b/ash/media/media_notification_item.cc
@@ -69,6 +69,15 @@ view_->UpdateWithMediaMetadata(session_metadata_); } +void MediaNotificationItem::MediaSessionActionsChanged( + const std::vector<media_session::mojom::MediaSessionAction>& actions) { + session_actions_ = std::set<media_session::mojom::MediaSessionAction>( + actions.begin(), actions.end()); + + if (view_) + view_->UpdateWithMediaActions(session_actions_); +} + void MediaNotificationItem::SetView(MediaNotificationView* view) { DCHECK(view_ || view); @@ -78,6 +87,7 @@ DCHECK(!session_info_.is_null()); view_->UpdateWithMediaSessionInfo(session_info_); view_->UpdateWithMediaMetadata(session_metadata_); + view_->UpdateWithMediaActions(session_actions_); } }
diff --git a/ash/media/media_notification_item.h b/ash/media/media_notification_item.h index ba06190..6b5b2781 100644 --- a/ash/media/media_notification_item.h +++ b/ash/media/media_notification_item.h
@@ -5,6 +5,7 @@ #ifndef ASH_MEDIA_MEDIA_NOTIFICATION_ITEM_H_ #define ASH_MEDIA_MEDIA_NOTIFICATION_ITEM_H_ +#include <set> #include <string> #include "ash/ash_export.h" @@ -34,7 +35,7 @@ const base::Optional<media_session::MediaMetadata>& metadata) override; void MediaSessionActionsChanged( const std::vector<media_session::mojom::MediaSessionAction>& actions) - override {} + override; void SetView(MediaNotificationView* view); @@ -66,6 +67,8 @@ media_session::MediaMetadata session_metadata_; + std::set<media_session::mojom::MediaSessionAction> session_actions_; + mojo::Binding<media_session::mojom::MediaSessionObserver> observer_binding_{ this};
diff --git a/ash/media/media_notification_view.cc b/ash/media/media_notification_view.cc index 3f308a5..b4f4a29 100644 --- a/ash/media/media_notification_view.cc +++ b/ash/media/media_notification_view.cc
@@ -7,6 +7,7 @@ #include "ash/media/media_notification_constants.h" #include "ash/media/media_notification_controller.h" #include "ash/shell.h" +#include "base/stl_util.h" #include "components/vector_icons/vector_icons.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "ui/gfx/font.h" @@ -207,9 +208,12 @@ bool playing = session_info->playback_state == media_session::mojom::MediaPlaybackState::kPlaying; play_pause_button_->SetToggled(playing); - play_pause_button_->set_tag( - playing ? static_cast<int>(MediaSessionAction::kPause) - : static_cast<int>(MediaSessionAction::kPlay)); + + MediaSessionAction action = + playing ? MediaSessionAction::kPause : MediaSessionAction::kPlay; + play_pause_button_->set_tag(static_cast<int>(action)); + play_pause_button_->SetVisible(IsActionButtonVisible(action)); + PreferredSizeChanged(); } void MediaNotificationView::UpdateWithMediaMetadata( @@ -228,6 +232,13 @@ artist_label_->SetVisible(!metadata.artist.empty()); } +void MediaNotificationView::UpdateWithMediaActions( + const std::set<media_session::mojom::MediaSessionAction>& actions) { + enabled_actions_ = actions; + UpdateActionButtonsVisibility(); + PreferredSizeChanged(); +} + void MediaNotificationView::UpdateControlButtonsVisibilityWithNotification( const message_center::Notification& notification) { // Media notifications do not use the settings and snooze buttons. @@ -238,18 +249,31 @@ UpdateControlButtonsVisibility(); } -void MediaNotificationView::UpdateViewForExpandedState() { +bool MediaNotificationView::IsActionButtonVisible( + MediaSessionAction action) const { + // Not all media sessions support the same actions. + bool visible = base::ContainsKey(enabled_actions_, action); + // We should reduce the number of action buttons we show when we are // collapsed. + // TODO(beccahughes): Use priority based ranking here + if (!expanded_ && visible) + visible = ShouldShowActionWhenCollapsed(action); + + return visible; +} + +void MediaNotificationView::UpdateActionButtonsVisibility() { for (int i = 0; i < button_row_->child_count(); ++i) { views::Button* action_button = views::Button::AsButton(button_row_->child_at(i)); - action_button->SetVisible(expanded_ || ShouldShowActionWhenCollapsed( - static_cast<MediaSessionAction>( - action_button->tag()))); + action_button->SetVisible(IsActionButtonVisible( + static_cast<MediaSessionAction>(action_button->tag()))); } +} +void MediaNotificationView::UpdateViewForExpandedState() { // Adjust the layout of the |main_row_| based on the expanded state. If the // notification is expanded then the buttons should be below the title/artist // information. If it is collapsed then the buttons will be to the right. @@ -272,6 +296,8 @@ } header_row_->SetExpanded(expanded_); + + UpdateActionButtonsVisibility(); } void MediaNotificationView::CreateMediaButton(const gfx::VectorIcon& icon,
diff --git a/ash/media/media_notification_view.h b/ash/media/media_notification_view.h index 67e392a8..097d138 100644 --- a/ash/media/media_notification_view.h +++ b/ash/media/media_notification_view.h
@@ -58,6 +58,8 @@ void UpdateWithMediaSessionInfo( const media_session::mojom::MediaSessionInfoPtr& session_info); void UpdateWithMediaMetadata(const media_session::MediaMetadata& metadata); + void UpdateWithMediaActions( + const std::set<media_session::mojom::MediaSessionAction>& actions); private: friend class MediaNotificationViewTest; @@ -70,6 +72,10 @@ void CreateMediaButton(const gfx::VectorIcon& icon, media_session::mojom::MediaSessionAction action); + bool IsActionButtonVisible( + media_session::mojom::MediaSessionAction action) const; + + void UpdateActionButtonsVisibility(); void UpdateViewForExpandedState(); // View containing close and settings buttons. @@ -79,6 +85,9 @@ // Whether this notification is expanded or not. bool expanded_ = false; + // Set of enabled actions. + std::set<media_session::mojom::MediaSessionAction> enabled_actions_; + // Container views directly attached to this view. message_center::NotificationHeaderView* header_row_ = nullptr; views::View* button_row_ = nullptr;
diff --git a/ash/media/media_notification_view_unittest.cc b/ash/media/media_notification_view_unittest.cc index 298d38b..5b05946 100644 --- a/ash/media/media_notification_view_unittest.cc +++ b/ash/media/media_notification_view_unittest.cc
@@ -117,6 +117,8 @@ void TearDown() override { view_ = nullptr; + actions_.clear(); + message_center::MessageViewFactory:: ClearCustomNotificationViewFactoryForTest( kMediaSessionNotificationCustomViewType); @@ -147,6 +149,28 @@ EXPECT_EQ(metadata.artist, artist_label()->text()); } + void EnableAllActions() { + actions_.insert(MediaSessionAction::kPlay); + actions_.insert(MediaSessionAction::kPause); + actions_.insert(MediaSessionAction::kPreviousTrack); + actions_.insert(MediaSessionAction::kNextTrack); + actions_.insert(MediaSessionAction::kSeekBackward); + actions_.insert(MediaSessionAction::kSeekForward); + actions_.insert(MediaSessionAction::kStop); + + NotifyUpdatedActions(); + } + + void EnableAction(MediaSessionAction action) { + actions_.insert(action); + NotifyUpdatedActions(); + } + + void DisableAction(MediaSessionAction action) { + actions_.erase(action); + NotifyUpdatedActions(); + } + MediaNotificationView* view() const { return view_; } TestMediaController* media_controller() const { @@ -173,6 +197,10 @@ return nullptr; } + bool IsActionButtonVisible(MediaSessionAction action) const { + return GetButtonForAction(action)->visible(); + } + MediaNotificationItem* GetItem() const { return Shell::Get()->media_notification_controller()->GetItem( request_id_.ToString()); @@ -190,10 +218,17 @@ return view; } + void NotifyUpdatedActions() { + GetItem()->MediaSessionActionsChanged( + std::vector<MediaSessionAction>(actions_.begin(), actions_.end())); + } + base::UnguessableToken request_id_; base::test::ScopedFeatureList scoped_feature_list_; + std::set<MediaSessionAction> actions_; + std::unique_ptr<TestMediaController> media_controller_; std::unique_ptr<views::Widget> widget_; MediaNotificationView* view_ = nullptr; @@ -224,6 +259,8 @@ } TEST_F(MediaNotificationViewTest, ButtonsSanityCheck) { + EnableAllActions(); + EXPECT_TRUE(button_row()->visible()); EXPECT_GT(button_row()->width(), 0); EXPECT_GT(button_row()->height(), 0); @@ -251,6 +288,8 @@ } TEST_F(MediaNotificationViewTest, NextTrackButtonClick) { + EnableAction(MediaSessionAction::kNextTrack); + EXPECT_EQ(0, media_controller()->next_track_count()); gfx::Point cursor_location(1, 1); @@ -264,6 +303,8 @@ } TEST_F(MediaNotificationViewTest, PlayButtonClick) { + EnableAction(MediaSessionAction::kPlay); + EXPECT_EQ(0, media_controller()->resume_count()); gfx::Point cursor_location(1, 1); @@ -277,6 +318,8 @@ } TEST_F(MediaNotificationViewTest, PauseButtonClick) { + EnableAction(MediaSessionAction::kPause); + EXPECT_EQ(0, media_controller()->suspend_count()); media_session::mojom::MediaSessionInfoPtr session_info( @@ -297,6 +340,8 @@ } TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) { + EnableAction(MediaSessionAction::kPreviousTrack); + EXPECT_EQ(0, media_controller()->previous_track_count()); gfx::Point cursor_location(1, 1); @@ -310,6 +355,8 @@ } TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) { + EnableAction(MediaSessionAction::kSeekBackward); + EXPECT_EQ(0, media_controller()->seek_backward_count()); gfx::Point cursor_location(1, 1); @@ -323,6 +370,8 @@ } TEST_F(MediaNotificationViewTest, SeekForwardButtonClick) { + EnableAction(MediaSessionAction::kSeekForward); + EXPECT_EQ(0, media_controller()->seek_forward_count()); gfx::Point cursor_location(1, 1); @@ -384,34 +433,61 @@ } TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_Empty) { - views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( - GetButtonForAction(MediaSessionAction::kPlay)); - ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); - EXPECT_FALSE(button->toggled_for_testing()); + EnableAction(MediaSessionAction::kPlay); - GetItem()->MediaSessionInfoChanged( + { + views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( + GetButtonForAction(MediaSessionAction::kPlay)); + ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); + EXPECT_FALSE(button->toggled_for_testing()); + } + + view()->UpdateWithMediaSessionInfo( media_session::mojom::MediaSessionInfo::New()); - EXPECT_FALSE(button->toggled_for_testing()); + + { + views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( + GetButtonForAction(MediaSessionAction::kPlay)); + ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); + EXPECT_FALSE(button->toggled_for_testing()); + } } TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_PlaybackState) { - views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( - GetButtonForAction(MediaSessionAction::kPlay)); - ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); - EXPECT_FALSE(button->toggled_for_testing()); + EnableAction(MediaSessionAction::kPlay); + EnableAction(MediaSessionAction::kPause); + + { + views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( + GetButtonForAction(MediaSessionAction::kPlay)); + ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); + EXPECT_FALSE(button->toggled_for_testing()); + } media_session::mojom::MediaSessionInfoPtr session_info( media_session::mojom::MediaSessionInfo::New()); session_info->playback_state = media_session::mojom::MediaPlaybackState::kPlaying; - GetItem()->MediaSessionInfoChanged(session_info.Clone()); - EXPECT_TRUE(button->toggled_for_testing()); + view()->UpdateWithMediaSessionInfo(session_info.Clone()); + + { + views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( + GetButtonForAction(MediaSessionAction::kPause)); + ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); + EXPECT_TRUE(button->toggled_for_testing()); + } session_info->playback_state = media_session::mojom::MediaPlaybackState::kPaused; - GetItem()->MediaSessionInfoChanged(session_info.Clone()); - EXPECT_FALSE(button->toggled_for_testing()); + view()->UpdateWithMediaSessionInfo(session_info.Clone()); + + { + views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>( + GetButtonForAction(MediaSessionAction::kPlay)); + ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName()); + EXPECT_FALSE(button->toggled_for_testing()); + } } TEST_F(MediaNotificationViewTest, UpdateMetadata_FromObserver) { @@ -469,6 +545,8 @@ } TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) { + EnableAllActions(); + media_session::MediaMetadata metadata; metadata.artist = base::ASCIIToUTF16("artist"); @@ -478,16 +556,28 @@ EXPECT_FALSE(is_expanded()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)->visible()); - EXPECT_TRUE( - GetButtonForAction(MediaSessionAction::kPreviousTrack)->visible()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kNextTrack)->visible()); - EXPECT_FALSE( - GetButtonForAction(MediaSessionAction::kSeekBackward)->visible()); - EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kSeekForward)->visible()); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPlay)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); + + DisableAction(MediaSessionAction::kPreviousTrack); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); + + EnableAction(MediaSessionAction::kPreviousTrack); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); + + DisableAction(MediaSessionAction::kSeekForward); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); + + EnableAction(MediaSessionAction::kSeekForward); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); } TEST_F(MediaNotificationViewTest, Buttons_WhenExpanded) { + EnableAllActions(); + media_session::MediaMetadata metadata; metadata.artist = base::ASCIIToUTF16("artist"); @@ -497,12 +587,11 @@ EXPECT_TRUE(is_expanded()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)->visible()); - EXPECT_TRUE( - GetButtonForAction(MediaSessionAction::kPreviousTrack)->visible()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kNextTrack)->visible()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekBackward)->visible()); - EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekForward)->visible()); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPlay)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kSeekBackward)); + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); } TEST_F(MediaNotificationViewTest, ClickHeader_ToggleExpand) { @@ -527,4 +616,24 @@ EXPECT_TRUE(is_expanded()); } +TEST_F(MediaNotificationViewTest, ActionButtonsHiddenByDefault) { + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPlay)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward)); +} + +TEST_F(MediaNotificationViewTest, ActionButtonsToggleVisbility) { + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); + + EnableAction(MediaSessionAction::kNextTrack); + + EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); + + DisableAction(MediaSessionAction::kNextTrack); + + EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); +} + } // namespace ash
diff --git a/ash/metrics/time_to_first_present_recorder_test_api.h b/ash/metrics/time_to_first_present_recorder_test_api.h index 1d39c01..0b1240d8 100644 --- a/ash/metrics/time_to_first_present_recorder_test_api.h +++ b/ash/metrics/time_to_first_present_recorder_test_api.h
@@ -5,7 +5,7 @@ #ifndef ASH_METRICS_TIME_TO_FIRST_PRESENT_RECORDER_TEST_API_H_ #define ASH_METRICS_TIME_TO_FIRST_PRESENT_RECORDER_TEST_API_H_ -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.mojom.h" +#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" #include "base/macros.h" namespace ash {
diff --git a/ash/mojo_test_interface_factory.cc b/ash/mojo_test_interface_factory.cc index 1d8f737..026e60d35 100644 --- a/ash/mojo_test_interface_factory.cc +++ b/ash/mojo_test_interface_factory.cc
@@ -8,12 +8,12 @@ #include "ash/login/login_screen_test_api.h" #include "ash/metrics/time_to_first_present_recorder_test_api.h" -#include "ash/public/interfaces/login_screen_test_api.mojom.h" -#include "ash/public/interfaces/shelf_test_api.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" -#include "ash/public/interfaces/status_area_widget_test_api.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.mojom.h" +#include "ash/public/interfaces/login_screen_test_api.test-mojom.h" +#include "ash/public/interfaces/shelf_test_api.test-mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" +#include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" +#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" #include "ash/shelf/shelf_test_api.h" #include "ash/shell_test_api.h" #include "ash/system/status_area_widget_test_api.h"
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index f5984197..a4682ed 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -100,12 +100,12 @@ testonly = true disable_variants = true sources = [ - "login_screen_test_api.mojom", - "shelf_test_api.mojom", - "shell_test_api.mojom", - "status_area_widget_test_api.mojom", - "system_tray_test_api.mojom", - "time_to_first_present_recorder_test_api.mojom", + "login_screen_test_api.test-mojom", + "shelf_test_api.test-mojom", + "shell_test_api.test-mojom", + "status_area_widget_test_api.test-mojom", + "system_tray_test_api.test-mojom", + "time_to_first_present_recorder_test_api.test-mojom", ] deps = [ "//components/account_id/interfaces",
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom index ee8df7d..6e7f203 100644 --- a/ash/public/interfaces/login_screen.mojom +++ b/ash/public/interfaces/login_screen.mojom
@@ -218,6 +218,9 @@ // Sets if the guest button on the login shelf can be shown during OOBE. SetShowGuestButtonInOobe(bool show); + // Sets whether parent access button can be shown on the login shelf. + SetShowParentAccess(bool show); + // Transitions focus to the shelf area. If |reverse|, focuses the status area. FocusLoginShelf(bool reverse); };
diff --git a/ash/public/interfaces/login_screen_test_api.mojom b/ash/public/interfaces/login_screen_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/login_screen_test_api.mojom rename to ash/public/interfaces/login_screen_test_api.test-mojom
diff --git a/ash/public/interfaces/shelf_test_api.mojom b/ash/public/interfaces/shelf_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/shelf_test_api.mojom rename to ash/public/interfaces/shelf_test_api.test-mojom
diff --git a/ash/public/interfaces/shell_test_api.mojom b/ash/public/interfaces/shell_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/shell_test_api.mojom rename to ash/public/interfaces/shell_test_api.test-mojom
diff --git a/ash/public/interfaces/status_area_widget_test_api.mojom b/ash/public/interfaces/status_area_widget_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/status_area_widget_test_api.mojom rename to ash/public/interfaces/status_area_widget_test_api.test-mojom
diff --git a/ash/public/interfaces/system_tray_test_api.mojom b/ash/public/interfaces/system_tray_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/system_tray_test_api.mojom rename to ash/public/interfaces/system_tray_test_api.test-mojom
diff --git a/ash/public/interfaces/time_to_first_present_recorder_test_api.mojom b/ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom similarity index 100% rename from ash/public/interfaces/time_to_first_present_recorder_test_api.mojom rename to ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index d156267..205a5d4 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -99,6 +99,7 @@ "shelf_overflow.icon", "shelf_overflow_horizontal_dots.icon", "shelf_overview.icon", + "shelf_parent_access_button.icon", "shelf_position.icon", "shelf_shutdown_button.icon", "shelf_sign_out_button.icon",
diff --git a/ash/resources/vector_icons/shelf_parent_access_button.icon b/ash/resources/vector_icons/shelf_parent_access_button.icon new file mode 100644 index 0000000..f87fa00 --- /dev/null +++ b/ash/resources/vector_icons/shelf_parent_access_button.icon
@@ -0,0 +1,71 @@ +CANVAS_DIMENSIONS, 40, +MOVE_TO, 30, 13.33f, +R_H_LINE_TO, -1.67f, +V_LINE_TO, 10, +R_CUBIC_TO, 0, -4.6f, -3.73f, -8.33f, -8.33f, -8.33f, +ARC_TO, 8.34f, 8.34f, 0, 0, 0, 11.67f, 10, +R_V_LINE_TO, 3.33f, +H_LINE_TO, 10, +R_ARC_TO, 3.34f, 3.34f, 0, 0, 0, -3.33f, 3.33f, +R_V_LINE_TO, 16.67f, +R_CUBIC_TO, 0, 1.83f, 1.5f, 3.33f, 3.33f, 3.33f, +R_H_LINE_TO, 20, +R_CUBIC_TO, 1.83f, 0, 3.33f, -1.5f, 3.33f, -3.33f, +V_LINE_TO, 16.67f, +R_CUBIC_TO, 0, -1.83f, -1.5f, -3.33f, -3.33f, -3.33f, +CLOSE, +MOVE_TO, 15, 10, +R_CUBIC_TO, 0, -2.77f, 2.23f, -5, 5, -5, +R_CUBIC_TO, 2.77f, 0, 5, 2.23f, 5, 5, +R_V_LINE_TO, 3.33f, +H_LINE_TO, 15, +V_LINE_TO, 10, +CLOSE, +R_MOVE_TO, 15, 23.33f, +H_LINE_TO, 10, +V_LINE_TO, 16.67f, +R_H_LINE_TO, 20, +R_V_LINE_TO, 16.67f, +CLOSE, +R_MOVE_TO, -10, -5, +R_CUBIC_TO, 1.83f, 0, 3.33f, -1.5f, 3.33f, -3.33f, +R_CUBIC_TO, 0, -1.83f, -1.5f, -3.33f, -3.33f, -3.33f, +ARC_TO, 3.34f, 3.34f, 0, 0, 0, 16.67f, 25, +R_CUBIC_TO, 0, 1.83f, 1.5f, 3.33f, 3.33f, 3.33f, +CLOSE + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 15, 6.67f, +R_H_LINE_TO, -0.83f, +V_LINE_TO, 5, +CUBIC_TO, 14.17f, 2.7f, 12.3f, 0.83f, 10, 0.83f, +ARC_TO, 4.17f, 4.17f, 0, 0, 0, 5.83f, 5, +R_V_LINE_TO, 1.67f, +H_LINE_TO, 5, +R_CUBIC_TO, -0.92f, 0, -1.67f, 0.75f, -1.67f, 1.67f, +R_V_LINE_TO, 8.33f, +R_CUBIC_TO, 0, 0.92f, 0.75f, 1.67f, 1.67f, 1.67f, +R_H_LINE_TO, 10, +R_CUBIC_TO, 0.92f, 0, 1.67f, -0.75f, 1.67f, -1.67f, +V_LINE_TO, 8.33f, +R_CUBIC_TO, 0, -0.92f, -0.75f, -1.67f, -1.67f, -1.67f, +CLOSE, +MOVE_TO, 7.5f, 5, +R_CUBIC_TO, 0, -1.38f, 1.12f, -2.5f, 2.5f, -2.5f, +R_CUBIC_TO, 1.38f, 0, 2.5f, 1.12f, 2.5f, 2.5f, +R_V_LINE_TO, 1.67f, +R_H_LINE_TO, -5, +V_LINE_TO, 5, +CLOSE, +MOVE_TO, 15, 16.67f, +H_LINE_TO, 5, +V_LINE_TO, 8.33f, +R_H_LINE_TO, 10, +R_V_LINE_TO, 8.33f, +CLOSE, +R_MOVE_TO, -5, -2.5f, +R_CUBIC_TO, 0.92f, 0, 1.67f, -0.75f, 1.67f, -1.67f, +R_CUBIC_TO, 0, -0.92f, -0.75f, -1.67f, -1.67f, -1.67f, +R_CUBIC_TO, -0.92f, 0, -1.67f, 0.75f, -1.67f, 1.67f, +R_CUBIC_TO, 0, 0.92f, 0.75f, 1.67f, 1.67f, 1.67f, +CLOSE
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index eac4157..12e6575 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -386,6 +386,8 @@ add_button(kBrowseAsGuest, IDS_ASH_BROWSE_AS_GUEST_BUTTON, kShelfBrowseAsGuestButtonIcon); add_button(kAddUser, IDS_ASH_ADD_USER_BUTTON, kShelfAddPersonButtonIcon); + add_button(kParentAccess, IDS_ASH_PARENT_ACCESS_BUTTON, + kShelfParentAccessButtonIcon); // Adds observers for states that affect the visiblity of different buttons. tray_action_observer_.Add(Shell::Get()->tray_action()); @@ -506,6 +508,11 @@ UpdateUi(); } +void LoginShelfView::SetShowParentAccess(bool show) { + show_parent_access_ = show; + UpdateUi(); +} + void LoginShelfView::SetShowGuestButtonInOobe(bool show) { allow_guest_in_oobe_ = show; UpdateUi(); @@ -563,6 +570,7 @@ bool show_reboot = Shell::Get()->shutdown_controller()->reboot_on_shutdown(); mojom::TrayActionState tray_action_state = Shell::Get()->tray_action()->GetLockScreenNoteState(); + bool is_locked = (session_state == SessionState::LOCKED); bool is_lock_screen_note_in_foreground = (tray_action_state == mojom::TrayActionState::kActive || tray_action_state == mojom::TrayActionState::kLaunching) && @@ -573,13 +581,13 @@ !is_lock_screen_note_in_foreground); GetViewByID(kRestart)->SetVisible(show_reboot && !is_lock_screen_note_in_foreground); - GetViewByID(kSignOut)->SetVisible(session_state == SessionState::LOCKED && + GetViewByID(kSignOut)->SetVisible(is_locked && !is_lock_screen_note_in_foreground); GetViewByID(kCloseNote) - ->SetVisible(session_state == SessionState::LOCKED && - is_lock_screen_note_in_foreground); + ->SetVisible(is_locked && is_lock_screen_note_in_foreground); GetViewByID(kCancel)->SetVisible(session_state == SessionState::LOGIN_SECONDARY); + GetViewByID(kParentAccess)->SetVisible(is_locked && show_parent_access_); bool is_login_primary = (session_state == SessionState::LOGIN_PRIMARY); bool dialog_visible = dialog_state_ != mojom::OobeDialogState::HIDDEN;
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h index 1dd6e459..95e6cc32 100644 --- a/ash/shelf/login_shelf_view.h +++ b/ash/shelf/login_shelf_view.h
@@ -50,14 +50,15 @@ public LoginDataDispatcher::Observer { public: enum ButtonId { - kShutdown = 1, // Shut down the device. - kRestart, // Restart the device. - kSignOut, // Sign out the active user session. - kCloseNote, // Close the lock screen note. - kCancel, // Cancel multiple user sign-in. - kBrowseAsGuest, // Use in guest mode. - kAddUser, // Add a new user. - kApps, // Show list of available kiosk apps. + kShutdown = 1, // Shut down the device. + kRestart, // Restart the device. + kSignOut, // Sign out the active user session. + kCloseNote, // Close the lock screen note. + kCancel, // Cancel multiple user sign-in. + kBrowseAsGuest, // Use in guest mode. + kAddUser, // Add a new user. + kApps, // Show list of available kiosk apps. + kParentAccess // Unlock child device with Parent Access Code. }; explicit LoginShelfView( @@ -78,6 +79,9 @@ // true the button may still not be visible. void SetAllowLoginAsGuest(bool allow_guest); + // Sets whether parent access button can be shown on the login shelf. + void SetShowParentAccess(bool show); + // Sets if the guest button on the login shelf can be shown during gaia // signin screen. void SetShowGuestButtonInOobe(bool show); @@ -125,7 +129,7 @@ mojom::OobeDialogState dialog_state_ = mojom::OobeDialogState::HIDDEN; bool allow_guest_ = true; bool allow_guest_in_oobe_ = false; - + bool show_parent_access_ = false; // When the Gaia screen is active during Login, the guest-login button should // appear if there are no user views. bool login_screen_has_users_ = false;
diff --git a/ash/shelf/login_shelf_view_unittest.cc b/ash/shelf/login_shelf_view_unittest.cc index 71b269b..6b7ad1f 100644 --- a/ash/shelf/login_shelf_view_unittest.cc +++ b/ash/shelf/login_shelf_view_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/focus_cycler.h" #include "ash/lock_screen_action/lock_screen_action_background_controller.h" #include "ash/lock_screen_action/test_lock_screen_action_background_controller.h" +#include "ash/login/login_screen_controller.h" #include "ash/login/mock_login_screen_client.h" #include "ash/login/ui/login_test_base.h" #include "ash/login/ui/views_utils.h" @@ -519,5 +520,48 @@ EXPECT_TRUE(IsButtonEnabled(LoginShelfView::kShutdown)); } +TEST_F(LoginShelfViewTest, ParentAccessButtonVisibility) { + // Parent access button should only be visible on lock screen. + Shell::Get()->login_screen_controller()->SetShowParentAccess(true); + + NotifySessionStateChanged(SessionState::LOGIN_PRIMARY); + EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown, + LoginShelfView::kBrowseAsGuest, + LoginShelfView::kAddUser})); + + NotifySessionStateChanged(SessionState::LOGGED_IN_NOT_ACTIVE); + EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown})); + + NotifySessionStateChanged(SessionState::ACTIVE); + EXPECT_TRUE(ShowsShelfButtons({})); + + NotifySessionStateChanged(SessionState::LOGIN_SECONDARY); + EXPECT_TRUE( + ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kCancel})); + + NotifySessionStateChanged(SessionState::ACTIVE); + EXPECT_TRUE(ShowsShelfButtons({})); + + NotifySessionStateChanged(SessionState::LOCKED); + EXPECT_TRUE( + ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kSignOut, + LoginShelfView::kParentAccess})); +} + +TEST_F(LoginShelfViewTest, ParentAccessButtonVisibilityChangeOnLockScreen) { + NotifySessionStateChanged(SessionState::LOCKED); + EXPECT_TRUE( + ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kSignOut})); + + Shell::Get()->login_screen_controller()->SetShowParentAccess(true); + EXPECT_TRUE( + ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kSignOut, + LoginShelfView::kParentAccess})); + + Shell::Get()->login_screen_controller()->SetShowParentAccess(false); + EXPECT_TRUE( + ShowsShelfButtons({LoginShelfView::kShutdown, LoginShelfView::kSignOut})); +} + } // namespace } // namespace ash
diff --git a/ash/shelf/shelf_test_api.h b/ash/shelf/shelf_test_api.h index 6f01ef4..7c5d702e 100644 --- a/ash/shelf/shelf_test_api.h +++ b/ash/shelf/shelf_test_api.h
@@ -5,7 +5,7 @@ #ifndef ASH_SHELF_SHELF_TEST_API_H_ #define ASH_SHELF_SHELF_TEST_API_H_ -#include "ash/public/interfaces/shelf_test_api.mojom.h" +#include "ash/public/interfaces/shelf_test_api.test-mojom.h" #include "base/macros.h" namespace ash {
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index aee4d3a..8d86563 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -483,16 +483,26 @@ return nullptr; } -bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const { - gfx::Rect tooltip_bounds; - for (int i = 0; i < child_count(); ++i) { - const views::View* child = child_at(i); +void ShelfView::UpdateVisibleShelfItemBoundsUnion() { + visible_shelf_item_bounds_union_.SetRect(0, 0, 0, 0); + for (int i = first_visible_index_; i <= last_visible_index_; ++i) { + const views::View* child = view_model_->view_at(i); if (!IsTabletModeEnabled() && child == GetBackButton()) continue; - if (child != overflow_button_ && ShouldShowTooltipForView(child)) - tooltip_bounds.Union(child->GetMirroredBounds()); + if (ShouldShowTooltipForView(child)) + visible_shelf_item_bounds_union_.Union(child->GetMirroredBounds()); } - return !tooltip_bounds.Contains(cursor_location); +} + +bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) const { + // Hide the tooltip if this is the app list button and the list is showing. + const AppListButton* app_list_button = GetAppListButton(); + if (app_list_button && + app_list_button->GetMirroredBounds().Contains(cursor_location) && + app_list_button->is_showing_app_list()) { + return true; + } + return !visible_shelf_item_bounds_union_.Contains(cursor_location); } bool ShelfView::ShouldShowTooltipForView(const views::View* view) const { @@ -928,6 +938,7 @@ overflow_button_->SetBoundsRect(overflow_bounds); UpdateBackButton(); LayoutAppListAndBackButtonHighlight(); + UpdateVisibleShelfItemBoundsUnion(); } bool ShelfView::IsItemPinned(const ShelfItem& item) const { @@ -1187,6 +1198,7 @@ } overflow_button_->SetBoundsRect(overflow_bounds); LayoutAppListAndBackButtonHighlight(); + UpdateVisibleShelfItemBoundsUnion(); } views::View* ShelfView::CreateViewForItem(const ShelfItem& item) {
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 87eb8f0..355df80 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -151,6 +151,11 @@ AppListButton* GetAppListButton() const; BackButton* GetBackButton() const; + // Updates the union of all the shelf item bounds shown by this shelf view. + // This is used to determine the common area where the mouse can hover + // for showing tooltips without stuttering over gaps. + void UpdateVisibleShelfItemBoundsUnion(); + // Returns true if the mouse cursor exits the area for launcher tooltip. // There are thin gaps between launcher buttons but the tooltip shouldn't hide // in the gaps, but the tooltip should hide if the mouse moved totally outside @@ -597,6 +602,10 @@ // items. views::Separator* separator_ = nullptr; + // The union of all visible shelf item bounds. Used for showing tooltips in + // a continuous manner. + gfx::Rect visible_shelf_item_bounds_union_; + // A view to draw a background behind the app list and back buttons. // Owned by the view hierarchy. views::View* back_and_app_list_background_ = nullptr;
diff --git a/ash/shell.cc b/ash/shell.cc index 81f97594..4be8d81a 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -22,7 +22,7 @@ #include "ash/assistant/assistant_controller.h" #include "ash/autoclick/autoclick_controller.h" #include "ash/cast_config_controller.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/contained_shell/contained_shell_controller.h" #include "ash/dbus/ash_dbus_services.h" #include "ash/detachable_base/detachable_base_handler.h" @@ -1262,9 +1262,11 @@ base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kShowTaps)) { // The show taps feature is a separate service. // TODO(jamescook): Make this work in ash_shell_with_content. - // TODO(https://crbug.com/904148): This should not use |WarmService()|. - connector_->WarmService(service_manager::ServiceFilter::ByName( - tap_visualizer::mojom::kServiceName)); + tap_visualizer::mojom::TapVisualizerPtr tap_visualizer_ptr; + connector_->BindInterface(service_manager::ServiceFilter::ByName( + tap_visualizer::mojom::kServiceName), + mojo::MakeRequest(&tap_visualizer_ptr)); + tap_visualizer_ptr->Show(); } if (!::features::IsMultiProcessMash()) {
diff --git a/ash/shell/ash_content_browser_manifest_overlay.json b/ash/shell/ash_content_browser_manifest_overlay.json index 52d105d..9f0f4d0 100644 --- a/ash/shell/ash_content_browser_manifest_overlay.json +++ b/ash/shell/ash_content_browser_manifest_overlay.json
@@ -4,8 +4,9 @@ "interface_provider_specs": { "service_manager:connector": { "requires": { + "device": [ "device:fingerprint" ], "shortcut_viewer_app": [ "shortcut_viewer" ], - "device": [ "device:fingerprint" ] + "tap_visualizer_app": [ "tap_visualizer" ] } } }
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc index 246ac97b..da86a59e 100644 --- a/ash/shell/content/client/shell_browser_main_parts.cc +++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -9,7 +9,7 @@ #include "ash/components/quick_launch/public/mojom/constants.mojom.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/keyboard/test_keyboard_ui.h" #include "ash/login_status.h" #include "ash/shell.h"
diff --git a/ash/shell/content/client/shell_content_browser_client.cc b/ash/shell/content/client/shell_content_browser_client.cc index 1e393c3a..d37d07b 100644 --- a/ash/shell/content/client/shell_content_browser_client.cc +++ b/ash/shell/content/client/shell_content_browser_client.cc
@@ -9,7 +9,7 @@ #include "ash/ash_service.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/shell.h"
diff --git a/ash/shell/content/client/shell_main_delegate.cc b/ash/shell/content/client/shell_main_delegate.cc index 0328236..87d7874 100644 --- a/ash/shell/content/client/shell_main_delegate.cc +++ b/ash/shell/content/client/shell_main_delegate.cc
@@ -8,7 +8,7 @@ #include "ash/components/quick_launch/quick_launch_application.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" #include "ash/components/shortcut_viewer/shortcut_viewer_application.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/components/tap_visualizer/tap_visualizer_app.h" #include "ash/shell/content/client/shell_content_browser_client.h" #include "base/command_line.h"
diff --git a/ash/shell_test_api.h b/ash/shell_test_api.h index 0b4117c..1dcfb91b 100644 --- a/ash/shell_test_api.h +++ b/ash/shell_test_api.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/macros.h" #include "services/ws/common/types.h"
diff --git a/ash/system/network/network_icon_unittest.cc b/ash/system/network/network_icon_unittest.cc index 060200f..36aba2a 100644 --- a/ash/system/network/network_icon_unittest.cc +++ b/ash/system/network/network_icon_unittest.cc
@@ -26,6 +26,14 @@ namespace network_icon { +namespace { + +const char kShillManagerClientStubWifiDevice[] = "/device/stub_wifi_device1"; +const char kShillManagerClientStubCellularDevice[] = + "/device/stub_cellular_device1"; + +} // namespace + class NetworkIconTest : public chromeos::NetworkStateTest { public: NetworkIconTest() = default; @@ -33,43 +41,72 @@ void SetUp() override { chromeos::DBusThreadManager::Initialize(); - chromeos::NetworkStateTest::SetUp(); + NetworkStateTest::SetUp(); + SetUpDefaultNetworkState(); chromeos::NetworkHandler::Initialize(); - handler_ = chromeos::NetworkHandler::Get()->network_state_handler(); - - tether_network_ = - std::make_unique<chromeos::NetworkState>("tetherNetworkPath"); - tether_network_->set_type(chromeos::kTypeTether); - - wifi_network_ = std::make_unique<chromeos::NetworkState>("wifiServicePath"); - wifi_network_->set_type(shill::kTypeWifi); - - cellular_network_ = - std::make_unique<chromeos::NetworkState>("cellularServicePath"); - cellular_network_->set_type(shill::kTypeCellular); - - wifi_tether_network_ = - std::make_unique<chromeos::NetworkState>("wifiTetherServicePath"); - wifi_tether_network_->set_type(shill::kTypeWifi); - wifi_tether_network_.get()->set_tether_guid("tetherNetworkGuid"); - - ethernet_network_ = - std::make_unique<chromeos::NetworkState>("ethernetNetworkPath"); - ethernet_network_->set_type(shill::kTypeEthernet); + base::RunLoop().RunUntilIdle(); } void TearDown() override { PurgeNetworkIconCache(); - chromeos::NetworkHandler::Shutdown(); ShutdownNetworkState(); chromeos::NetworkStateTest::TearDown(); + chromeos::DBusThreadManager::Shutdown(); } - gfx::Image ImageForNetwork(chromeos::NetworkState* network) { + void SetUpDefaultNetworkState() { + base::RunLoop().RunUntilIdle(); // Process any pending updates + device_test_ = chromeos::DBusThreadManager::Get() + ->GetShillDeviceClient() + ->GetTestInterface(); + ASSERT_TRUE(device_test_); + device_test_->ClearDevices(); + device_test_->AddDevice(kShillManagerClientStubWifiDevice, shill::kTypeWifi, + "stub_wifi_device1"); + device_test_->AddDevice(kShillManagerClientStubCellularDevice, + shill::kTypeCellular, "stub_cellular_device1"); + + ClearDefaultServices(); + + wifi1_path_ = ConfigureService( + R"({"GUID": "wifi1_guid", "Type": "wifi", "State": "idle"})"); + wifi2_path_ = ConfigureService( + R"({"GUID": "wifi2_guid", "Type": "wifi", "State": "idle"})"); + cellular_path_ = ConfigureService( + R"({"GUID": "cellular_guid", "Type": "cellular", "Technology": "LTE", + "State": "idle"})"); + } + + std::unique_ptr<chromeos::NetworkState> CreateStandaloneNetworkState( + const std::string& id, + const std::string& type, + const std::string& connection_state, + int signal_strength) { + auto network = std::make_unique<chromeos::NetworkState>(id); + network->set_type(type); + network->set_visible(true); + network->set_connection_state(connection_state); + network->set_signal_strength(signal_strength); + return network; + } + + std::unique_ptr<chromeos::NetworkState> + CreateStandaloneWifiTetherNetworkState(const std::string& id, + const std::string& tether_guid, + const std::string& connection_state, + int signal_strength) { + std::unique_ptr<chromeos::NetworkState> network = + CreateStandaloneNetworkState(id, shill::kTypeWifi, connection_state, + signal_strength); + network->set_tether_guid(tether_guid); + return network; + } + + gfx::Image ImageForNetwork(const chromeos::NetworkState* network) { gfx::ImageSkia image_skia = GetImageForNetwork(network, icon_type_); return gfx::Image(image_skia); } @@ -79,11 +116,23 @@ // Wi-Fi network. The icon for a cellular network should be different from one // for a Wi-Fi network. The icon for a Tether network should be the same as // one for a Wi-Fi network with an associated Tether guid. - void GetAndCompareImagesByNetworkType() { - gfx::Image tether_image = ImageForNetwork(tether_network_.get()); - gfx::Image wifi_image = ImageForNetwork(wifi_network_.get()); - gfx::Image cellular_image = ImageForNetwork(cellular_network_.get()); - gfx::Image wifi_tether_image = ImageForNetwork(wifi_tether_network_.get()); + void GetAndCompareImagesByNetworkType( + const chromeos::NetworkState* wifi_network, + const chromeos::NetworkState* cellular_network, + const chromeos::NetworkState* tether_network, + const chromeos::NetworkState* wifi_tether_network) { + ASSERT_EQ(wifi_network->type(), shill::kTypeWifi); + gfx::Image wifi_image = ImageForNetwork(wifi_network); + + ASSERT_EQ(cellular_network->type(), shill::kTypeCellular); + gfx::Image cellular_image = ImageForNetwork(cellular_network); + + ASSERT_EQ(tether_network->type(), chromeos::kTypeTether); + gfx::Image tether_image = ImageForNetwork(tether_network); + + ASSERT_EQ(wifi_tether_network->type(), shill::kTypeWifi); + ASSERT_FALSE(wifi_tether_network->tether_guid().empty()); + gfx::Image wifi_tether_image = ImageForNetwork(wifi_tether_network); EXPECT_FALSE(gfx::test::AreImagesEqual(tether_image, wifi_image)); EXPECT_FALSE(gfx::test::AreImagesEqual(cellular_image, wifi_image)); @@ -99,7 +148,8 @@ ASSERT_EQ( chromeos::NetworkStateHandler::TechnologyState::TECHNOLOGY_UNAVAILABLE, - handler_->GetTechnologyState(chromeos::NetworkTypePattern::Cellular())); + network_state_handler()->GetTechnologyState( + chromeos::NetworkTypePattern::Cellular())); } void SetCellularUninitialized() { @@ -110,27 +160,28 @@ base::RunLoop().RunUntilIdle(); - ASSERT_EQ( - chromeos::NetworkStateHandler::TechnologyState:: - TECHNOLOGY_UNINITIALIZED, - handler_->GetTechnologyState(chromeos::NetworkTypePattern::Cellular())); + ASSERT_EQ(chromeos::NetworkStateHandler::TechnologyState:: + TECHNOLOGY_UNINITIALIZED, + network_state_handler()->GetTechnologyState( + chromeos::NetworkTypePattern::Cellular())); } - const base::MessageLoop message_loop_; + const std::string& wifi1_path() const { return wifi1_path_; } + const std::string& wifi2_path() const { return wifi2_path_; } + const std::string& cellular_path() const { return cellular_path_; } IconType icon_type_ = ICON_TYPE_TRAY_REGULAR; - chromeos::NetworkStateHandler* handler_; - - std::unique_ptr<chromeos::NetworkState> tether_network_; - std::unique_ptr<chromeos::NetworkState> wifi_network_; - std::unique_ptr<chromeos::NetworkState> cellular_network_; - // A network whose type is shill::kTypeWifi, but which is associated with - // a Tether network via its Tether network ID. - std::unique_ptr<chromeos::NetworkState> wifi_tether_network_; - std::unique_ptr<chromeos::NetworkState> ethernet_network_; + chromeos::ShillDeviceClient::TestInterface* device_test_; private: + const base::MessageLoop message_loop_; + + // Preconfigured service paths: + std::string wifi1_path_; + std::string wifi2_path_; + std::string cellular_path_; + DISALLOW_COPY_AND_ASSIGN(NetworkIconTest); }; @@ -141,39 +192,76 @@ // verifies that the Tether network and Wi-Fi network with associated Tether // guid are treated the same for purposes of icon display TEST_F(NetworkIconTest, CompareImagesByNetworkType_NotVisible) { - GetAndCompareImagesByNetworkType(); + std::unique_ptr<chromeos::NetworkState> wifi_network = + CreateStandaloneNetworkState("wifi", shill::kTypeWifi, shill::kStateIdle, + 50); + + std::unique_ptr<chromeos::NetworkState> cellular_network = + CreateStandaloneNetworkState("cellular", shill::kTypeCellular, + shill::kStateIdle, 50); + + std::unique_ptr<chromeos::NetworkState> wimax_network = + CreateStandaloneNetworkState("wimax", shill::kTypeWimax, + shill::kStateIdle, 50); + + EXPECT_TRUE(gfx::test::AreImagesEqual(ImageForNetwork(cellular_network.get()), + ImageForNetwork(wimax_network.get()))); + + std::unique_ptr<chromeos::NetworkState> tether_network = + CreateStandaloneNetworkState("tether", chromeos::kTypeTether, + shill::kStateIdle, 50); + + std::unique_ptr<chromeos::NetworkState> wifi_tether_network = + CreateStandaloneWifiTetherNetworkState("wifi_tether", "tether", + shill::kStateIdle, 50); + + GetAndCompareImagesByNetworkType(wifi_network.get(), cellular_network.get(), + tether_network.get(), + wifi_tether_network.get()); } TEST_F(NetworkIconTest, CompareImagesByNetworkType_Connecting) { - tether_network_->set_visible(true); - tether_network_->set_connection_state(shill::kStateAssociation); + std::unique_ptr<chromeos::NetworkState> wifi_network = + CreateStandaloneNetworkState("wifi", shill::kTypeWifi, + shill::kStateAssociation, 50); - wifi_network_->set_visible(true); - wifi_network_->set_connection_state(shill::kStateAssociation); + std::unique_ptr<chromeos::NetworkState> cellular_network = + CreateStandaloneNetworkState("cellular", shill::kTypeCellular, + shill::kStateAssociation, 50); - cellular_network_->set_visible(true); - cellular_network_->set_connection_state(shill::kStateAssociation); + std::unique_ptr<chromeos::NetworkState> tether_network = + CreateStandaloneNetworkState("tether", chromeos::kTypeTether, + shill::kStateAssociation, 50); - wifi_tether_network_->set_visible(true); - wifi_tether_network_->set_connection_state(shill::kStateAssociation); + std::unique_ptr<chromeos::NetworkState> wifi_tether_network = + CreateStandaloneWifiTetherNetworkState("wifi_tether", "tether", + shill::kStateAssociation, 50); - GetAndCompareImagesByNetworkType(); + GetAndCompareImagesByNetworkType(wifi_network.get(), cellular_network.get(), + tether_network.get(), + wifi_tether_network.get()); } TEST_F(NetworkIconTest, CompareImagesByNetworkType_Connected) { - tether_network_->set_visible(true); - tether_network_->set_connection_state(shill::kStateOnline); + std::unique_ptr<chromeos::NetworkState> wifi_network = + CreateStandaloneNetworkState("wifi", shill::kTypeWifi, + shill::kStateOnline, 50); - wifi_network_->set_visible(true); - wifi_network_->set_connection_state(shill::kStateOnline); + std::unique_ptr<chromeos::NetworkState> cellular_network = + CreateStandaloneNetworkState("cellular", shill::kTypeCellular, + shill::kStateOnline, 50); - cellular_network_->set_visible(true); - cellular_network_->set_connection_state(shill::kStateOnline); + std::unique_ptr<chromeos::NetworkState> tether_network = + CreateStandaloneNetworkState("tether", chromeos::kTypeTether, + shill::kStateOnline, 50); - wifi_tether_network_->set_visible(true); - wifi_tether_network_->set_connection_state(shill::kStateOnline); + std::unique_ptr<chromeos::NetworkState> wifi_tether_network = + CreateStandaloneWifiTetherNetworkState("wifi_tether", "tether", + shill::kStateOnline, 50); - GetAndCompareImagesByNetworkType(); + GetAndCompareImagesByNetworkType(wifi_network.get(), cellular_network.get(), + tether_network.get(), + wifi_tether_network.get()); } TEST_F(NetworkIconTest, @@ -193,16 +281,12 @@ test_manager_client()->AddTechnology(shill::kTypeCellular, true); - chromeos::DBusThreadManager* dbus_manager = - chromeos::DBusThreadManager::Get(); - chromeos::ShillDeviceClient::TestInterface* device_test = - dbus_manager->GetShillDeviceClient()->GetTestInterface(); - - device_test->SetDeviceProperty("/device/cellular1", shill::kScanningProperty, - base::Value(true), /*notify_changed=*/true); + device_test_->SetDeviceProperty(kShillManagerClientStubCellularDevice, + shill::kScanningProperty, base::Value(true), + /*notify_changed=*/true); base::RunLoop().RunUntilIdle(); - ASSERT_TRUE( - handler_->GetScanningByType(chromeos::NetworkTypePattern::Cellular())); + ASSERT_TRUE(network_state_handler()->GetScanningByType( + chromeos::NetworkTypePattern::Cellular())); EXPECT_EQ(IDS_ASH_STATUS_TRAY_MOBILE_SCANNING, GetCellularUninitializedMsg()); } @@ -210,30 +294,420 @@ TEST_F(NetworkIconTest, NetworkSignalStrength) { using ss = SignalStrength; + std::unique_ptr<chromeos::NetworkState> ethernet_network = + CreateStandaloneNetworkState("eth", shill::kTypeEthernet, + shill::kStateOnline, 50); + + std::unique_ptr<chromeos::NetworkState> wifi_network = + CreateStandaloneNetworkState("wifi", shill::kTypeWifi, + shill::kStateOnline, 50); + // Verify non-wirless network types return SignalStrength::NOT_WIRELESS, and // wireless network types return something other than // SignalStrength::NOT_WIRELESS. EXPECT_EQ(ss::NOT_WIRELESS, - GetSignalStrengthForNetwork(ethernet_network_.get())); - EXPECT_NE(ss::NOT_WIRELESS, GetSignalStrengthForNetwork(wifi_network_.get())); + GetSignalStrengthForNetwork(ethernet_network.get())); + EXPECT_NE(ss::NOT_WIRELESS, GetSignalStrengthForNetwork(wifi_network.get())); // Signal strength is divided into four categories: none, weak, medium and // strong. They are meant to match the number of sections in the wifi icon. // The wifi icon currently has four levels; signals [0, 100] are mapped to [1, // 4]. There are only three signal strengths so icons that were mapped to 2 // are also considered weak. - wifi_network_->set_signal_strength(0); - EXPECT_EQ(ss::NONE, GetSignalStrengthForNetwork(wifi_network_.get())); - wifi_network_->set_signal_strength(50); - EXPECT_EQ(ss::WEAK, GetSignalStrengthForNetwork(wifi_network_.get())); - wifi_network_->set_signal_strength(51); - EXPECT_EQ(ss::MEDIUM, GetSignalStrengthForNetwork(wifi_network_.get())); - wifi_network_->set_signal_strength(75); - EXPECT_EQ(ss::MEDIUM, GetSignalStrengthForNetwork(wifi_network_.get())); - wifi_network_->set_signal_strength(76); - EXPECT_EQ(ss::STRONG, GetSignalStrengthForNetwork(wifi_network_.get())); - wifi_network_->set_signal_strength(100); - EXPECT_EQ(ss::STRONG, GetSignalStrengthForNetwork(wifi_network_.get())); + wifi_network->set_signal_strength(0); + EXPECT_EQ(ss::NONE, GetSignalStrengthForNetwork(wifi_network.get())); + wifi_network->set_signal_strength(50); + EXPECT_EQ(ss::WEAK, GetSignalStrengthForNetwork(wifi_network.get())); + wifi_network->set_signal_strength(51); + EXPECT_EQ(ss::MEDIUM, GetSignalStrengthForNetwork(wifi_network.get())); + wifi_network->set_signal_strength(75); + EXPECT_EQ(ss::MEDIUM, GetSignalStrengthForNetwork(wifi_network.get())); + wifi_network->set_signal_strength(76); + EXPECT_EQ(ss::STRONG, GetSignalStrengthForNetwork(wifi_network.get())); + wifi_network->set_signal_strength(100); + EXPECT_EQ(ss::STRONG, GetSignalStrengthForNetwork(wifi_network.get())); +} + +TEST_F(NetworkIconTest, DefaultImageAndLabelWifiConnected) { + // Set the Wifi service as connected. + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeWifi, + shill::kStateOnline, 45); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +TEST_F(NetworkIconTest, DefaultImageAndLabelWifiConnecting) { + // Set the Wifi service as connected. + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_TRUE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeWifi, + shill::kStateAssociation, 45); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests that the default network image is a cellular network icon when cellular +// network is the default network, even if a wifi network is connected. +// Generally, shill will prefer wifi over cellular networks when both are +// connected, but that is not always the case. For example, if the connected +// wifi service has no Internet connectivity, cellular service will be selected +// as default. +TEST_F(NetworkIconTest, DefaultImageAndLabelCellularDefaultWithWifiConnected) { + // Set both wifi and cellular networks in a connected state, but with wifi not + // online - this should prompt fake shill manager implementation to prefer + // cellular network over wifi. + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateReady)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeCellular, + shill::kStateOnline, 65); + + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests the use case where the default network starts reconnecting while +// another network is connected. +TEST_F(NetworkIconTest, DefaultImageReconnectingWifiWithCellularConnected) { + // First connect both wifi and cellular network (with wifi as default). + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + // Start reconnecting wifi network. + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + // Verify that the default network is connecting icon for the initial default + // network (even though the default network as reported by shill actually + // changed). + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_TRUE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network_1 = + CreateStandaloneNetworkState("reference1", shill::kTypeWifi, + shill::kStateAssociation, 45); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_1.get()))); + + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateReady)); + + // At this point the wifi network is not connecting, but is not yet default - + // the default network icon should have image for the cellular network (which + // is the default one at this point). + // TODO(tbarzic): This creates a unoptimal behavior in the UI where cellular + // icon could flash between wifi connecting and connected icons - this + // should be fixed, for example by not showing connecting icon when + // reconnecting a network if another network is connected. + std::unique_ptr<chromeos::NetworkState> reference_network_2 = + CreateStandaloneNetworkState("reference2", shill::kTypeCellular, + shill::kStateOnline, 65); + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_2.get()))); + + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + // The wifi network is online, and thus default - the default network icon + // should display the wifi network's associated image again. + std::unique_ptr<chromeos::NetworkState> reference_network_3 = + CreateStandaloneNetworkState("reference3", shill::kTypeWifi, + shill::kStateOnline, 45); + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_3.get()))); +} + +TEST_F(NetworkIconTest, DefaultImageDisconnectWifiWithCellularConnected) { + // First connect both wifi and cellular network (with wifi as default). + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + // Disconnect wifi network, and verify the default icon changes to cellular. + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateIdle)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeCellular, + shill::kStateOnline, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests that the default network image remains the same if non-default network +// reconnects. +TEST_F(NetworkIconTest, DefaultImageWhileNonDefaultNetworkReconnecting) { + // First connect both wifi and cellular network (with wifi as default). + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + // Start reconnecting the non-default, cellular network. + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + // Currently, a connecting icon is used as default network icon even if + // another network connected and used as default. + // TODO(tbarzic): Consider changing network icon logic to use a connected + // network icon if a network is connected while a network is reconnecting. + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_TRUE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network_1 = + CreateStandaloneNetworkState("reference1", shill::kTypeCellular, + shill::kStateAssociation, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_1.get()))); + + // Move the cellular network to connected, but not yet online state - the + // default network image changes back to the default network. + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateReady)); + + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + std::unique_ptr<chromeos::NetworkState> reference_network_2 = + CreateStandaloneNetworkState("reference2", shill::kTypeWifi, + shill::kStateOnline, 45); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_2.get()))); + + // Move the cellular network to online state - the default network image + // should remain the same. + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network_2.get()))); +} + +// Tests that the default network image shows a cellular network icon if +// cellular network is connected while wifi is connecting. +TEST_F(NetworkIconTest, DefaultImageConnectingToWifiWileCellularConnected) { + // Connect cellular network, and set the wifi as connecting. + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeCellular, + shill::kStateOnline, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Test that a cellular icon is displayed when activating cellular +// network (if other networks are not connected). +TEST_F(NetworkIconTest, DefaultNetworkImageActivatingCellularNetwork) { + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kActivationStateProperty, + base::Value(shill::kActivationStateActivating)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeCellular, + shill::kStateIdle, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests that default network image is a wifi network image if wifi network is +// connected during cellular network activation. +TEST_F(NetworkIconTest, + DefaultNetworkImageActivatingCellularNetworkWithConnectedWifi) { + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(45)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateOnline)); + + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kActivationStateProperty, + base::Value(shill::kActivationStateActivating)); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_FALSE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeWifi, + shill::kStateIdle, 45); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests that wifi image is shown when connecting to wifi network with vpn. +TEST_F(NetworkIconTest, DefaultNetworkImageVpnAndWifi) { + SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(wifi1_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + std::string vpn_path = ConfigureService( + R"({"GUID": "vpn_guid", "Type": "vpn", "State": "online"})"); + ASSERT_FALSE(vpn_path.empty()); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_TRUE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeWifi, + shill::kStateAssociation, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); +} + +// Tests that cellular image is shown when connecting to cellular network with +// VPN. +TEST_F(NetworkIconTest, DefaultNetworkImageVpnAndCellular) { + SetServiceProperty(cellular_path(), shill::kSignalStrengthProperty, + base::Value(65)); + SetServiceProperty(cellular_path(), shill::kStateProperty, + base::Value(shill::kStateAssociation)); + + std::string vpn_path = ConfigureService( + R"({"GUID": "vpn_guid", "Type": "vpn", "State": "online"})"); + ASSERT_FALSE(vpn_path.empty()); + + gfx::ImageSkia default_image; + base::string16 label; + bool animating = false; + ash::network_icon::GetDefaultNetworkImageAndLabel(icon_type_, &default_image, + &label, &animating); + ASSERT_FALSE(default_image.isNull()); + EXPECT_TRUE(animating); + + std::unique_ptr<chromeos::NetworkState> reference_network = + CreateStandaloneNetworkState("reference", shill::kTypeCellular, + shill::kStateAssociation, 65); + EXPECT_TRUE(gfx::test::AreImagesEqual( + gfx::Image(default_image), ImageForNetwork(reference_network.get()))); } } // namespace network_icon
diff --git a/ash/system/status_area_widget_test_api.h b/ash/system/status_area_widget_test_api.h index c83987e2..10af7197 100644 --- a/ash/system/status_area_widget_test_api.h +++ b/ash/system/status_area_widget_test_api.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ash/public/interfaces/status_area_widget_test_api.mojom.h" +#include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" #include "ash/system/status_area_widget.h" #include "base/macros.h"
diff --git a/ash/system/unified/unified_system_tray_test_api.h b/ash/system/unified/unified_system_tray_test_api.h index aa9285f..6323aacd 100644 --- a/ash/system/unified/unified_system_tray_test_api.h +++ b/ash/system/unified/unified_system_tray_test_api.h
@@ -7,7 +7,7 @@ #include <memory> -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/macros.h" namespace ui {
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc index 54d8d0a0..90ba5eaf 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -51,7 +51,7 @@ Shell::Get()->split_view_controller()->RemoveObserver(this); EnableBackdropBehindTopWindowOnEachDisplay(false); RemoveWindowCreationObservers(); - RestoreAllWindows(); + ArrangeWindowsForDesktopMode(); } int TabletModeWindowManager::GetNumberOfManagedWindows() { @@ -269,7 +269,7 @@ // guarantee the proper order, it will be turned off from here. CancelOverview(); - MaximizeAllWindows(); + ArrangeWindowsForTabletMode(); AddWindowCreationObservers(); EnableBackdropBehindTopWindowOnEachDisplay(true); display::Screen::GetScreen()->AddObserver(this); @@ -278,18 +278,77 @@ event_handler_ = std::make_unique<wm::TabletModeEventHandler>(); } -void TabletModeWindowManager::MaximizeAllWindows() { - // For maximizing and tracking windows, we want the build mru list to ignore - // the fact that the windows are on the lock screen. +void TabletModeWindowManager::ArrangeWindowsForTabletMode() { + // We want the build mru list to include windows on the lock screen. ScopedSkipUserSessionBlockedCheck scoped_skip_user_session_blocked_check; + MruWindowTracker::WindowList windows = Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal(); - // Add all existing MRU windows. + + // Specifically check for the case of no windows, so that subsequent logic can + // refer to the active window and assume it exists. + if (windows.empty()) + return; + + const mojom::WindowStateType active_window_state_type = + wm::GetWindowState(windows[0])->GetStateType(); + + // If the active window is not snapped, then just maximize all windows. + if (active_window_state_type != mojom::WindowStateType::LEFT_SNAPPED && + active_window_state_type != mojom::WindowStateType::RIGHT_SNAPPED) { + for (auto* window : windows) + MaximizeAndTrackWindow(window); + return; + } + + // The snapped active window will be represented by split view, which will be + // activated after maximizing all windows. The split view layout is decided + // here by examining window states before all those states become maximized. + SplitViewController::SnapPosition curr_win_snap_pos = + SplitViewController::NONE; + SplitViewController::SnapPosition prev_win_snap_pos = + SplitViewController::NONE; + if (active_window_state_type == mojom::WindowStateType::LEFT_SNAPPED) { + // The active window snapped on the left shall go there in split view. + curr_win_snap_pos = SplitViewController::LEFT; + + if (windows.size() > 1u && wm::GetWindowState(windows[1])->GetStateType() == + mojom::WindowStateType::RIGHT_SNAPPED) { + // The previous window snapped on the right shall go there in split view. + prev_win_snap_pos = SplitViewController::RIGHT; + } + } else { + DCHECK_EQ(mojom::WindowStateType::RIGHT_SNAPPED, active_window_state_type); + + // The active window snapped on the right shall go there in split view. + curr_win_snap_pos = SplitViewController::RIGHT; + + if (windows.size() > 1u && wm::GetWindowState(windows[1])->GetStateType() == + mojom::WindowStateType::LEFT_SNAPPED) { + // The previous window snapped on the left shall go there in split view. + prev_win_snap_pos = SplitViewController::LEFT; + } + } + + // Use |defer_bounds_update| to suppress the maximizing animation which would + // look weird here, especially when overview appears beside the active window. for (auto* window : windows) - MaximizeAndTrackWindow(window); + MaximizeAndTrackWindow(window, /*defer_bounds_update=*/true); + + // Implement the previously decided split view layout. + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + split_view_controller->SnapWindow(windows[0], curr_win_snap_pos); + if (prev_win_snap_pos == SplitViewController::NONE) + Shell::Get()->window_selector_controller()->ToggleOverview(); + else + split_view_controller->SnapWindow(windows[1], prev_win_snap_pos); + + for (auto* window : windows) + SetDeferBoundsUpdates(window, false); } -void TabletModeWindowManager::RestoreAllWindows() { +void TabletModeWindowManager::ArrangeWindowsForDesktopMode() { while (window_state_map_.size()) ForgetWindow(window_state_map_.begin()->first, false /* destroyed */); } @@ -301,7 +360,9 @@ iter->second->SetDeferBoundsUpdates(defer_bounds_updates); } -void TabletModeWindowManager::MaximizeAndTrackWindow(aura::Window* window) { +void TabletModeWindowManager::MaximizeAndTrackWindow( + aura::Window* window, + bool defer_bounds_updates) { if (!ShouldHandleWindow(window)) return; @@ -310,7 +371,8 @@ // We create and remember a tablet mode state which will attach itself to // the provided state object. - window_state_map_[window] = new TabletModeWindowState(window, this); + window_state_map_[window] = + new TabletModeWindowState(window, this, defer_bounds_updates); } void TabletModeWindowManager::ForgetWindow(aura::Window* window,
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.h b/ash/wm/tablet_mode/tablet_mode_window_manager.h index bf4bdb9..cf573b6 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager.h +++ b/ash/wm/tablet_mode/tablet_mode_window_manager.h
@@ -95,11 +95,13 @@ private: using WindowToState = std::map<aura::Window*, TabletModeWindowState*>; - // Maximize all windows and restore their current state. - void MaximizeAllWindows(); + // Maximize all windows, except that a snapped active window shall become + // represented in split view, along with the previously active window if it is + // snapped to the opposite side. + void ArrangeWindowsForTabletMode(); - // Restore all windows to their previous state. - void RestoreAllWindows(); + // Revert all windows to how they were arranged before tablet mode. + void ArrangeWindowsForDesktopMode(); // Set whether to defer bounds updates for |window|. When set to false bounds // will be updated as they may be stale. @@ -110,7 +112,8 @@ // state). // Note: If the given window cannot be handled by us the function will return // immediately. - void MaximizeAndTrackWindow(aura::Window* window); + void MaximizeAndTrackWindow(aura::Window* window, + bool defer_bounds_updates = false); // Remove a window from our tracking list. If the window is going to be // destroyed, do not restore its old previous window state object as it will
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc index 8e6d7ae..117b42db 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -43,6 +43,7 @@ #include "ui/events/test/event_generator.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/transient_window_manager.h" +#include "ui/wm/core/window_util.h" namespace ash { @@ -169,6 +170,22 @@ return window; } + // Creates a test window snapped on the left in desktop mode. + std::unique_ptr<aura::Window> CreateDesktopWindowSnappedLeft() { + std::unique_ptr<aura::Window> window = CreateTestWindow(); + wm::WMEvent snap_to_left(wm::WMEventType::WM_EVENT_CYCLE_SNAP_LEFT); + wm::GetWindowState(window.get())->OnWMEvent(&snap_to_left); + return window; + } + + // Creates a test window snapped on the right in desktop mode. + std::unique_ptr<aura::Window> CreateDesktopWindowSnappedRight() { + std::unique_ptr<aura::Window> window = CreateTestWindow(); + wm::WMEvent snap_to_right(wm::WMEventType::WM_EVENT_CYCLE_SNAP_RIGHT); + wm::GetWindowState(window.get())->OnWMEvent(&snap_to_right); + return window; + } + private: DISALLOW_COPY_AND_ASSIGN(TabletModeWindowManagerTest); }; @@ -1830,4 +1847,76 @@ EXPECT_EQ(rect.size(), child->bounds().size()); } +// Test that if the active window is not snapped before tablet mode, then +// neither split view nor overview is activated. +TEST_F(TabletModeWindowManagerTest, ActiveNoSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> window = CreateTestWindow(); + ::wm::ActivateWindow(window.get()); + ASSERT_TRUE(CreateTabletModeWindowManager()); + EXPECT_EQ(SplitViewController::NO_SNAP, split_view_controller->state()); + EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting()); +} + +// Test that if the active window is snapped on the left before tablet mode, +// then split view is activated with the active window on the left. +TEST_F(TabletModeWindowManagerTest, ActiveLeftSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> window = CreateDesktopWindowSnappedLeft(); + ::wm::ActivateWindow(window.get()); + ASSERT_TRUE(CreateTabletModeWindowManager()); + EXPECT_EQ(SplitViewController::LEFT_SNAPPED, split_view_controller->state()); + EXPECT_EQ(window.get(), split_view_controller->left_window()); + EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting()); +} + +// Test that if the active window is snapped on the right before tablet mode, +// then split view is activated with the active window on the right. +TEST_F(TabletModeWindowManagerTest, ActiveRightSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> window = CreateDesktopWindowSnappedRight(); + ::wm::ActivateWindow(window.get()); + ASSERT_TRUE(CreateTabletModeWindowManager()); + EXPECT_EQ(SplitViewController::RIGHT_SNAPPED, split_view_controller->state()); + EXPECT_EQ(window.get(), split_view_controller->right_window()); + EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting()); +} + +// Test that if before tablet mode, the active window is snapped on the left and +// the previous window is snapped on the right, then split view is activated +// with the active window on the left and the previous window on the right. +TEST_F(TabletModeWindowManagerTest, ActiveLeftSnapPreviousRightSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> left_window = CreateDesktopWindowSnappedLeft(); + std::unique_ptr<aura::Window> right_window = + CreateDesktopWindowSnappedRight(); + ::wm::ActivateWindow(left_window.get()); + ASSERT_TRUE(CreateTabletModeWindowManager()); + EXPECT_EQ(SplitViewController::BOTH_SNAPPED, split_view_controller->state()); + EXPECT_EQ(left_window.get(), split_view_controller->left_window()); + EXPECT_EQ(right_window.get(), split_view_controller->right_window()); + EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting()); +} + +// Test that if before tablet mode, the active window is snapped on the right +// and the previous window is snapped on the left, then split view is activated +// with the active window on the right and the previous window on the left. +TEST_F(TabletModeWindowManagerTest, ActiveRightSnapPreviousLeftSnap) { + SplitViewController* split_view_controller = + Shell::Get()->split_view_controller(); + std::unique_ptr<aura::Window> left_window = CreateDesktopWindowSnappedLeft(); + std::unique_ptr<aura::Window> right_window = + CreateDesktopWindowSnappedRight(); + ::wm::ActivateWindow(right_window.get()); + ASSERT_TRUE(CreateTabletModeWindowManager()); + EXPECT_EQ(SplitViewController::BOTH_SNAPPED, split_view_controller->state()); + EXPECT_EQ(left_window.get(), split_view_controller->left_window()); + EXPECT_EQ(right_window.get(), split_view_controller->right_window()); + EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting()); +} + } // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc index 92b5287..f11d0979 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -167,10 +167,12 @@ } TabletModeWindowState::TabletModeWindowState(aura::Window* window, - TabletModeWindowManager* creator) + TabletModeWindowManager* creator, + bool defer_bounds_updates) : window_(window), creator_(creator), - current_state_type_(wm::GetWindowState(window)->GetStateType()) { + current_state_type_(wm::GetWindowState(window)->GetStateType()), + defer_bounds_updates_(defer_bounds_updates) { old_state_.reset(wm::GetWindowState(window) ->SetStateObject(std::unique_ptr<State>(this)) .release());
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.h b/ash/wm/tablet_mode/tablet_mode_window_state.h index 88b0e38b..2d5af86 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.h +++ b/ash/wm/tablet_mode/tablet_mode_window_state.h
@@ -26,7 +26,9 @@ // state handler. Upon destruction it will restore the previous state handler // and call |creator::WindowStateDestroyed()| to inform that the window mode // was reverted to the old window manager. - TabletModeWindowState(aura::Window* window, TabletModeWindowManager* creator); + TabletModeWindowState(aura::Window* window, + TabletModeWindowManager* creator, + bool defer_bounds_updates); ~TabletModeWindowState() override; void set_ignore_wm_events(bool ignore) { ignore_wm_events_ = ignore; }
diff --git a/base/message_loop/message_loop_impl.cc b/base/message_loop/message_loop_impl.cc index 52526b4..a7e30b2 100644 --- a/base/message_loop/message_loop_impl.cc +++ b/base/message_loop/message_loop_impl.cc
@@ -11,7 +11,6 @@ #include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/debug/task_annotator.h" -#include "base/feature_list.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop_task_runner.h" @@ -19,9 +18,7 @@ #include "base/message_loop/message_pump_for_io.h" #include "base/message_loop/message_pump_for_ui.h" #include "base/message_loop/sequenced_task_source.h" -#include "base/optional.h" #include "base/run_loop.h" -#include "base/synchronization/lock.h" #include "base/task/common/operations_controller.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" @@ -34,13 +31,6 @@ #include "base/message_loop/message_pump_android.h" #endif -namespace { - -constexpr base::Feature kLockFreeScheduleWork{"LockFreeScheduleWork", - base::FEATURE_ENABLED_BY_DEFAULT}; - -} // namespace - namespace base { class MessageLoopImpl::Controller : public SequencedTaskSource::Observer { @@ -73,12 +63,6 @@ private: internal::OperationsController operations_controller_; - // An optional lock, only instantiated and used when kLockFreeScheduleWork is - // experimentally disabled. This lock is undesired, we only run a retroactive - // experiment to reintroduce it to confirm that we see the impact of its - // removal across our new swath of jank metrics. - Optional<Lock> undesired_operations_lock_; - // A TaskAnnotator which is owned by this Controller to be able to use it // without locking |message_loop_lock_|. It cannot be owned by MessageLoop // because this Controller cannot access |message_loop_| safely without the @@ -95,8 +79,6 @@ MessageLoopImpl::Controller::Controller(MessageLoopImpl* message_loop) : message_loop_(message_loop) { DCHECK(message_loop_); - if (!FeatureList::IsEnabled(kLockFreeScheduleWork)) - undesired_operations_lock_.emplace(); } void MessageLoopImpl::Controller::WillQueueTask(PendingTask* task) { @@ -111,12 +93,6 @@ if (!operation_token) return; - // This is a retroactive experiment to determine the performance improvement - // caused by the removal of this lock in an earlier CL. - Optional<AutoLock> undesired_schedule_work_lock; - if (undesired_operations_lock_) - undesired_schedule_work_lock.emplace(*undesired_operations_lock_); - // Some scenarios can result in getting to this point on multiple threads at // once, e.g.: //
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py index cba8c7f..effc6a1 100755 --- a/build/android/gyp/dex.py +++ b/build/android/gyp/dex.py
@@ -37,6 +37,10 @@ parser = optparse.OptionParser() build_utils.AddDepfileOption(parser) + parser.add_option('--classpath', help='Classpaths necessary for desugaring.') + parser.add_option( + '--sdk-jars', + help='Path(s) to android sdk jar, necessary for desugaring.') parser.add_option('--output-directory', default=os.getcwd(), help='Path to the output build directory.') @@ -318,7 +322,13 @@ if options.multi_dex: input_paths.append(options.main_dex_list_path) - dex_cmd = ['java', '-jar', options.d8_jar_path, '--no-desugaring'] + dex_cmd = ['java', '-jar', options.d8_jar_path] + options.sdk_jars = build_utils.ParseGnList(options.sdk_jars) + options.classpath = build_utils.ParseGnList(options.classpath) + for path in options.classpath: + dex_cmd += ['--classpath', path] + for path in options.sdk_jars: + dex_cmd += ['--lib', path] if options.multi_dex: dex_cmd += ['--main-dex-list', options.main_dex_list_path] if options.release:
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py index 84fbd02..4e6ec5f7 100755 --- a/build/android/gyp/proguard.py +++ b/build/android/gyp/proguard.py
@@ -14,19 +14,6 @@ from util import proguard_util -_DANGEROUS_OPTIMIZATIONS = [ - # See crbug.com/825995 (can cause VerifyErrors) - "class/merging/vertical", - "class/unboxing/enum", - # See crbug.com/625992 - "code/allocation/variable", - # See crbug.com/625994 - "field/propagation/value", - "method/propagation/parameter", - "method/propagation/returnvalue", -] - - # Example: # android.arch.core.internal.SafeIterableMap$Entry -> b: # 1:1:java.lang.Object getKey():353:353 -> getKey @@ -56,13 +43,12 @@ help='GN list of paths to proguard configuration files ' 'included by --proguard-configs, but that should ' 'not actually be included.') - parser.add_option('--mapping', help='Path to proguard mapping to apply.') + parser.add_option( + '--apply-mapping', help='Path to proguard mapping to apply.') parser.add_option('--mapping-output', help='Path for proguard to output mapping file to.') parser.add_option('--classpath', action='append', help='Classpath for proguard.') - parser.add_option('--enable-dangerous-optimizations', action='store_true', - help='Enable optimizations which are known to have issues.') parser.add_option('--main-dex-rules-path', action='append', help='Paths to main dex rules for multidex' '- only works with R8.') @@ -95,6 +81,10 @@ if not options.mapping_output: options.mapping_output = options.output_path + ".mapping" + if options.apply_mapping: + options.apply_mapping = os.path.abspath(options.apply_mapping) + + return options @@ -117,26 +107,26 @@ shutil.move(tmp_dex_path, dex_path) -def _CreateR8Command(options, map_output_path, output_dir): - # TODO: R8 needs -applymapping equivalent. +def _CreateR8Command(options, map_output_path, output_dir, tmp_proguard_config, + libraries): cmd = [ 'java', '-jar', options.r8_path, - '--no-desugaring', '--no-data-resources', '--output', output_dir, '--pg-map-output', map_output_path, ] - classpath = [ - p for p in set(options.classpath) if p not in options.input_paths - ] - - for lib in classpath: + for lib in libraries: cmd += ['--lib', lib] for config_file in options.proguard_configs: cmd += ['--pg-conf', config_file] + if options.apply_mapping: + tmp_proguard_config.write('-applymapping ' + options.apply_mapping) + tmp_proguard_config.flush() + cmd += ['--pg-conf', tmp_proguard_config.name] + if options.min_api: cmd += ['--min-api', options.min_api] @@ -152,33 +142,27 @@ args = build_utils.ExpandFileArgs(args) options = _ParseOptions(args) - proguard = proguard_util.ProguardCmdBuilder(options.proguard_path) - proguard.injars(options.input_paths) - proguard.configs(options.proguard_configs) - proguard.config_exclusions(options.proguard_config_exclusions) - proguard.outjar(options.output_path) - proguard.mapping_output(options.mapping_output) - - # If a jar is part of input no need to include it as library jar. - classpath = [ - p for p in set(options.classpath) if p not in options.input_paths - ] - proguard.libraryjars(classpath) - proguard.verbose(options.verbose) - if not options.enable_dangerous_optimizations: - proguard.disable_optimizations(_DANGEROUS_OPTIMIZATIONS) + libraries = [] + for p in options.classpath: + # If a jar is part of input no need to include it as library jar. + if p not in libraries and p not in options.input_paths: + libraries.append(p) # TODO(agrieve): Remove proguard usages. if options.r8_path: with tempfile.NamedTemporaryFile() as mapping_temp: - if options.output_path.endswith('.dex'): - with build_utils.TempDir() as tmp_dex_dir: - cmd = _CreateR8Command(options, mapping_temp.name, tmp_dex_dir) + with tempfile.NamedTemporaryFile() as tmp_proguard_config: + if options.output_path.endswith('.dex'): + with build_utils.TempDir() as tmp_dex_dir: + cmd = _CreateR8Command(options, mapping_temp.name, tmp_dex_dir, + tmp_proguard_config, libraries) + build_utils.CheckOutput(cmd) + _MoveTempDexFile(tmp_dex_dir, options.output_path) + else: + cmd = _CreateR8Command(options, mapping_temp.name, + options.output_path, tmp_proguard_config, + libraries) build_utils.CheckOutput(cmd) - _MoveTempDexFile(tmp_dex_dir, options.output_path) - else: - cmd = _CreateR8Command(options, mapping_temp.name, options.output_path) - build_utils.CheckOutput(cmd) # Copy the mapping file back to where it should be. map_path = options.mapping_output @@ -188,20 +172,35 @@ mapping_temp.seek(0) mapping.writelines(l for l in mapping_temp if not l.startswith("#")) - build_utils.WriteDepfile(options.depfile, options.output_path, - inputs=proguard.GetDepfileDeps(), - add_pydeps=False) + other_inputs = [] + if options.apply_mapping: + other_inputs += options.apply_mapping + + build_utils.WriteDepfile( + options.depfile, + options.output_path, + inputs=options.proguard_configs + options.input_paths + libraries + + other_inputs, + add_pydeps=False) else: + proguard = proguard_util.ProguardCmdBuilder(options.proguard_path) + proguard.injars(options.input_paths) + proguard.configs(options.proguard_configs) + proguard.config_exclusions(options.proguard_config_exclusions) + proguard.outjar(options.output_path) + proguard.mapping_output(options.mapping_output) + proguard.libraryjars(libraries) + proguard.verbose(options.verbose) # Do not consider the temp file as an input since its name is random. input_paths = proguard.GetInputs() with tempfile.NamedTemporaryFile() as f: - if options.mapping: - input_paths.append(options.mapping) + if options.apply_mapping: + input_paths.append(options.apply_mapping) # Maintain only class name mappings in the .mapping file in order to # work around what appears to be a ProGuard bug in -applymapping: # method 'int close()' is not being kept as 'a', but remapped to 'c' - _RemoveMethodMappings(options.mapping, f) + _RemoveMethodMappings(options.apply_mapping, f) proguard.mapping(f.name) input_strings = proguard.build()
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 7a02ba5..2fb5743 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -221,9 +221,10 @@ android_sdk_tools_bundle_aapt2 = "//third_party/android_build_tools/aapt2/aapt2" - # Use r8 for Java optimization rather than ProGuard. - # This will evenutally be the default. https://crbug.com/872904 - experimental_use_r8 = false + # Use R8 for Java optimization rather than ProGuard for all targets. R8 is + # already used as the default for public targets. This will evenutally be + # the default. https://crbug.com/908988 + use_r8 = false } # We need a second declare_args block to make sure we are using the overridden
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index f70eb63..9bbcaca 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -951,13 +951,7 @@ pool = "//build/toolchain:link_pool($default_toolchain)" _output_path = invoker.output_path - _proguard_jar_path = _default_proguard_jar_path - if (defined(invoker.proguard_jar_path)) { - _proguard_jar_path = invoker.proguard_jar_path - } - inputs = [ - _proguard_jar_path, invoker.build_config, ] if (defined(invoker.inputs)) { @@ -976,8 +970,6 @@ args = [ "--depfile", rebase_path(depfile, root_build_dir), - "--proguard-path", - rebase_path(_proguard_jar_path, root_build_dir), "--output-path", rebase_path(_output_path, root_build_dir), "--mapping-output", @@ -987,20 +979,25 @@ "--classpath", "@FileArg($_rebased_build_config:android:sdk_jars)", ] - if (experimental_use_r8) { + + if (!defined(invoker.proguard_jar_path) || use_r8) { args += [ "--r8-path", rebase_path(_r8_path, root_build_dir), ] + inputs += [ _r8_path ] + } else { + _proguard_jar_path = invoker.proguard_jar_path + args += [ + "--proguard-path", + rebase_path(_proguard_jar_path, root_build_dir), + ] + inputs += [ _proguard_jar_path ] } + if (defined(invoker.args)) { args += invoker.args } - if (defined(invoker.proguard_jar_path)) { - # We assume that if we are using a different ProGuard, this new version - # can handle the 'dangerous' optimizaions. - args += [ "--enable-dangerous-optimizations" ] - } } } @@ -1074,11 +1071,18 @@ _proguard_enabled = defined(invoker.proguard_enabled) && invoker.proguard_enabled - _proguarding_with_r8 = _proguard_enabled && experimental_use_r8 + _proguarding_with_r8 = + _proguard_enabled && !defined(invoker.proguard_jar_path) + _enable_multidex = + defined(invoker.enable_multidex) && invoker.enable_multidex assert(!(defined(invoker.input_jars) && _proguard_enabled), "input_jars can't be specified when proguarding a dex.") + if (_enable_multidex) { + _main_dex_rules = "//build/android/main_dex_classes.flags" + } + if (!_proguarding_with_r8) { _dexing_jars = [] if (defined(invoker.input_jars)) { @@ -1088,10 +1092,6 @@ if (_proguard_enabled) { if (defined(invoker.enable_multidex)) { - assert(invoker.enable_multidex || !invoker.enable_multidex) - if (defined(invoker.extra_main_dex_proguard_config)) { - assert(invoker.extra_main_dex_proguard_config != []) - } if (defined(invoker.negative_main_dex_globs)) { assert(invoker.negative_main_dex_globs != []) } @@ -1145,13 +1145,27 @@ ] } + if (_enable_multidex && _proguarding_with_r8) { + if (defined(invoker.extra_main_dex_proguard_config)) { + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + inputs += [ invoker.extra_main_dex_proguard_config ] + } + args += [ + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + ] + inputs += [ _main_dex_rules ] + } + output_path = _proguard_output_path } } if (!_proguarding_with_r8) { - _enable_multidex = - defined(invoker.enable_multidex) && invoker.enable_multidex if (_enable_multidex) { _main_dex_list_path = invoker.output + ".main_dex_list" _main_dex_list_target_name = "${target_name}__main_dex_list" @@ -1168,8 +1182,6 @@ # http://crbug.com/725224. Fix for bots running out of memory. pool = "//build/toolchain:link_pool($default_toolchain)" - main_dex_rules = "//build/android/main_dex_classes.flags" - if (defined(invoker.proguard_jar_path)) { _proguard_jar_path = invoker.proguard_jar_path } else { @@ -1179,7 +1191,7 @@ _shrinked_android = "$android_sdk_build_tools/lib/shrinkedAndroid.jar" _dx = "$android_sdk_build_tools/lib/dx.jar" inputs = [ - main_dex_rules, + _main_dex_rules, _dx, _proguard_jar_path, _shrinked_android, @@ -1199,7 +1211,7 @@ "--main-dex-list-path", rebase_path(_main_dex_list_path, root_build_dir), "--main-dex-rules-path", - rebase_path(main_dex_rules, root_build_dir), + rebase_path(_main_dex_rules, root_build_dir), "--proguard-path", rebase_path(_proguard_jar_path, root_build_dir), ] @@ -1243,22 +1255,31 @@ ]) script = "//build/android/gyp/dex.py" depfile = "$target_gen_dir/$target_name.d" - inputs = [] + inputs = [ + invoker.build_config, + ] outputs = [ invoker.output, ] _rebased_output = rebase_path(invoker.output, root_build_dir) - + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) args = [ "--depfile", rebase_path(depfile, root_build_dir), "--dex-path", _rebased_output, + "--sdk-jars=@FileArg($_rebased_build_config:android:sdk_jars)", ] + # Some targets use java_runtime_classpath and others use + # javac_full_interface_classpath. Either of them will work for desugar. if (_proguard_enabled) { deps += [ ":${_proguard_target_name}" ] + args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)" ] + } else { + args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)" ] } if (_enable_multidex) { @@ -1425,7 +1446,7 @@ # Turned off because of existing code which fails the assertion _enable_thread_annotations = false - _desugar = defined(invoker.supports_android) && invoker.supports_android + _desugar = defined(invoker.desugar) && invoker.desugar _emma_instrument = invoker.emma_instrument _enable_bytecode_rewriter = _enable_assert || _enable_custom_resources || _enable_thread_annotations @@ -3357,6 +3378,11 @@ _accumulated_public_deps += [ ":$_copy_system_library_target_name" ] } else { _process_prebuilt_target_name = "${target_name}__process_prebuilt" + + # Skip desugaring for debug builds using r8 to increase incremental + # build speed. Release builds still need desugar.jar for binary size. + _using_r8 = !defined(invoker.proguard_jar_path) || use_r8 + _desugar = !(_using_r8 && is_java_debug) && _supports_android process_java_prebuilt(_process_prebuilt_target_name) { forward_variables_from(invoker, [ @@ -3366,7 +3392,7 @@ "jar_included_patterns", ]) is_prebuilt = _is_prebuilt - supports_android = _supports_android + desugar = _desugar enable_build_hooks = _enable_build_hooks enable_build_hooks_android = _enable_build_hooks_android build_config = _build_config @@ -3389,7 +3415,9 @@ dex("${target_name}__dex") { input_jars = [ _final_jar_path ] output = _dex_path + build_config = _build_config deps = [ + ":$_build_config_target_name", ":$_process_prebuilt_target_name", ] }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index bcb3d717..add2ce2 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2578,10 +2578,6 @@ forward_variables_from(invoker, [ "proguard_jar_path" ]) deps += _deps + [ ":$_compile_resources_target" ] proguard_configs = [ _jar_path ] - if (defined(invoker.apk_under_test)) { - proguard_args = [ "--mapping=@FileArg($_rebased_build_config:deps_info:proguard_under_test_mapping)" ] - deps += [ "${invoker.apk_under_test}__final_dex" ] - } proguard_mapping_path = _proguard_mapping_path } else { if (_enable_multidex) {
diff --git a/build/config/posix/BUILD.gn b/build/config/posix/BUILD.gn index af09c96..a143421 100644 --- a/build/config/posix/BUILD.gn +++ b/build/config/posix/BUILD.gn
@@ -35,7 +35,13 @@ libs = [] if (use_custom_libcxx) { - if (!is_component_build) { + if (is_component_build) { + # In component builds, symbols from libc++.so are exported for all DSOs to + # use. If the system libc++ gets loaded (indirectly through a system + # library), then it will conflict with our libc++.so. Add a custom ABI + # version to avoid conflicts. + defines += [ "_LIBCPP_ABI_VERSION=Cr" ] + } else { # Don't leak any symbols on a static build. defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ] if (!export_libcxxabi_from_executables) {
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 9e6ead0..805818ea0 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -264,9 +264,12 @@ cflags_cc += [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ] if (!is_component_build) { + # Don't leak any symbols on a static build. defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ] } + # Windows doesn't need to set _LIBCPP_ABI_VERSION since there's no system + # C++ library we could conflict with. defines += [ "CR_LIBCXX_REVISION=$libcxx_svn_revision", "CR_LIBCXXABI_REVISION=$libcxxabi_svn_revision",
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 9eaf90f..3f2bf53 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -3697400dc0b66d69e8bb1544147bf387ae4e5a81 \ No newline at end of file +4cb6cfe20aa2144b34d051ee31306969be7582c7 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index d13ca12..60095c4 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -fa7ae7dc8664d4089fd890b79358d1db5cfb7fa1 \ No newline at end of file +ece0fa0dc069c87a2ce7636fc4b170de33642d05 \ No newline at end of file
diff --git a/cc/animation/keyframe_model.cc b/cc/animation/keyframe_model.cc index 51449a9..06c9a54 100644 --- a/cc/animation/keyframe_model.cc +++ b/cc/animation/keyframe_model.cc
@@ -143,14 +143,10 @@ } void KeyframeModel::Pause(base::TimeDelta pause_offset) { - // Convert pause offset to monotonic time. - - // TODO(crbug.com/840364): This conversion is incorrect. pause_offset is - // actually a local time so to convert it to monotonic time we should include - // total_paused_duration_ but exclude time_offset. The current calculation is - // is incorrect for animations that have start-delay or are paused and - // unpaused multiple times. - base::TimeTicks monotonic_time = pause_offset + start_time_ + time_offset_; + // Convert pause offset which is in local time to monotonic time. + // TODO(yigu): This should be scaled by playbackrate. http://crbug.com/912407 + base::TimeTicks monotonic_time = + pause_offset + start_time_ + total_paused_duration_; SetRunState(PAUSED, monotonic_time); } @@ -242,8 +238,7 @@ return base::TimeDelta(); // If we're paused, time is 'stuck' at the pause time. - base::TimeTicks time = - (run_state_ == PAUSED) ? pause_time_ - time_offset_ : monotonic_time; + base::TimeTicks time = (run_state_ == PAUSED) ? pause_time_ : monotonic_time; return time - start_time_ - total_paused_duration_; }
diff --git a/cc/animation/keyframe_model_unittest.cc b/cc/animation/keyframe_model_unittest.cc index e205231..a04fe6d 100644 --- a/cc/animation/keyframe_model_unittest.cc +++ b/cc/animation/keyframe_model_unittest.cc
@@ -438,16 +438,67 @@ .InSecondsF()); } +TEST(KeyframeModelTest, TrimTimePauseBasic) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + // When paused, the time returned is always the pause time + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1)) + .InSecondsF()); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.2)) + .InSecondsF()); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2)) + .InSecondsF()); +} + +TEST(KeyframeModelTest, TrimTimePauseAffectedByDelay) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Pause time is in local time so delay should apply on top of it. + keyframe_model->set_time_offset(TimeDelta::FromSecondsD(-0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.3, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); + + keyframe_model->set_time_offset(TimeDelta::FromSecondsD(0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.7, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); +} + +TEST(KeyframeModelTest, TrimTimePauseNotAffectedByStartTime) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Pause time is in local time so start time should not affect it. + keyframe_model->set_start_time(TicksFromSecondsF(0.2)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); + + keyframe_model->set_start_time(TicksFromSecondsF(0.4)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); + EXPECT_EQ(0.5, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.1)) + .InSecondsF()); +} + TEST(KeyframeModelTest, TrimTimePauseResume) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->SetRunState(KeyframeModel::RUNNING, TicksFromSecondsF(0.0)); EXPECT_EQ(0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); - EXPECT_EQ(0.5, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) + EXPECT_EQ(0.4, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.4)) .InSecondsF()); - keyframe_model->SetRunState(KeyframeModel::PAUSED, TicksFromSecondsF(0.5)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.5)); EXPECT_EQ( 0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) .InSecondsF()); @@ -459,6 +510,15 @@ EXPECT_EQ( 1, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.5)) .InSecondsF()); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.6)); + EXPECT_EQ( + 0.6, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2000.0)) + .InSecondsF()); + keyframe_model->SetRunState(KeyframeModel::RUNNING, + TicksFromSecondsF(2000.0)); + EXPECT_EQ( + 0.7, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(2000.1)) + .InSecondsF()); } TEST(KeyframeModelTest, TrimTimePauseResumeReverse) { @@ -471,7 +531,7 @@ EXPECT_EQ(0.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); - keyframe_model->SetRunState(KeyframeModel::PAUSED, TicksFromSecondsF(0.25)); + keyframe_model->Pause(base::TimeDelta::FromSecondsD(0.25)); EXPECT_EQ(0.75, keyframe_model ->TrimTimeToCurrentIteration(TicksFromSecondsF(1024.0)) .InSecondsF());
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index a12b09a..74d2b6d 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -31,7 +31,6 @@ "image_provider.h", "image_transfer_cache_entry.cc", "image_transfer_cache_entry.h", - "layer_tree_painter.h", "paint_cache.cc", "paint_cache.h", "paint_canvas.h", @@ -61,6 +60,7 @@ "paint_shader.cc", "paint_shader.h", "paint_worklet_input.h", + "paint_worklet_layer_painter.h", "raw_memory_transfer_cache_entry.cc", "raw_memory_transfer_cache_entry.h", "record_paint_canvas.cc",
diff --git a/cc/paint/layer_tree_painter.h b/cc/paint/layer_tree_painter.h deleted file mode 100644 index 9536252..0000000 --- a/cc/paint/layer_tree_painter.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CC_PAINT_LAYER_TREE_PAINTER_H_ -#define CC_PAINT_LAYER_TREE_PAINTER_H_ - -#include "cc/cc_export.h" - -namespace cc { - -class CC_EXPORT LayerTreePainter { - public: - virtual ~LayerTreePainter() {} - - // TODO(xidachen) add a PaintWorkletPaint function. -}; - -} // namespace cc - -#endif // CC_PAINT_LAYER_TREE_PAINTER_H_
diff --git a/cc/paint/paint_worklet_layer_painter.h b/cc/paint/paint_worklet_layer_painter.h new file mode 100644 index 0000000..586bd3b7 --- /dev/null +++ b/cc/paint/paint_worklet_layer_painter.h
@@ -0,0 +1,21 @@ +// 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 CC_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_ +#define CC_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_ + +#include "cc/cc_export.h" + +namespace cc { + +class CC_EXPORT PaintWorkletLayerPainter { + public: + virtual ~PaintWorkletLayerPainter() {} + + // TODO(xidachen) add a PaintWorkletPaint function. +}; + +} // namespace cc + +#endif // CC_PAINT_PAINT_WORKLET_LAYER_PAINTER_H_
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 4a1c252..75d238e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1457,9 +1457,6 @@ load_library_from_apk = _is_modern && chromium_linker_supported version_name = chrome_version_name - if (!experimental_use_r8) { - enable_multidex = true - } } } @@ -1558,9 +1555,6 @@ (!defined(use_trichrome_library) || !use_trichrome_library) version_name = chrome_version_name - if (!experimental_use_r8) { - enable_multidex = true - } } } @@ -1823,9 +1817,6 @@ base_module_target = ":chrome_public_base_module" if (!is_java_debug) { proguard_enabled = true - if (!experimental_use_r8) { - enable_multidex = true - } } # Signing is very slow, only do that for official builds. @@ -1839,9 +1830,6 @@ base_module_target = ":chrome_modern_public_base_module" if (!is_java_debug) { proguard_enabled = true - if (!experimental_use_r8) { - enable_multidex = true - } } enable_language_splits = enable_chrome_language_splits if (modularize_vr) { @@ -1859,9 +1847,6 @@ base_module_target = ":monochrome_public_base_module" if (!is_java_debug) { proguard_enabled = true - if (!experimental_use_r8) { - enable_multidex = true - } proguard_android_sdk_dep = webview_framework_dep } enable_language_splits = enable_chrome_language_splits
diff --git a/chrome/android/java/res/layout-sw600dp/location_status_icon.xml b/chrome/android/java/res/layout-sw600dp/location_status_icon.xml new file mode 100644 index 0000000..2a5653c --- /dev/null +++ b/chrome/android/java/res/layout-sw600dp/location_status_icon.xml
@@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/location_bar_status_icon" + style="@style/LocationBarButton" + android:layout_width="@dimen/location_bar_icon_width" + android:layout_height="match_parent" + android:layout_gravity="center" + android:contentDescription="@string/accessibility_toolbar_btn_site_info" + android:scaleType="center" /> +</merge>
diff --git a/chrome/android/java/res/layout/autofill_name_fixflow.xml b/chrome/android/java/res/layout/autofill_name_fixflow.xml index c091f65..96ebfcec 100644 --- a/chrome/android/java/res/layout/autofill_name_fixflow.xml +++ b/chrome/android/java/res/layout/autofill_name_fixflow.xml
@@ -11,6 +11,7 @@ style="@style/AlertDialogContent" android:minHeight="36dp" android:layout_marginBottom="32dp" + android:paddingBottom="16dp" android:layout_marginTop="6dp" android:orientation="horizontal" android:gravity="center_vertical"> @@ -30,7 +31,7 @@ android:hint="@string/autofill_card_holder_name" android:layout_width="match_parent" android:layout_height="wrap_content" - android:imeOptions="flagNoExtractUi" + android:imeOptions="actionDone" android:inputType="textCapWords"/> </org.chromium.chrome.browser.widget.CompatibilityTextInputLayout>
diff --git a/chrome/android/java/res/layout/location_status.xml b/chrome/android/java/res/layout/location_status.xml index ea736de2..a993528 100644 --- a/chrome/android/java/res/layout/location_status.xml +++ b/chrome/android/java/res/layout/location_status.xml
@@ -11,14 +11,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent"> - <org.chromium.ui.widget.ChromeImageButton - android:id="@+id/location_bar_status_icon" - style="@style/LocationBarButton" - android:layout_width="@dimen/location_bar_start_icon_width" - android:layout_height="match_parent" - android:layout_gravity="center" - android:contentDescription="@string/accessibility_toolbar_btn_site_info" - android:scaleType="center" /> + <include layout="@layout/location_status_icon" /> <TextView android:id="@+id/location_bar_verbose_status" android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/location_status_icon.xml b/chrome/android/java/res/layout/location_status_icon.xml new file mode 100644 index 0000000..722f8a2 --- /dev/null +++ b/chrome/android/java/res/layout/location_status_icon.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/location_bar_status_icon" + style="@style/LocationBarButton" + android:layout_width="@dimen/location_bar_start_icon_width" + android:layout_height="match_parent" + android:layout_gravity="center" + android:paddingEnd="4dp" + android:contentDescription="@string/accessibility_toolbar_btn_site_info" + android:scaleType="center" /> +</merge>
diff --git a/chrome/android/java/res/layout/preference_text_scale.xml b/chrome/android/java/res/layout/preference_text_scale.xml index 6281107c..6645594 100644 --- a/chrome/android/java/res/layout/preference_text_scale.xml +++ b/chrome/android/java/res/layout/preference_text_scale.xml
@@ -32,12 +32,13 @@ <TextView android:id="@+id/preview" android:layout_width="match_parent" - android:layout_height="180dp" + android:layout_height="wrap_content" + android:minHeight="180dp" android:layout_marginTop="10dp" android:background="#fafafa" android:padding="16dp" android:text="@string/font_size_preview_text" - android:textColor="?android:attr/textColorPrimary" + android:textAppearance="@style/TextAppearance.AccessibilityTextPreference" android:lineSpacingExtra="6dp" /> </LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index b635b01..1e93ba6 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -40,6 +40,8 @@ <item name="android:windowExitTransition" tools:targetApi="21">@null</item> <item name="android:windowSharedElementEnterTransition" tools:targetApi="21">@transition/move_image</item> <item name="android:windowSharedElementExitTransition" tools:targetApi="21">@transition/move_image</item> + <item name="android:popupMenuStyle">@style/PopupMenuStyle</item> + <item name="android:contextPopupMenuStyle" tools:targetApi="24">@style/PopupMenuStyle</item> </style> <style name="MainTheme" parent="MainThemeBase" /> <style name="TranslucentMainTheme" parent="MainThemeBase"> @@ -74,6 +76,8 @@ <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="spinnerStyle">@style/SpinnerStyle</item> <item name="windowNoTitle">true</item> + <item name="android:popupMenuStyle">@style/PopupMenuStyle</item> + <item name="android:contextPopupMenuStyle" tools:targetApi="24">@style/PopupMenuStyle</item> </style> <style name="FullscreenWhite" parent="FullscreenWhiteBase" /> @@ -144,6 +148,8 @@ <item name="floatLabelPaddingTop">@dimen/pref_autofill_field_top_margin</item> <item name="actionBarStyle">@style/PreferenceActionBarModern</item> <item name="android:windowContentOverlay">@null</item> + <item name="android:popupMenuStyle">@style/PopupMenuStyle</item> + <item name="android:contextPopupMenuStyle" tools:targetApi="24">@style/PopupMenuStyle</item> </style> <style name="PreferenceActionBarModern" parent="@style/Widget.AppCompat.Light.ActionBar.Solid"> <item name="titleTextStyle">@style/BlackHeadline</item> @@ -201,6 +207,9 @@ <item name="android:layout_marginTop">2dp</item> <item name="android:background">@color/modern_grey_600</item> </style> + <style name="TextAppearance.AccessibilityTextPreference"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + </style> <style name="ThemeWithActionBarBase" parent="Theme.AppCompat.Light"> <item name="android:windowBackground">@drawable/action_bar_activity_bg</item> @@ -212,6 +221,8 @@ <item name="colorAccent">@color/pref_accent_color</item> <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="spinnerStyle">@style/SpinnerStyle</item> + <item name="android:popupMenuStyle">@style/PopupMenuStyle</item> + <item name="android:contextPopupMenuStyle" tools:targetApi="24">@style/PopupMenuStyle</item> </style> <style name="ThemeWithActionBar" parent="ThemeWithActionBarBase" /> @@ -337,6 +348,13 @@ <item name="android:popupElevation" tools:targetApi="21">0dp</item> </style> + <!-- Popup and long-press context popup menu style --> + <style name="PopupMenuStyle" parent="Widget.AppCompat.Light.PopupMenu"> + <item name="android:popupBackground">@drawable/popup_bg</item> + <item name="android:overlapAnchor" tools:targetApi="21">true</item> + <item name="android:popupElevation" tools:targetApi="21">0dp</item> + </style> + <!-- Bubble styles --> <style name="TextBubbleAnimation"> <item name="android:windowEnterAnimation">@anim/textbubble_in</item>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java index 6f4cfa9..fad6de9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java
@@ -82,10 +82,11 @@ if (!isUndoable) return; if (titles.length == 1) { - mSnackbarManager.showSnackbar(Snackbar - .make(titles[0], this, Snackbar.TYPE_ACTION, Snackbar.UMA_BOOKMARK_DELETE_UNDO) - .setTemplateText(mContext.getString(R.string.undo_bar_delete_message)) - .setAction(mContext.getString(R.string.undo), null)); + mSnackbarManager.showSnackbar( + Snackbar.make(titles[0], this, Snackbar.TYPE_ACTION, + Snackbar.UMA_BOOKMARK_DELETE_UNDO) + .setTemplateText(mContext.getString(R.string.delete_message)) + .setAction(mContext.getString(R.string.undo), null)); } else { mSnackbarManager.showSnackbar( Snackbar.make(String.format(Locale.getDefault(), "%d", titles.length), this,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index 14ab7b6..e113352 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -89,6 +89,7 @@ private CompositorView mCompositorView; private boolean mContentOverlayVisiblity = true; + private boolean mCanBeFocusable; private int mPendingFrameCount; @@ -817,9 +818,10 @@ } @Override - public void setContentOverlayVisibility(boolean show) { - if (show != mContentOverlayVisiblity) { + public void setContentOverlayVisibility(boolean show, boolean canBeFocusable) { + if (show != mContentOverlayVisiblity || canBeFocusable != mCanBeFocusable) { mContentOverlayVisiblity = show; + mCanBeFocusable = canBeFocusable; updateContentOverlayVisibility(mContentOverlayVisiblity); } } @@ -1019,8 +1021,8 @@ } } else { if (mView.getParent() == this) { - setFocusable(true); - setFocusableInTouchMode(true); + setFocusable(mCanBeFocusable); + setFocusableInTouchMode(mCanBeFocusable); if (webContents != null && !webContents.isDestroyed()) { getContentView().setVisibility(View.INVISIBLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java index 6486adc..ea485d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -764,6 +764,14 @@ } /** + * @return True if the host container can set itself as focusable e.g. for accessibility. + * Subclasses can override e.g. to provide a different default focused view. + */ + public boolean canHostBeFocusable() { + return true; + } + + /** * @param e The {@link MotionEvent} to consider. * @param offsets The current touch offsets that should be applied to the * {@link EventFilter}s.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java index d40da26a..0766793 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -809,7 +809,8 @@ onViewportChanged(); getActiveLayout().show(time(), animate); - mHost.setContentOverlayVisibility(getActiveLayout().shouldDisplayContentOverlay()); + mHost.setContentOverlayVisibility(getActiveLayout().shouldDisplayContentOverlay(), + getActiveLayout().canHostBeFocusable()); mHost.requestRender(); // Notify observers about the new scene.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerHost.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerHost.java index 73b543a..44fa199 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerHost.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerHost.java
@@ -86,8 +86,9 @@ /** * Sets the visibility of the content overlays. * @param show True if the content overlays should be shown. + * @param canBeFocusable Whether the host view can make itself focusable e.g. for accessibility. */ - void setContentOverlayVisibility(boolean show); + void setContentOverlayVisibility(boolean show, boolean canBeFocusable); /** * @return The {@link TitleCache} to use to store title bitmaps.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java index bfb5734..fabe543 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.contextual_suggestions; -import android.graphics.Bitmap; - import org.chromium.base.Callback; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -88,18 +86,27 @@ nativeFetchSuggestions(mNativeContextualSuggestionsBridge, url, callback); } - /** Fetches a thumbnail for the suggestion. */ - void fetchSuggestionImage(SnippetArticle suggestion, Callback<Bitmap> callback) { + /** + * Get the url of the image used for the given suggestion. + * + * @param suggestion The suggestion that the image url is for. + * @return The url for the image or null if one can't be found. + */ + String getImageUrl(SnippetArticle suggestion) { assert mNativeContextualSuggestionsBridge != 0; - nativeFetchSuggestionImage( - mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory, callback); + return nativeGetImageUrl(mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory); } - /** Fetches a favicon for the suggestion. */ - void fetchSuggestionFavicon(SnippetArticle suggestion, Callback<Bitmap> callback) { + /** + * Get the url of the favicon used for the given suggestion. + * + * @param suggestion The suggestion that the favicon url is for. + * @return The url for the image or null if one can't be found. + */ + String getFaviconUrl(SnippetArticle suggestion) { assert mNativeContextualSuggestionsBridge != 0; - nativeFetchSuggestionFavicon( - mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory, callback); + return nativeGetFaviconUrl( + mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory); } /** Requests the backend to clear state related to this bridge. */ @@ -157,10 +164,10 @@ private native void nativeDestroy(long nativeContextualSuggestionsBridge); private native void nativeFetchSuggestions(long nativeContextualSuggestionsBridge, String url, Callback<ContextualSuggestionsResult> callback); - private native void nativeFetchSuggestionImage( - long nativeContextualSuggestionsBridge, String suggestionId, Callback<Bitmap> callback); - private native void nativeFetchSuggestionFavicon( - long nativeContextualSuggestionsBridge, String suggestionId, Callback<Bitmap> callback); + private native String nativeGetImageUrl( + long nativeContextualSuggestionsBridge, String suggestionId); + private native String nativeGetFaviconUrl( + long nativeContextualSuggestionsBridge, String suggestionId); private native void nativeClearState(long nativeContextualSuggestionsBridge); private native void nativeReportEvent( long nativeContextualSuggestionsBridge, WebContents webContents, int eventId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImpl.java index f345ab3e..febd0af8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImpl.java
@@ -7,6 +7,10 @@ import android.graphics.Bitmap; import org.chromium.base.Callback; +import org.chromium.base.VisibleForTesting; +import org.chromium.base.task.PostTask; +import org.chromium.base.task.TaskTraits; +import org.chromium.chrome.browser.cached_image_fetcher.CachedImageFetcher; import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsBridge.ContextualSuggestionsResult; import org.chromium.chrome.browser.ntp.snippets.EmptySuggestionsSource; import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; @@ -19,6 +23,7 @@ class ContextualSuggestionsSourceImpl extends EmptySuggestionsSource implements ContextualSuggestionsSource { private ContextualSuggestionsBridge mBridge; + private CachedImageFetcher mCachedImageFetcher; /** * Creates a ContextualSuggestionsSource for getting contextual suggestions for the current @@ -28,6 +33,7 @@ */ public ContextualSuggestionsSourceImpl(Profile profile) { mBridge = new ContextualSuggestionsBridge(profile); + mCachedImageFetcher = CachedImageFetcher.getInstance(); } @Override @@ -37,19 +43,32 @@ @Override public void fetchSuggestionImage(SnippetArticle suggestion, Callback<Bitmap> callback) { - mBridge.fetchSuggestionImage(suggestion, callback); + String url = mBridge.getImageUrl(suggestion); + mCachedImageFetcher.fetchImage(url, callback); } @Override public void fetchContextualSuggestionImage( SnippetArticle suggestion, Callback<Bitmap> callback) { - mBridge.fetchSuggestionImage(suggestion, callback); + String url = mBridge.getImageUrl(suggestion); + if (url == null) { + PostTask.postTask(new TaskTraits(), () -> callback.onResult(null)); + return; + } + + mCachedImageFetcher.fetchImage(url, callback); } @Override public void fetchSuggestionFavicon(SnippetArticle suggestion, int minimumSizePx, int desiredSizePx, Callback<Bitmap> callback) { - mBridge.fetchSuggestionFavicon(suggestion, callback); + String url = mBridge.getFaviconUrl(suggestion); + if (url == null) { + PostTask.postTask(new TaskTraits(), () -> callback.onResult(null)); + return; + } + + mCachedImageFetcher.fetchImage(url, desiredSizePx, desiredSizePx, callback); } @Override @@ -66,4 +85,11 @@ public void clearState() { mBridge.clearState(); } + + @VisibleForTesting + ContextualSuggestionsSourceImpl( + ContextualSuggestionsBridge bridge, CachedImageFetcher cachedImageFethcer) { + mBridge = bridge; + mCachedImageFetcher = cachedImageFethcer; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java index 5e6a59c..e0c7821 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java
@@ -34,22 +34,17 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.chrome.browser.ChromeApplication; -import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.download.DownloadNotificationUmaHelper.UmaDownloadResumption; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory; import org.chromium.chrome.browser.init.BrowserParts; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.init.EmptyBrowserParts; -import org.chromium.chrome.browser.init.ServiceManagerStartupUtils; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.PendingState; import org.chromium.content_public.browser.BrowserStartupController; -import java.util.HashSet; -import java.util.Set; - /** * Class that spins up native when an interaction with a notification happens and passes the * relevant information on to native. @@ -202,10 +197,7 @@ @Override public boolean startServiceManagerOnly() { if (!LegacyHelpers.isLegacyDownload(id)) return false; - Set<String> features = new HashSet<String>(); - features.add(ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD); - features.add(ChromeFeatureList.NETWORK_SERVICE); - return ServiceManagerStartupUtils.canStartServiceManager(features) + return DownloadUtils.shouldStartServiceManagerOnly() && !ACTION_DOWNLOAD_OPEN.equals(intent.getAction()); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java index 265beeb..e3e5d66 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.download.ui.DownloadHistoryItemWrapper.OfflineItemWrapper; import org.chromium.chrome.browser.feature_engagement.ScreenshotTabObserver; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.init.ServiceManagerStartupUtils; import org.chromium.chrome.browser.media.MediaViewerUtils; import org.chromium.chrome.browser.offlinepages.DownloadUiActionFlags; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; @@ -81,9 +82,11 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; /** @@ -999,6 +1002,14 @@ && entry.isAutoResumable; } + /** @return Whether we should start service manager only, based off the features enabled. */ + public static boolean shouldStartServiceManagerOnly() { + Set<String> features = new HashSet<String>(); + features.add(ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD); + features.add(ChromeFeatureList.NETWORK_SERVICE); + return ServiceManagerStartupUtils.canStartServiceManager(features); + } + /** * Format the number of bytes into KB, or MB, or GB and return the corresponding string * resource. Uses default download-related set of strings.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java index 2e49528..0e9bd09 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java
@@ -27,7 +27,7 @@ public static String getTemplateTextFor(Collection<OfflineItem> items) { Context context = ContextUtils.getApplicationContext(); return items.size() == 1 - ? context.getString(R.string.undo_bar_delete_message) + ? context.getString(R.string.delete_message) : context.getString(R.string.undo_bar_multiple_downloads_delete_message); } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java index 80a55b62e..a21f939 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
@@ -10,6 +10,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask; import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask.StartBeforeNativeResult; +import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.background_task_scheduler.TaskParameters; import org.chromium.components.download.DownloadTaskType; @@ -22,6 +23,8 @@ * Entry point for the download service to perform desired action when the task is fired by the * scheduler. The scheduled task is executed for the regular profile and also for incognito profile * if an incognito profile exists. + * TODO(shaktisahu): Since we probably don't need to run tasks for incognito profile, cleanup this + * class and remove any reference to profiles. */ @JNINamespace("download::android") public class DownloadBackgroundTask extends NativeBackgroundTask { @@ -37,6 +40,9 @@ // Keeps track of in progress tasks which haven't invoked their {@link TaskFinishedCallback}s. private Map<Integer, PendingTaskCounter> mPendingTaskCounters = new HashMap<>(); + @DownloadTaskType + private int mCurrentTaskType; + @Override protected @StartBeforeNativeResult int onStartTaskBeforeNativeLoaded( Context context, TaskParameters taskParameters, TaskFinishedCallback callback) { @@ -59,34 +65,42 @@ // In case of future upgrades, we would need to build an intent for the old version and // validate that this code still works. This would require decoupling this immediate class // from native as well. - @DownloadTaskType - final int taskType = - taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE); + mCurrentTaskType = taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE); Callback<Boolean> wrappedCallback = new Callback<Boolean>() { @Override public void onResult(Boolean needsReschedule) { - if (mPendingTaskCounters.get(taskType) == null) return; + if (mPendingTaskCounters.get(mCurrentTaskType) == null) return; boolean noPendingCallbacks = - decrementPendingCallbackCount(taskType, needsReschedule); + decrementPendingCallbackCount(mCurrentTaskType, needsReschedule); if (noPendingCallbacks) { - callback.taskFinished(mPendingTaskCounters.get(taskType).needsReschedule); - mPendingTaskCounters.remove(taskType); + callback.taskFinished( + mPendingTaskCounters.get(mCurrentTaskType).needsReschedule); + mPendingTaskCounters.remove(mCurrentTaskType); } } }; - Profile profile = Profile.getLastUsedProfile().getOriginalProfile(); - incrementPendingCallbackCount(taskType); - nativeStartBackgroundTask(profile, taskType, wrappedCallback); + Profile profile = supportsServiceManagerOnly() + ? null + : Profile.getLastUsedProfile().getOriginalProfile(); + incrementPendingCallbackCount(mCurrentTaskType); + nativeStartBackgroundTask(profile, mCurrentTaskType, wrappedCallback); - if (profile.hasOffTheRecordProfile()) { - incrementPendingCallbackCount(taskType); - nativeStartBackgroundTask(profile.getOffTheRecordProfile(), taskType, wrappedCallback); + if (profile != null && profile.hasOffTheRecordProfile()) { + incrementPendingCallbackCount(mCurrentTaskType); + nativeStartBackgroundTask( + profile.getOffTheRecordProfile(), mCurrentTaskType, wrappedCallback); } } + @Override + protected boolean supportsServiceManagerOnly() { + return mCurrentTaskType == DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK + && DownloadUtils.shouldStartServiceManagerOnly(); + } + private void incrementPendingCallbackCount(@DownloadTaskType int taskType) { PendingTaskCounter taskCounter = mPendingTaskCounters.containsKey(taskType) ? mPendingTaskCounters.get(taskType) @@ -117,10 +131,12 @@ int taskType = taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE); mPendingTaskCounters.remove(taskType); - Profile profile = Profile.getLastUsedProfile().getOriginalProfile(); + Profile profile = supportsServiceManagerOnly() + ? null + : Profile.getLastUsedProfile().getOriginalProfile(); boolean needsReschedule = nativeStopBackgroundTask(profile, taskType); - if (profile.hasOffTheRecordProfile()) { + if (profile != null && profile.hasOffTheRecordProfile()) { needsReschedule |= nativeStopBackgroundTask(profile.getOffTheRecordProfile(), taskType); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java index e54d9e3..3b71fa1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java
@@ -29,6 +29,7 @@ public static final String EXTRA_TASK_TYPE = "extra_task_type"; static final long TWELVE_HOURS_IN_SECONDS = TimeUnit.HOURS.toSeconds(12); static final long FIVE_MINUTES_IN_SECONDS = TimeUnit.MINUTES.toSeconds(5); + static final long ONE_DAY_IN_SECONDS = TimeUnit.DAYS.toSeconds(1); @CalledByNative private static void scheduleTask(@DownloadTaskType int taskType, @@ -69,6 +70,8 @@ 2 * FIVE_MINUTES_IN_SECONDS); scheduleTask(DownloadTaskType.CLEANUP_TASK, false, false, 0, TWELVE_HOURS_IN_SECONDS, 2 * TWELVE_HOURS_IN_SECONDS); + scheduleTask(DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK, false, false, 0, + FIVE_MINUTES_IN_SECONDS, ONE_DAY_IN_SECONDS); } private static int getTaskId(@DownloadTaskType int taskType) { @@ -77,6 +80,8 @@ return TaskIds.DOWNLOAD_SERVICE_JOB_ID; case DownloadTaskType.CLEANUP_TASK: return TaskIds.DOWNLOAD_CLEANUP_JOB_ID; + case DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK: + return TaskIds.DOWNLOAD_AUTO_RESUMPTION_JOB_ID; default: assert false; return -1; @@ -85,9 +90,16 @@ private static int getRequiredNetworkType( @DownloadTaskType int taskType, boolean requiresUnmeteredNetwork) { - if (taskType != DownloadTaskType.DOWNLOAD_TASK) return TaskInfo.NETWORK_TYPE_NONE; - - return requiresUnmeteredNetwork ? TaskInfo.NETWORK_TYPE_UNMETERED - : TaskInfo.NETWORK_TYPE_ANY; + switch (taskType) { + case DownloadTaskType.CLEANUP_TASK: + return TaskInfo.NETWORK_TYPE_NONE; + case DownloadTaskType.DOWNLOAD_TASK: // intentional fall-through + case DownloadTaskType.DOWNLOAD_AUTO_RESUMPTION_TASK: + return requiresUnmeteredNetwork ? TaskInfo.NETWORK_TYPE_UNMETERED + : TaskInfo.NETWORK_TYPE_ANY; + default: + assert false; + return TaskInfo.NETWORK_TYPE_ANY; + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index a574193..c5461e8d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -471,7 +471,8 @@ String snackbarText = singleItemDeleted ? items.get(0).getDisplayFileName() : String.format(Locale.getDefault(), "%d", items.size()); - int snackbarTemplateId = singleItemDeleted ? R.string.undo_bar_delete_message + int snackbarTemplateId = singleItemDeleted + ? R.string.delete_message : R.string.undo_bar_multiple_downloads_delete_message; Snackbar snackbar = Snackbar.make(snackbarText, mUndoDeletionSnackbarController,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java index e4bb173..02e33c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -222,11 +222,25 @@ recordSelectionCountHistorgram("Remove"); recordUserActionWithOptionalSearch("RemoveSelected"); + int numItemsRemoved = 0; + HistoryItem lastItemRemoved = null; for (HistoryItem historyItem : mSelectionDelegate.getSelectedItems()) { mHistoryAdapter.markItemForRemoval(historyItem); + numItemsRemoved++; + lastItemRemoved = historyItem; } + mHistoryAdapter.removeItems(); mSelectionDelegate.clearSelection(); + + if (numItemsRemoved == 1) { + assert lastItemRemoved != null; + announceItemRemoved(lastItemRemoved); + } else if (numItemsRemoved > 1) { + mRecyclerView.announceForAccessibility(mRecyclerView.getContext().getString( + R.string.multiple_history_items_deleted, numItemsRemoved)); + } + return true; } else if (item.getItemId() == R.id.search_menu_id) { mHistoryAdapter.removeHeader(); @@ -285,6 +299,12 @@ } mHistoryAdapter.markItemForRemoval(item); mHistoryAdapter.removeItems(); + announceItemRemoved(item); + } + + private void announceItemRemoved(HistoryItem item) { + mRecyclerView.announceForAccessibility( + mRecyclerView.getContext().getString(R.string.delete_message, item.getTitle())); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java index 59e6dd41..a489f1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -23,7 +23,6 @@ * Container that holds the {@link UrlBar} and SSL state related with the current {@link Tab}. */ public interface LocationBar extends UrlBarDelegate { - /** * Handles native dependent initialization for this class. */ @@ -134,7 +133,7 @@ /** * Updates the security icon displayed in the LocationBar. */ - void updateSecurityIcon(); + void updateStatusIcon(); /** * @return The {@link ViewGroup} that this container holds.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index e8044731..5bae736 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -247,8 +247,7 @@ } @Override - public void initializeControls(WindowDelegate windowDelegate, - WindowAndroid windowAndroid) { + public void initializeControls(WindowDelegate windowDelegate, WindowAndroid windowAndroid) { mWindowDelegate = windowDelegate; mWindowAndroid = windowAndroid; @@ -331,8 +330,7 @@ // This will only be called once at least one tab exists, and the tab model is told to // update its state. During Chrome initialization the tab model update happens after the // call to onNativeLibraryReady, so this assert will not fire. - assert mNativeInitialized - : "Setting Autocomplete Profile before native side initialized"; + assert mNativeInitialized : "Setting Autocomplete Profile before native side initialized"; mAutocompleteCoordinator.setAutocompleteProfile(profile); mOmniboxPrerender.initializeForProfile(profile); } @@ -581,8 +579,8 @@ * Updates the security icon displayed in the LocationBar. */ @Override - public void updateSecurityIcon() { - mStatusViewCoordinator.updateSecurityIcon(); + public void updateStatusIcon() { + mStatusViewCoordinator.updateStatusIcon(); // Update the URL in case the scheme change triggers a URL emphasis change. setUrlToPageUrl(); } @@ -622,21 +620,21 @@ int widthMeasureSpec; int heightMeasureSpec; if (childLayoutParams.width == LayoutParams.WRAP_CONTENT) { - widthMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredWidth(), MeasureSpec.AT_MOST); + widthMeasureSpec = + MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST); } else if (childLayoutParams.width == LayoutParams.MATCH_PARENT) { - widthMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredWidth(), MeasureSpec.EXACTLY); + widthMeasureSpec = + MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY); } else { widthMeasureSpec = MeasureSpec.makeMeasureSpec( childLayoutParams.width, MeasureSpec.EXACTLY); } if (childLayoutParams.height == LayoutParams.WRAP_CONTENT) { - heightMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredHeight(), MeasureSpec.AT_MOST); + heightMeasureSpec = + MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST); } else if (childLayoutParams.height == LayoutParams.MATCH_PARENT) { - heightMeasureSpec = MeasureSpec.makeMeasureSpec( - getMeasuredHeight(), MeasureSpec.EXACTLY); + heightMeasureSpec = + MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY); } else { heightMeasureSpec = MeasureSpec.makeMeasureSpec( childLayoutParams.height, MeasureSpec.EXACTLY); @@ -782,7 +780,6 @@ }); } - @Override public void onClick(View v) { if (v == mDeleteButton) { @@ -947,7 +944,7 @@ public void updateLoadingState(boolean updateUrl) { if (updateUrl) setUrlToPageUrl(); updateNavigationButton(); - mStatusViewCoordinator.updateSecurityIcon(); + mStatusViewCoordinator.updateStatusIcon(); } /** @return The current active {@link Tab}. */ @@ -1070,10 +1067,10 @@ } @Override - public void setTitleToPageTitle() { } + public void setTitleToPageTitle() {} @Override - public void setShowTitle(boolean showTitle) { } + public void setShowTitle(boolean showTitle) {} @Override public WindowAndroid getWindowAndroid() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java index 978e64e..bfae132 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -23,7 +23,6 @@ private boolean mVerboseStatusSpaceAvailable; private boolean mPageIsPreview; private boolean mPageIsOffline; - private boolean mTabletMode; private int mUrlMinWidth; private int mSeparatorMinWidth; @@ -110,13 +109,6 @@ } /** - * Toggle tablet mode. - */ - void setTabletMode(boolean isTablet) { - mTabletMode = isTablet; - } - - /** * Specify object to receive status click events. * * @param listener Specifies target object to receive events. @@ -265,7 +257,7 @@ * - not shown if URL is focused. */ private void updateLocationBarIcon() { - if (mUrlHasFocus && mTabletMode) { + if (mUrlHasFocus) { mModel.set(StatusProperties.STATUS_ICON_RES, mNavigationIconRes); mModel.set(StatusProperties.STATUS_ICON_TINT_RES, mNavigationIconTintRes); mModel.set(StatusProperties.STATUS_ICON_DESCRIPTION_RES,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java index 8e4c04b..dcecd81 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
@@ -73,9 +73,6 @@ mMediator.setVerboseStatusTextMinWidth( res.getDimensionPixelSize(R.dimen.location_bar_min_verbose_status_text_width)); - - mMediator.setTabletMode(mIsTablet); - mMediator.setNavigationButtonType(NavigationButtonType.PAGE); } /** @@ -110,13 +107,13 @@ // TODO(ender): remove this once icon selection has complete set of // corresponding properties (for tinting etc). - updateSecurityIcon(); + updateStatusIcon(); } /** * Updates the security icon displayed in the LocationBar. */ - public void updateSecurityIcon() { + public void updateStatusIcon() { mMediator.setSecurityIconResource(mToolbarDataProvider.getSecurityIconResource(mIsTablet)); mMediator.setSecurityIconTint(mToolbarDataProvider.getSecurityIconColorStateList()); mMediator.setSecurityIconDescription(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index cae5c8c..7ff42bb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -127,7 +127,6 @@ * Handle UI updates of menu icons. Only applicable for phones. */ public interface MenuDelegatePhone { - /** * Called when current tab's loading status changes. * @@ -408,13 +407,13 @@ if (mLocationBarModel.getTab() == null) return; assert tab == mLocationBarModel.getTab(); - mLocationBar.updateSecurityIcon(); + mLocationBar.updateStatusIcon(); mLocationBar.setUrlToPageUrl(); } @Override public void didReloadLoFiImages(Tab tab) { - mLocationBar.updateSecurityIcon(); + mLocationBar.updateStatusIcon(); } @Override @@ -459,7 +458,7 @@ // finishes loading. If this is a preview, update the security icon which will // also update the verbose status view to make sure the "Lite" badge is // displayed. - mLocationBar.updateSecurityIcon(); + mLocationBar.updateStatusIcon(); PreviewsUma.recordLitePageAtLoadFinish( PreviewsAndroidBridge.getInstance().getPreviewsType( tab.getWebContents())); @@ -603,7 +602,7 @@ // Some previews are not fully decided until the page commits. If this // is a preview, update the security icon which will also update the verbose // status view to make sure the "Lite" badge is displayed. - mLocationBar.updateSecurityIcon(); + mLocationBar.updateStatusIcon(); PreviewsUma.recordLitePageAtCommit( PreviewsAndroidBridge.getInstance().getPreviewsType( tab.getWebContents()), @@ -1402,8 +1401,9 @@ if (mControlsVisibilityDelegate == null) return; if (hasFocus) { - mFullscreenFocusToken = mControlsVisibilityDelegate - .showControlsPersistentAndClearOldToken(mFullscreenFocusToken); + mFullscreenFocusToken = + mControlsVisibilityDelegate.showControlsPersistentAndClearOldToken( + mFullscreenFocusToken); } else { mControlsVisibilityDelegate.releasePersistentShowingToken(mFullscreenFocusToken); } @@ -1544,8 +1544,7 @@ * @param activityCreationTimeMs The time of creation for the activity this toolbar belongs to. * @param activityName Simple class name for the activity this toolbar belongs to. */ - public void onDeferredStartup(final long activityCreationTimeMs, - final String activityName) { + public void onDeferredStartup(final long activityCreationTimeMs, final String activityName) { // Record startup performance statistics long elapsedTime = SystemClock.elapsedRealtime() - activityCreationTimeMs; if (elapsedTime < RECORD_UMA_PERFORMANCE_METRICS_DELAY_MS) { @@ -1598,8 +1597,8 @@ private void updateBookmarkButtonStatus() { assert mToolbarInflationComplete; Tab currentTab = mLocationBarModel.getTab(); - boolean isBookmarked = currentTab != null - && currentTab.getBookmarkId() != Tab.INVALID_BOOKMARK_ID; + boolean isBookmarked = + currentTab != null && currentTab.getBookmarkId() != Tab.INVALID_BOOKMARK_ID; boolean editingAllowed = currentTab == null || mBookmarkBridge == null || mBookmarkBridge.isEditBookmarksEnabled(); mToolbar.updateBookmarkButton(isBookmarked, editingAllowed);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java index 5582c02b..f4795047 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -334,7 +334,7 @@ mTitleBar.setLayoutParams(lp); mTitleBar.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.custom_tabs_title_text_size)); - updateSecurityIcon(); + updateStatusIcon(); } else { assert false : "Unreached state"; } @@ -387,7 +387,7 @@ setUrlBarHidden(false); } } - updateSecurityIcon(); + updateStatusIcon(); } @VisibleForTesting @@ -460,7 +460,7 @@ @Override public void updateLoadingState(boolean updateUrl) { if (updateUrl) setUrlToPageUrl(); - updateSecurityIcon(); + updateStatusIcon(); } @Override @@ -476,7 +476,7 @@ @Override public void updateVisualsForState() { Resources resources = getResources(); - updateSecurityIcon(); + updateStatusIcon(); updateButtonsTint(); if (mUrlCoordinator.setUseDarkTextColors(mUseDarkColors)) { setUrlToPageUrl(); @@ -485,7 +485,7 @@ int titleTextColor = mUseDarkColors ? ApiCompatibilityUtils.getColor(resources, R.color.url_emphasis_default_text) : ApiCompatibilityUtils.getColor( - resources, R.color.url_emphasis_light_default_text); + resources, R.color.url_emphasis_light_default_text); mTitleBar.setTextColor(titleTextColor); if (getProgressBar() != null) { @@ -537,7 +537,7 @@ public void initializeControls(WindowDelegate windowDelegate, WindowAndroid windowAndroid) {} @Override - public void updateSecurityIcon() { + public void updateStatusIcon() { if (mState == STATE_TITLE_ONLY) return; int securityIconResource = getToolbarDataProvider().getSecurityIconResource(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 69c89632..b57f70de 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -153,6 +153,7 @@ private boolean mForceTextureCapture; private boolean mUseLightDrawablesForTextureCapture; private boolean mLightDrawablesUsedForLastTextureCapture; + private int mTabCountForLastTextureCapture; @ViewDebug.ExportedProperty(category = "chrome") private boolean mAnimateNormalToolbar; @@ -654,7 +655,7 @@ private int getViewBoundsLeftOfLocationBar(@VisualState int visualState) { // Uses getMeasuredWidth()s instead of getLeft() because this is called in onMeasure // and the layout values have not yet been set. - if (visualState == VisualState.NEW_TAB_NORMAL) { + if (visualState == VisualState.NEW_TAB_NORMAL && mTabSwitcherState == STATIC_TAB) { return mToolbarSidePadding; } else if (ApiCompatibilityUtils.isLayoutRtl(this)) { return getBoundsAfterAccountingForRightButtons(); @@ -682,7 +683,7 @@ private int getViewBoundsRightOfLocationBar(@VisualState int visualState) { // Uses getMeasuredWidth()s instead of getRight() because this is called in onMeasure // and the layout values have not yet been set. - if (visualState == VisualState.NEW_TAB_NORMAL) { + if (visualState == VisualState.NEW_TAB_NORMAL && mTabSwitcherState == STATIC_TAB) { return getMeasuredWidth() - mToolbarSidePadding; } else if (ApiCompatibilityUtils.isLayoutRtl(this)) { return getMeasuredWidth() - getBoundsAfterAccountingForLeftButton(); @@ -1297,6 +1298,10 @@ mLightDrawablesUsedForLastTextureCapture = mUseLightDrawablesForTextureCapture; + if (mTabSwitcherAnimationTabStackDrawable != null && mToggleTabStackButton != null) { + mTabCountForLastTextureCapture = mTabSwitcherAnimationTabStackDrawable.getTabCount(); + } + canvas.restore(); } @@ -1420,6 +1425,7 @@ int rightDelta = getViewBoundsRightOfLocationBar(mVisualState) - mUnfocusedLocationBarLayoutLeft - mUnfocusedLocationBarLayoutWidth; float inversePercent = 1f - mUrlExpansionPercent; + locationBarClipLeft += leftDelta * inversePercent; locationBarClipRight -= rightDelta * inversePercent; @@ -1524,9 +1530,17 @@ public boolean setForceTextureCapture(boolean forceTextureCapture) { if (forceTextureCapture) { setUseLightDrawablesForTextureCapture(); - // Only force a texture capture if the tint for the toolbar drawables is changing. + // Only force a texture capture if the tint for the toolbar drawables is changing or + // if the tab count has changed since the last texture capture. mForceTextureCapture = mLightDrawablesUsedForLastTextureCapture != mUseLightDrawablesForTextureCapture; + + if (mTabSwitcherAnimationTabStackDrawable != null && mToggleTabStackButton != null) { + mForceTextureCapture = mForceTextureCapture + || mTabCountForLastTextureCapture + != mTabSwitcherAnimationTabStackDrawable.getTabCount(); + } + return mForceTextureCapture; } @@ -1620,7 +1634,7 @@ exitAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - updateViewsForTabSwitcherMode(); + onExitTabSwitcherAnimationEnd(); } }); @@ -1646,19 +1660,28 @@ @Override public void onAnimationEnd(Animator animation) { mDelayedTabSwitcherModeAnimation = null; - updateViewsForTabSwitcherMode(); + onExitTabSwitcherAnimationEnd(); } }); return exitAnimation; } + private void onExitTabSwitcherAnimationEnd() { + updateViewsForTabSwitcherMode(); + + // Request a texture update to ensure a texture is captured before the user + // re-enters the tab switcher. + mLayoutUpdateHost.requestUpdate(); + } + @Override public void setTextureCaptureMode(boolean textureMode) { assert mTextureCaptureMode != textureMode; mTextureCaptureMode = textureMode; if (mTextureCaptureMode) { - if (!hideShadowForIncognitoNtp() && !hideShadowForInterstitial()) { + if (!hideShadowForIncognitoNtp() && !hideShadowForInterstitial() + && !hideShadowForRegularNtpTextureCapture()) { mToolbarShadow.setVisibility(VISIBLE); } mPreTextureCaptureAlpha = getAlpha(); @@ -1673,6 +1696,11 @@ } } + private boolean hideShadowForRegularNtpTextureCapture() { + return !isIncognito() && NewTabPage.isNTPUrl(getToolbarDataProvider().getCurrentUrl()) + && mNtpSearchBoxScrollPercent < 1.f; + } + // TODO(dtrainor): This is always true when in the tab switcher (crbug.com/710750). private boolean isTabSwitcherAnimationRunning() { return mTabSwitcherState == ENTERING_TAB_SWITCHER @@ -2267,7 +2295,6 @@ // These are used to skip setting state unnecessarily while in the tab switcher. boolean inOrEnteringStaticTab = mTabSwitcherState == STATIC_TAB || mTabSwitcherState == EXITING_TAB_SWITCHER; - boolean inOrEnteringTabSwitcher = !inOrEnteringStaticTab; @VisualState int newVisualState = computeVisualState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java index 2e9a4ab..50bfd31 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java
@@ -160,6 +160,13 @@ } @Override + public boolean canHostBeFocusable() { + // TODO(https://crbug.com/918171): Consider fine-tuning accessibility support for the + // overview list layout. + return false; + } + + @Override public void setTabModelSelector( TabModelSelector tabModelSelector, TabContentManager tabContentManager) { super.setTabModelSelector(tabModelSelector, tabContentManager);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 884a3e3..0474fe5d 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -814,6 +814,9 @@ <message name="IDS_ANDROID_HISTORY_BLOCKED_SITE" desc="The text displayed in the history page indicating that a visit to a web site was blocked due to an administrator policy."> Blocked site </message> + <message name="IDS_MULTIPLE_HISTORY_ITEMS_DELETED" desc="Accessibility announcement when multiple browsing history items have been deleted."> + <ph name="NUMBER_OF_ITEMS">%1$s<ex>3</ex></ph> items deleted + </message> <message name="IDS_USAGE_AND_CRASH_REPORTS_TITLE_LEGACY" desc="Title for 'Usage and crash reports' preference"> Usage and crash reports @@ -3408,8 +3411,8 @@ <message name="IDS_UNDO_BAR_CLOSE_ALL_MESSAGE" desc="Message shown when you can undo a close all tabs action."> <ph name="TAB_COUNT">%1$s<ex>3</ex></ph> tabs closed </message> - <message name="IDS_UNDO_BAR_DELETE_MESSAGE" desc="Message shown when you can undo a delete action."> - Deleted <ph name="BOOKMARK_TITLE">%1$s<ex>YouTube</ex></ph> + <message name="IDS_DELETE_MESSAGE" desc="Message shown or announced when an item has been deleted."> + Deleted <ph name="ITEM_TITLE">%1$s<ex>YouTube</ex></ph> </message> <message name="IDS_UNDO_BAR_MULTIPLE_DELETE_MESSAGE" desc="Message shown when you can undo several bookmark delete actions."> <ph name="NUMBER_OF_BOOKMARKS">%1$s<ex>3</ex></ph> bookmarks deleted
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 99909c3..90a1aad5 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -2385,6 +2385,7 @@ "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityDisclosureControllerTest.java", "junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorderTest.java", "junit/src/org/chromium/chrome/browser/cached_image_fetcher/CachedImageFetcherImplTest.java", + "junit/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImplTest.java", "junit/src/org/chromium/chrome/browser/cached_image_fetcher/InMemoryCachedImageFetcherTest.java", "junit/src/org/chromium/chrome/browser/compositor/CompositorSurfaceManagerImplTest.java", "junit/src/org/chromium/chrome/browser/compositor/EventOffsetHandlerTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockLayoutHost.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockLayoutHost.java index e5280d8..e7afc5b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockLayoutHost.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockLayoutHost.java
@@ -32,10 +32,10 @@ } @Override - public void remove(int tabId) { } + public void remove(int tabId) {} @Override - public void clearExcept(int tabId) { } + public void clearExcept(int tabId) {} } private final MockTitleCache mMockTitleCache = new MockTitleCache(); @@ -49,16 +49,16 @@ } @Override - public void requestRender() { } + public void requestRender() {} @Override - public void onCompositorLayout() { } + public void onCompositorLayout() {} @Override public void didSwapFrame(int pendingFrameCount) {} @Override - public void onSurfaceCreated() { } + public void onSurfaceCreated() {} @Override public void onSurfaceResized(int width, int height) {} @@ -118,13 +118,13 @@ } @Override - public void pushDebugRect(Rect rect, int color) { } + public void pushDebugRect(Rect rect, int color) {} @Override - public void loadPersitentTextureDataIfNeeded() { } + public void loadPersitentTextureDataIfNeeded() {} @Override - public void setContentOverlayVisibility(boolean visible) { } + public void setContentOverlayVisibility(boolean visible, boolean canBeFocusable) {} @Override public TitleCache getTitleCache() { @@ -142,10 +142,10 @@ } @Override - public void invalidateAccessibilityProvider() { } + public void invalidateAccessibilityProvider() {} @Override - public void onContentChanged() { } + public void onContentChanged() {} @Override public int getBrowserControlsBackgroundColor() {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImplTest.java new file mode 100644 index 0000000..6643969 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsSourceImplTest.java
@@ -0,0 +1,119 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.contextual_suggestions; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import android.graphics.Bitmap; +import android.support.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; + +import org.chromium.base.Callback; +import org.chromium.base.task.test.BackgroundShadowAsyncTask; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.cached_image_fetcher.CachedImageFetcher; +import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulatorTest.ShadowUrlUtilities; +import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; + +/** + * Unit tests for CachedImageFetcherImpl. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, + shadows = {ShadowUrlUtilities.class, BackgroundShadowAsyncTask.class}) +public class ContextualSuggestionsSourceImplTest { + private static final String IMAGE_URL = "http://foo.com/bar.png"; + private static final int FAVICON_DIMENSION = 100; + + ContextualSuggestionsSourceImpl mContextualSuggestionsSourceImpl; + + @Mock + ContextualSuggestionsBridge mBridge; + + @Mock + CachedImageFetcher mCachedImageFetcher; + + @Mock + Bitmap mBitmap; + + @Captor + ArgumentCaptor<Callback<Bitmap>> mCallbackCaptor; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mContextualSuggestionsSourceImpl = + new ContextualSuggestionsSourceImpl(mBridge, mCachedImageFetcher); + // Answer with or without width/height. + doAnswer((InvocationOnMock invocation) -> { + mCallbackCaptor.getValue().onResult(mBitmap); + return null; + }) + .when(mCachedImageFetcher) + .fetchImage(any(), mCallbackCaptor.capture()); + } + + @Test + @SmallTest + public void testFetchContextualSuggestionImage() throws Exception { + doReturn(IMAGE_URL).when(mBridge).getImageUrl(any()); + + SnippetArticle article = mock(SnippetArticle.class); + mContextualSuggestionsSourceImpl.fetchContextualSuggestionImage( + article, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); + BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); + } + + @Test + @SmallTest + public void testFetchContextualSuggestionImageWhenNullUrlIsReturned() throws Exception { + doReturn(null).when(mBridge).getImageUrl(any()); + + SnippetArticle article = mock(SnippetArticle.class); + mContextualSuggestionsSourceImpl.fetchContextualSuggestionImage( + article, (Bitmap bitmap) -> { assertEquals(bitmap, null); }); + BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); + } + + @Test + @SmallTest + public void testFetchContextualSuggestionFavicon() throws Exception { + doReturn(IMAGE_URL).when(mBridge).getFaviconUrl(any()); + + SnippetArticle article = mock(SnippetArticle.class); + mContextualSuggestionsSourceImpl.fetchSuggestionFavicon(article, FAVICON_DIMENSION, + FAVICON_DIMENSION, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); + BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); + } + + @Test + @SmallTest + public void testFetchContextualSuggestionFaviconNullUrlIsReturned() throws Exception { + doReturn(null).when(mBridge).getFaviconUrl(any()); + + SnippetArticle article = mock(SnippetArticle.class); + mContextualSuggestionsSourceImpl.fetchSuggestionFavicon(article, FAVICON_DIMENSION, + FAVICON_DIMENSION, (Bitmap bitmap) -> { assertEquals(bitmap, null); }); + BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); + } +} \ No newline at end of file
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni index fe21a31b..f94d61e6 100644 --- a/chrome/android/trichrome.gni +++ b/chrome/android/trichrome.gni
@@ -8,9 +8,20 @@ import("//build/config/android/rules.gni") import("//chrome/android/chrome_public_apk_tmpl.gni") -trichrome_library_package = "org.chromium.trichromelibrary" -trichrome_certdigest = - "1975b2f17177bc89a5dff31f9e64a6cae281a53dc1d1d59b1d147fe1c82afa00" +if (!defined(default_trichrome_certdigest)) { + default_trichrome_certdigest = + "32a2fc74d731105859e5a85df16d95f102d85b22099b8064c5d8915c61dad1e0" +} + +declare_args() { + # The package name for the Trichrome static shared library on Android. + trichrome_library_package = "org.chromium.trichromelibrary" + + # The SHA256 certificate digest for the Trichrome static shared library on + # Android. You can use "apksigner verify --print-certs" on the signed APK to + # calculate the correct digest. + trichrome_certdigest = default_trichrome_certdigest +} trichrome_jinja_variables = [ "min_sdk_version=28",
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png b/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png deleted file mode 100644 index 698ea8b..0000000 --- a/chrome/app/theme/default_100_percent/legacy/favicon_laptop.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_phone.png b/chrome/app/theme/default_100_percent/legacy/favicon_phone.png deleted file mode 100644 index ab57626..0000000 --- a/chrome/app/theme/default_100_percent/legacy/favicon_phone.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png b/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png deleted file mode 100644 index c1458f1..0000000 --- a/chrome/app/theme/default_100_percent/legacy/favicon_tablet.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png b/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png deleted file mode 100644 index 5ac0165c..0000000 --- a/chrome/app/theme/default_200_percent/legacy/favicon_laptop.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_phone.png b/chrome/app/theme/default_200_percent/legacy/favicon_phone.png deleted file mode 100644 index 7a83337..0000000 --- a/chrome/app/theme/default_200_percent/legacy/favicon_phone.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png b/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png deleted file mode 100644 index ac453a6..0000000 --- a/chrome/app/theme/default_200_percent/legacy/favicon_tablet.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 2335092..5b66242e 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -164,11 +164,6 @@ <structure type="chrome_scaled_image" name="IDR_INFOBAR_3D_BLOCKED" file="common/infobar_3d_blocked.png" /> <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT" file="common/input_alert.png" /> <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT_MENU" file="common/input_alert_menu.png" /> - <if expr="is_macosx"> - <structure type="chrome_scaled_image" name="IDR_LAPTOP_FAVICON" file="legacy/favicon_laptop.png" /> - <structure type="chrome_scaled_image" name="IDR_PHONE_FAVICON" file="legacy/favicon_phone.png" /> - <structure type="chrome_scaled_image" name="IDR_TABLET_FAVICON" file="legacy/favicon_tablet.png" /> - </if> <if expr="enable_service_discovery"> <structure type="chrome_scaled_image" name="IDR_LOCAL_DISCOVERY_CLOUDPRINT_ICON" file="common/cloudprint.png" /> </if>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 47c0c5b4..5bd63ba 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -5096,6 +5096,7 @@ if (is_android) { deps += [ "//chrome/browser/ui/webui/eoc_internals:mojo_bindings_js", + "//chrome/browser/ui/webui/feed_internals:mojo_bindings_js", "//chrome/browser/ui/webui/snippets_internals:mojo_bindings_js", ] } else {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index decb45e1..eed68bc 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2611,6 +2611,10 @@ flag_descriptions::kExperimentalAccessibilityFeaturesName, flag_descriptions::kExperimentalAccessibilityFeaturesDescription, kOsCrOS, SINGLE_VALUE_TYPE(::switches::kEnableExperimentalAccessibilityFeatures)}, + {"enable-experimental-accessibility-labels", + flag_descriptions::kExperimentalAccessibilityLabelsName, + flag_descriptions::kExperimentalAccessibilityLabelsDescription, kOsAll, + SINGLE_VALUE_TYPE(::switches::kEnableExperimentalAccessibilityLabels)}, #if defined(OS_CHROMEOS) {"opt-in-ime-menu", flag_descriptions::kEnableImeMenuName, flag_descriptions::kEnableImeMenuDescription, kOsCrOS,
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc index 37342f7..3738ef1 100644 --- a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc +++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
@@ -114,30 +114,27 @@ ScopedJavaGlobalRef<jobject>(j_callback))); } -void ContextualSuggestionsBridge::FetchSuggestionImage( +base::android::ScopedJavaLocalRef<jstring> +ContextualSuggestionsBridge::GetImageUrl( JNIEnv* env, const JavaParamRef<jobject>& obj, - const JavaParamRef<jstring>& j_suggestion_id, - const JavaParamRef<jobject>& j_callback) { + const JavaParamRef<jstring>& j_suggestion_id) { std::string suggestion_id(ConvertJavaStringToUTF8(env, j_suggestion_id)); - service_proxy_->FetchContextualSuggestionImage( - suggestion_id, - base::BindOnce(&ContextualSuggestionsBridge::OnImageFetched, - weak_ptr_factory_.GetWeakPtr(), - ScopedJavaGlobalRef<jobject>(j_callback))); + std::string image_url = + service_proxy_->GetContextualSuggestionImageUrl(suggestion_id); + return image_url.empty() ? nullptr : ConvertUTF8ToJavaString(env, image_url); } -void ContextualSuggestionsBridge::FetchSuggestionFavicon( +base::android::ScopedJavaLocalRef<jstring> +ContextualSuggestionsBridge::GetFaviconUrl( JNIEnv* env, const JavaParamRef<jobject>& obj, - const JavaParamRef<jstring>& j_suggestion_id, - const JavaParamRef<jobject>& j_callback) { + const JavaParamRef<jstring>& j_suggestion_id) { std::string suggestion_id(ConvertJavaStringToUTF8(env, j_suggestion_id)); - service_proxy_->FetchContextualSuggestionFavicon( - suggestion_id, - base::BindOnce(&ContextualSuggestionsBridge::OnImageFetched, - weak_ptr_factory_.GetWeakPtr(), - ScopedJavaGlobalRef<jobject>(j_callback))); + std::string favicon_url = + service_proxy_->GetContextualSuggestionFaviconUrl(suggestion_id); + return favicon_url.empty() ? nullptr + : ConvertUTF8ToJavaString(env, favicon_url); } void ContextualSuggestionsBridge::ClearState(JNIEnv* env,
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h index 27249fa..a9ce466 100644 --- a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h +++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h
@@ -44,13 +44,17 @@ const base::android::JavaParamRef<jstring>& j_suggestion_id, const base::android::JavaParamRef<jobject>& j_callback); - // Fetches a favicon corresponding to suggestion with |j_suggestion_id| and - // passes results to Java side using |j_callback|. - void FetchSuggestionFavicon( + // Gets the image URL for the given |suggestion_id|. + base::android::ScopedJavaLocalRef<jstring> GetImageUrl( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& j_suggestion_id, - const base::android::JavaParamRef<jobject>& j_callback); + const base::android::JavaParamRef<jstring>& j_suggestion_id); + + // Gets the favicon URL for the given |suggestion_id|. + base::android::ScopedJavaLocalRef<jstring> GetFaviconUrl( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jstring>& j_suggestion_id); // Requests the backend to clear state related to this bridge. void ClearState(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc index 166981e1..f569dcd 100644 --- a/chrome/browser/android/download/download_controller.cc +++ b/chrome/browser/android/download/download_controller.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/download/dangerous_download_infobar_delegate.h" #include "chrome/browser/android/download/download_manager_service.h" +#include "chrome/browser/android/download/download_utils.h" #include "chrome/browser/android/tab_android.h" #include "chrome/browser/download/download_stats.h" #include "chrome/browser/infobars/infobar_service.h" @@ -28,6 +29,7 @@ #include "chrome/browser/ui/android/view_android_helper.h" #include "chrome/browser/vr/vr_tab_helper.h" #include "chrome/grit/chromium_strings.h" +#include "components/download/public/common/auto_resumption_handler.h" #include "components/download/public/common/download_url_parameters.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -59,11 +61,6 @@ // Guards download_controller_ base::LazyInstance<base::Lock>::DestructorAtExit g_download_controller_lock_; -// If received bytes is more than the size limit and resumption will restart -// from the beginning, throttle it. -int kDefaultAutoResumptionSizeLimit = 10 * 1024 * 1024; // 10 MB -const char kAutoResumptionSizeLimitParamName[] = "AutoResumptionSizeLimit"; - void CreateContextMenuDownload( const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::ContextMenuParams& params, @@ -116,16 +113,6 @@ dlm->DownloadUrl(std::move(dl_params)); } -int GetAutoResumptionSizeLimit() { - std::string value = base::GetFieldTrialParamValueByFeature( - chrome::android::kDownloadAutoResumptionThrottling, - kAutoResumptionSizeLimitParamName); - int size_limit; - return base::StringToInt(value, &size_limit) - ? size_limit - : kDefaultAutoResumptionSizeLimit; -} - // Helper class for retrieving a DownloadManager. class DownloadManagerGetter : public DownloadManager::Observer { public: @@ -395,6 +382,8 @@ download_item->RemoveObserver(this); download_item->AddObserver(this); + download::AutoResumptionHandler::Get()->OnDownloadStarted(download_item); + OnDownloadUpdated(download_item); } @@ -480,7 +469,7 @@ if (!download_item->GetURL().SchemeIsHTTPOrHTTPS()) return false; - static int size_limit = GetAutoResumptionSizeLimit(); + static int size_limit = DownloadUtils::GetAutoResumptionSizeLimit(); bool exceeds_size_limit = download_item->GetReceivedBytes() > size_limit; std::string etag = download_item->GetETag(); std::string last_modified = download_item->GetLastModifiedTime();
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc index aadb99c..1ff1531 100644 --- a/chrome/browser/android/download/download_manager_service.cc +++ b/chrome/browser/android/download/download_manager_service.cc
@@ -16,6 +16,8 @@ #include "base/time/time.h" #include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/download/download_controller.h" +#include "chrome/browser/android/download/download_utils.h" +#include "chrome/browser/android/download/service/download_task_scheduler.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" @@ -23,6 +25,8 @@ #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_constants.h" +#include "components/download/network/android/network_status_listener_android.h" +#include "components/download/public/common/auto_resumption_handler.h" #include "components/download/public/common/download_item.h" #include "components/download/public/common/download_item_impl.h" #include "components/download/public/common/download_url_loader_factory_getter_impl.h" @@ -51,6 +55,20 @@ int kDefaultAutoResumptionLimit = 5; const char kAutoResumptionLimitParamName[] = "AutoResumptionLimit"; +void CreateAutoResumptionHandler() { + auto network_listener = + std::make_unique<download::NetworkStatusListenerAndroid>(); + auto task_scheduler = + std::make_unique<download::android::DownloadTaskScheduler>(); + auto task_manager = + std::make_unique<download::TaskManager>(std::move(task_scheduler)); + auto config = std::make_unique<download::AutoResumptionHandler::Config>(); + config->auto_resumption_size_limit = + DownloadUtils::GetAutoResumptionSizeLimit(); + download::AutoResumptionHandler::Create( + std::move(network_listener), std::move(task_manager), std::move(config)); +} + bool ShouldShowDownloadItem(download::DownloadItem* item) { return !item->IsTemporary() && !item->IsTransient(); } @@ -649,6 +667,22 @@ if (!in_progress_manager_ && !is_history_query_complete_) return; is_pending_downloads_loaded_ = true; + + // Kick-off the auto-resumption handler. + content::DownloadManager::DownloadVector all_items; + if (in_progress_manager_) { + in_progress_manager_->GetAllDownloads(&all_items); + } else { + content::DownloadManager* manager = GetDownloadManager(false); + if (manager) + manager->GetAllDownloads(&all_items); + } + + if (!download::AutoResumptionHandler::Get()) + CreateAutoResumptionHandler(); + + download::AutoResumptionHandler::Get()->SetResumableDownloads(all_items); + for (auto iter = pending_actions_.begin(); iter != pending_actions_.end(); ++iter) { DownloadActionParams params = iter->second;
diff --git a/chrome/browser/android/download/download_utils.cc b/chrome/browser/android/download/download_utils.cc index c413f75..27670e0 100644 --- a/chrome/browser/android/download/download_utils.cc +++ b/chrome/browser/android/download/download_utils.cc
@@ -5,6 +5,9 @@ #include "chrome/browser/android/download/download_utils.h" #include "base/android/jni_string.h" +#include "base/metrics/field_trial_params.h" +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/download/offline_item_utils.h" #include "chrome/grit/generated_resources.h" #include "components/download/public/common/download_utils.h" @@ -15,6 +18,14 @@ using base::android::JavaParamRef; using base::android::ScopedJavaLocalRef; +namespace { +// If received bytes is more than the size limit and resumption will restart +// from the beginning, throttle it. +int kDefaultAutoResumptionSizeLimit = 10 * 1024 * 1024; // 10 MB +const char kAutoResumptionSizeLimitParamName[] = "AutoResumptionSizeLimit"; + +} // namespace + static ScopedJavaLocalRef<jstring> JNI_DownloadUtils_GetFailStateMessage( JNIEnv* env, jint fail_state) { @@ -46,3 +57,14 @@ return base::FilePath( base::android::ConvertJavaStringToUTF8(env, uri_jstring)); } + +// static +int DownloadUtils::GetAutoResumptionSizeLimit() { + std::string value = base::GetFieldTrialParamValueByFeature( + chrome::android::kDownloadAutoResumptionThrottling, + kAutoResumptionSizeLimitParamName); + int size_limit; + return base::StringToInt(value, &size_limit) + ? size_limit + : kDefaultAutoResumptionSizeLimit; +}
diff --git a/chrome/browser/android/download/download_utils.h b/chrome/browser/android/download/download_utils.h index b507ffa..73c0b27a 100644 --- a/chrome/browser/android/download/download_utils.h +++ b/chrome/browser/android/download/download_utils.h
@@ -11,6 +11,7 @@ class DownloadUtils { public: static base::FilePath GetUriStringForPath(const base::FilePath& file_path); + static int GetAutoResumptionSizeLimit(); }; #endif // CHROME_BROWSER_ANDROID_DOWNLOAD_DOWNLOAD_UTILS_H_
diff --git a/chrome/browser/android/download/service/download_background_task.cc b/chrome/browser/android/download/service/download_background_task.cc index 86c394a..b7cc72db 100644 --- a/chrome/browser/android/download/service/download_background_task.cc +++ b/chrome/browser/android/download/service/download_background_task.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "components/download/public/background_service/download_service.h" +#include "components/download/public/common/auto_resumption_handler.h" #include "content/public/browser/browser_context.h" #include "jni/DownloadBackgroundTask_jni.h" @@ -16,6 +17,13 @@ namespace download { namespace android { +DownloadService* GetDownloadService( + const base::android::JavaParamRef<jobject>& jprofile) { + Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); + DCHECK(profile); + return DownloadServiceFactory::GetForBrowserContext(profile); +} + // static void JNI_DownloadBackgroundTask_StartBackgroundTask( JNIEnv* env, @@ -23,17 +31,23 @@ const base::android::JavaParamRef<jobject>& jprofile, jint task_type, const base::android::JavaParamRef<jobject>& jcallback) { - Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); - DCHECK(profile); - TaskFinishedCallback finish_callback = base::BindOnce(&base::android::RunBooleanCallbackAndroid, base::android::ScopedJavaGlobalRef<jobject>(jcallback)); - DownloadService* download_service = - DownloadServiceFactory::GetForBrowserContext(profile); - download_service->OnStartScheduledTask( - static_cast<DownloadTaskType>(task_type), std::move(finish_callback)); + switch (static_cast<DownloadTaskType>(task_type)) { + case download::DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK: { + download::AutoResumptionHandler::Get()->OnStartScheduledTask( + std::move(finish_callback)); + break; + } + case download::DownloadTaskType::DOWNLOAD_TASK: + FALLTHROUGH; + case download::DownloadTaskType::CLEANUP_TASK: + GetDownloadService(jprofile)->OnStartScheduledTask( + static_cast<DownloadTaskType>(task_type), std::move(finish_callback)); + break; + } } // static @@ -42,13 +56,18 @@ const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jobject>& jprofile, jint task_type) { - Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); - DCHECK(profile); - - DownloadService* download_service = - DownloadServiceFactory::GetForBrowserContext(profile); - return download_service->OnStopScheduledTask( - static_cast<DownloadTaskType>(task_type)); + switch (static_cast<DownloadTaskType>(task_type)) { + case download::DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK: { + download::AutoResumptionHandler::Get()->OnStopScheduledTask(); + break; + } + case download::DownloadTaskType::DOWNLOAD_TASK: + FALLTHROUGH; + case download::DownloadTaskType::CLEANUP_TASK: + return GetDownloadService(jprofile)->OnStopScheduledTask( + static_cast<DownloadTaskType>(task_type)); + } + return false; } } // namespace android
diff --git a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc index c97d0f3..15fb04b 100644 --- a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc +++ b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
@@ -18,7 +18,6 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" -#include "ui/base/test/scoped_fake_nswindow_fullscreen.h" #endif #if defined(OS_WIN)
diff --git a/chrome/browser/ash_service_registry.cc b/chrome/browser/ash_service_registry.cc index 7b0fd72a..feb2ebe 100644 --- a/chrome/browser/ash_service_registry.cc +++ b/chrome/browser/ash_service_registry.cc
@@ -7,7 +7,7 @@ #include "ash/ash_service.h" #include "ash/components/quick_launch/public/mojom/constants.mojom.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" #include "ash/public/interfaces/window_properties.mojom.h"
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index 1170ff2..373ca03 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -320,8 +320,9 @@ DCHECK(image_service); // TODO(jdonnelly, rhalavati): Create a helper function with Callback to - // create annotation and pass it to image_service, merging this annotation and - // chrome/browser/ui/omnibox/chrome_omnibox_client.cc + // create annotation and pass it to image_service, merging the annotations + // in omnibox_page_handler.cc, chrome_omnibox_client.cc, + // and chrome_autocomplete_provider_client.cc. net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("omnibox_prefetch_image", R"( semantics {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index a9e45ef..6d22976a 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -200,6 +200,9 @@ <include name="IDR_EOC_INTERNALS_JS" file="resources\eoc_internals\eoc_internals.js" compress="gzip" type="BINDATA" /> <include name="IDR_EOC_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\eoc_internals\eoc_internals.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_EXPLORE_SITES_INTERNALS_HTML" file="resources\explore_sites_internals\explore_sites_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" /> + <include name="IDR_FEED_INTERNALS_HTML" file="resources\feed_internals\feed_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" /> + <include name="IDR_FEED_INTERNALS_JS" file="resources\feed_internals\feed_internals.js" compress="gzip" type="BINDATA" /> + <include name="IDR_FEED_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\feed_internals\feed_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_OFFLINE_INTERNALS_HTML" file="resources\offline_pages\offline_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_OFFLINE_INTERNALS_CSS" file="resources\offline_pages\offline_internals.css" type="BINDATA" compress="gzip" /> <include name="IDR_OFFLINE_INTERNALS_JS" file="resources\offline_pages\offline_internals.js" type="BINDATA" compress="gzip" /> @@ -559,9 +562,6 @@ <include name="IDR_MD_USER_MANAGER_TUTORIAL_HTML" file="resources\md_user_manager\user_manager_tutorial.html" type="BINDATA" /> <include name="IDR_MD_USER_MANAGER_TUTORIAL_JS" file="resources\md_user_manager\user_manager_tutorial.js" type="BINDATA" /> </if> - <if expr="is_macosx"> - <include name="IDR_RECENTLY_CLOSED_WINDOW" file="resources\ntp4\images\closed_window.png" type="BINDATA" /> - </if> <if expr="not is_android"> <include name="IDR_IDENTITY_INTERNALS_HTML" file="resources\identity_internals.html" type="BINDATA" /> <include name="IDR_IDENTITY_INTERNALS_CSS" file="resources\identity_internals.css" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index 808d55570..0b868ae8 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -66,6 +66,7 @@ "removable_storage_writer": [ "removable_storage_writer" ], "secure_channel": [ "secure_channel" ], "shortcut_viewer_app": [ "shortcut_viewer" ], + "tap_visualizer_app": [ "tap_visualizer" ], "ui": [ "ime_registrar", "input_device_controller", @@ -108,6 +109,7 @@ // TODO(beng): These should be moved to a separate capability. "app_management.mojom.PageHandlerFactory", "eoc_internals.mojom.PageHandler", + "feed_internals.mojom.PageHandler", "media.mojom.MediaEngagementScoreDetailsProvider", "md_downloads.mojom.PageHandlerFactory", "mojom.BluetoothInternalsHandler",
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc index 0f3ad72..82ea907 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -9,7 +9,7 @@ #include "ash/accessibility/accessibility_focus_ring_layer.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/status_area_widget_test_api.mojom.h" +#include "ash/public/interfaces/status_area_widget_test_api.test-mojom.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h"
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc index ba64beb..2a0dded1 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/chromeos/child_accounts/screen_time_controller.h" +#include "ash/public/interfaces/login_screen.mojom.h" +#include "base/feature_list.h" #include "base/optional.h" #include "base/time/clock.h" #include "base/time/default_clock.h" @@ -13,6 +15,8 @@ #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/ash/login_screen_client.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" @@ -177,6 +181,8 @@ ScreenLocker::default_screen_locker()->SetAuthEnabledForUser( account_id, !visible, visible ? next_unlock_time : base::Optional<base::Time>()); + if (base::FeatureList::IsEnabled(features::kParentAccessCode)) + LoginScreenClient::Get()->login_screen()->SetShowParentAccess(visible); } void ScreenTimeController::OnPolicyChanged() {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc index 00f47991c..39feac5 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -10,7 +10,7 @@ #include <utility> #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/containers/circular_deque.h" #include "base/json/json_reader.h" #include "base/json/json_value_converter.h"
diff --git a/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc b/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc index 4c835c44..4d92980a 100644 --- a/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc +++ b/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "chrome/browser/chromeos/first_run/first_run.h" #include "chrome/browser/chromeos/first_run/first_run_controller.h" #include "chrome/browser/chromeos/first_run/step_names.h"
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc index 4e66315..727367a8 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
@@ -8,7 +8,7 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/login_screen_test_api.mojom.h" +#include "ash/public/interfaces/login_screen_test_api.test-mojom.h" #include "base/command_line.h" #include "base/macros.h" #include "base/run_loop.h"
diff --git a/chrome/browser/chromeos/login/login_shelf_test_helper.h b/chrome/browser/chromeos/login/login_shelf_test_helper.h index 1607a28..dba4530 100644 --- a/chrome/browser/chromeos/login/login_shelf_test_helper.h +++ b/chrome/browser/chromeos/login/login_shelf_test_helper.h
@@ -4,7 +4,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SHELF_TEST_HELPER_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_SHELF_TEST_HELPER_H_ -#include "ash/public/interfaces/login_screen_test_api.mojom.h" +#include "ash/public/interfaces/login_screen_test_api.test-mojom.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc b/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc index 7a5f10ab..cd9b6f5 100644 --- a/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/command_line.h" #include "base/location.h" #include "base/macros.h"
diff --git a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc index 40ff96e..02f655ac 100644 --- a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc +++ b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
@@ -217,6 +217,8 @@ const GURL kUrl3 = GURL("https://example3.com/"); private: + // TODO(crbug.com/917580): Remove this; thread_bundle() should be used + // instead. const scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; chromeos::FakeChromeUserManager fake_user_manager_;
diff --git a/chrome/browser/chromeos/power/ml/fake_boot_clock.cc b/chrome/browser/chromeos/power/ml/fake_boot_clock.cc index 730688a..ac61ed6 100644 --- a/chrome/browser/chromeos/power/ml/fake_boot_clock.cc +++ b/chrome/browser/chromeos/power/ml/fake_boot_clock.cc
@@ -12,15 +12,28 @@ scoped_refptr<const base::TestMockTimeTaskRunner> task_runner, base::TimeDelta initial_time_since_boot) : task_runner_(task_runner), + env_(nullptr), initial_time_since_boot_(initial_time_since_boot) { DCHECK_GE(initial_time_since_boot, base::TimeDelta()); initial_time_ticks_ = task_runner_->NowTicks(); } +FakeBootClock::FakeBootClock(base::test::ScopedTaskEnvironment* env, + base::TimeDelta initial_time_since_boot) + : env_(env), initial_time_since_boot_(initial_time_since_boot) { + DCHECK_GE(initial_time_since_boot, base::TimeDelta()); + initial_time_ticks_ = env_->NowTicks(); +} + FakeBootClock::~FakeBootClock() = default; base::TimeDelta FakeBootClock::GetTimeSinceBoot() { - base::TimeTicks now = task_runner_->NowTicks(); + base::TimeTicks now; + if (env_) { + now = env_->NowTicks(); + } else { + now = task_runner_->NowTicks(); + } return (now - initial_time_ticks_) + initial_time_since_boot_; }
diff --git a/chrome/browser/chromeos/power/ml/fake_boot_clock.h b/chrome/browser/chromeos/power/ml/fake_boot_clock.h index 0c9784c0..070b3dd8 100644 --- a/chrome/browser/chromeos/power/ml/fake_boot_clock.h +++ b/chrome/browser/chromeos/power/ml/fake_boot_clock.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_mock_time_task_runner.h" namespace chromeos { @@ -19,13 +20,18 @@ public: FakeBootClock(scoped_refptr<const base::TestMockTimeTaskRunner> task_runner, base::TimeDelta initial_time_since_boot); + FakeBootClock(base::test::ScopedTaskEnvironment* env, + base::TimeDelta initial_time_since_boot); ~FakeBootClock() override; // BootClock: base::TimeDelta GetTimeSinceBoot() override; private: + // TODO(crbug.com/917580): This is no longer needed and should be removed. + // |env_| should give sufficient access to fake clock values. scoped_refptr<const base::TestMockTimeTaskRunner> task_runner_; + base::test::ScopedTaskEnvironment* env_; base::TimeDelta initial_time_since_boot_; base::TimeTicks initial_time_ticks_;
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc index f7eb0e9..1d5c98c 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc +++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -9,8 +9,10 @@ #include <string> #include <vector> +#include "base/cancelable_callback.h" +#include "base/sequenced_task_runner.h" #include "base/test/scoped_feature_list.h" -#include "base/test/test_mock_time_task_runner.h" +#include "base/test/scoped_task_environment.h" #include "base/time/clock.h" #include "base/timer/timer.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" @@ -36,6 +38,8 @@ #include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/web_contents.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" #include "content/public/test/web_contents_tester.h" #include "services/metrics/public/cpp/ukm_source.h" #include "testing/gtest/include/gtest/gtest.h" @@ -98,11 +102,10 @@ }; // Testing smart dim model. -// TODO(crbug.com/914640): This is single-threaded, unlike the production -// implementation. Convert it to multi-threaded. class FakeSmartDimModel : public SmartDimModel { public: - FakeSmartDimModel() = default; + FakeSmartDimModel(const scoped_refptr<base::SequencedTaskRunner> runner) + : task_runner_(runner) {} ~FakeSmartDimModel() override = default; void set_inactivity_score(const int inactivity_score) { @@ -113,9 +116,8 @@ decision_threshold_ = decision_threshold; } - // SmartDimModel overrides: - void RequestDimDecision(const UserActivityEvent::Features& features, - DimDecisionCallback dim_callback) override { + UserActivityEvent::ModelPrediction ShouldDim( + const UserActivityEvent::Features& input_features) { UserActivityEvent::ModelPrediction model_prediction; // If either of these two values are set outside of the legal range [0,100], // return an error code. @@ -135,14 +137,30 @@ model_prediction.set_response(UserActivityEvent::ModelPrediction::DIM); } } - std::move(dim_callback).Run(model_prediction); + return model_prediction; } - void CancelPreviousRequest() override{}; + // SmartDimModel overrides: + void RequestDimDecision(const UserActivityEvent::Features& features, + DimDecisionCallback dim_callback) override { + // Cancel previously assigned callbacks and set it to the new callback. + cancelable_callback_.Reset(std::move(dim_callback)); + base::PostTaskAndReplyWithResult( + task_runner_.get(), FROM_HERE, + base::BindOnce(&FakeSmartDimModel::ShouldDim, base::Unretained(this), + features), + base::BindOnce(cancelable_callback_.callback())); + } + + // TODO(crbug.com/893425): Add unit tests that test this API. + void CancelPreviousRequest() override { cancelable_callback_.Cancel(); }; private: int inactivity_score_ = -1; int decision_threshold_ = -1; + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + base::CancelableOnceCallback<void(UserActivityEvent::ModelPrediction)> + cancelable_callback_; DISALLOW_COPY_AND_ASSIGN(FakeSmartDimModel); }; @@ -150,7 +168,11 @@ class UserActivityManagerTest : public ChromeRenderViewHostTestHarness { public: UserActivityManagerTest() - : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()) { + : ChromeRenderViewHostTestHarness( + base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME, + base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED, + content::TestBrowserThreadBundle::Options::DEFAULT), + model_(thread_bundle()->GetMainThreadTaskRunner()) { fake_power_manager_client_.Init(nullptr); viz::mojom::VideoDetectorObserverPtr observer; idle_event_notifier_ = std::make_unique<IdleEventNotifier>( @@ -161,8 +183,9 @@ &fake_power_manager_client_, &session_manager_, mojo::MakeRequest(&observer), &fake_user_manager_, &model_); activity_logger_->SetTaskRunnerForTesting( - task_runner_, std::make_unique<FakeBootClock>( - task_runner_, base::TimeDelta::FromSeconds(10))); + thread_bundle()->GetMainThreadTaskRunner(), + std::make_unique<FakeBootClock>(thread_bundle(), + base::TimeDelta::FromSeconds(10))); } ~UserActivityManagerTest() override = default; @@ -210,7 +233,7 @@ void ReportSuspend(power_manager::SuspendImminent::Reason reason, base::TimeDelta sleep_duration) { fake_power_manager_client_.SendSuspendImminent(reason); - GetTaskRunner()->FastForwardBy(sleep_duration); + thread_bundle()->FastForwardBy(sleep_duration); fake_power_manager_client_.SendSuspendDone(sleep_duration); } @@ -285,10 +308,6 @@ return ukm::GetSourceIdForWebContentsDocument(contents); } - const scoped_refptr<base::TestMockTimeTaskRunner>& GetTaskRunner() { - return task_runner_; - } - TestingUserActivityUkmLogger delegate_; FakeSmartDimModel model_; chromeos::FakeChromeUserManager fake_user_manager_; @@ -302,8 +321,6 @@ const GURL url4_ = GURL("https://example4.com/"); private: - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - ui::UserActivityDetector user_activity_detector_; std::unique_ptr<IdleEventNotifier> idle_event_notifier_; chromeos::FakePowerManagerClient fake_power_manager_client_; @@ -319,7 +336,7 @@ // Trigger an idle event. const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(2)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(2)); ReportUserActivity(nullptr); const std::vector<UserActivityEvent>& events = delegate_.events(); @@ -385,18 +402,18 @@ // Trigger the 2nd idle event. ReportIdleEvent(data); // Second user event. - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(2)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(2)); ReportUserActivity(nullptr); // Trigger the 3rd idle event. ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(3)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(3)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(10)); // Trigger the 4th idle event. ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(4)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(4)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(10)); @@ -463,7 +480,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(2)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(2)); ReportLidEvent(chromeos::PowerManagerClient::LidState::CLOSED); const std::vector<UserActivityEvent>& events = delegate_.events(); EXPECT_TRUE(events.empty()); @@ -517,9 +534,9 @@ // Trigger an idle event. const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportScreenIdleState(true /* screen_dim */, false /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(30)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(30)); ReportScreenIdleState(true /* screen_dim */, true /* screen_off */); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(10)); @@ -543,11 +560,11 @@ // Trigger an idle event. const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportScreenIdleState(true /* screen_dim */, false /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(30)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(30)); ReportScreenIdleState(true /* screen_dim */, true /* screen_off */); - GetTaskRunner()->FastForwardUntilNoTasksRemain(); + thread_bundle()->RunUntilIdle(); const std::vector<UserActivityEvent>& events = delegate_.events(); ASSERT_EQ(0U, events.size()); @@ -560,14 +577,14 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportScreenIdleState(true /* screen_dim */, false /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(30)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(30)); ReportScreenIdleState(true /* screen_dim */, true /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(1)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1)); ReportUserActivity(nullptr); - GetTaskRunner()->FastForwardUntilNoTasksRemain(); + thread_bundle()->RunUntilIdle(); const std::vector<UserActivityEvent>& events = delegate_.events(); ASSERT_EQ(1U, events.size()); @@ -621,7 +638,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(1)); const std::vector<UserActivityEvent>& events = delegate_.events(); @@ -797,7 +814,7 @@ ReportScreenIdleState(false /* screen_dim */, true /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(7)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(7)); ReportUserActivity(nullptr); const std::vector<UserActivityEvent>& events = delegate_.events(); @@ -825,7 +842,7 @@ ReportIdleEvent(data); ReportScreenIdleState(false /* screen_dim */, false /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(7)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(7)); ReportScreenIdleState(true /* screen_dim */, true /* screen_off */); ReportUserActivity(nullptr); @@ -854,7 +871,7 @@ ReportScreenIdleState(true /* screen_dim */, false /* screen_off */); ReportScreenIdleState(true /* screen_dim */, true /* screen_off */); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(7)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(7)); ReportScreenIdleState(false /* screen_dim */, false /* screen_off */); ReportUserActivity(nullptr); @@ -886,6 +903,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); ReportUserActivity(nullptr); EXPECT_EQ(1, GetNumberOfDeferredDims()); @@ -921,6 +939,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); EXPECT_EQ(1, GetNumberOfDeferredDims()); const std::vector<UserActivityEvent>& events = delegate_.events(); @@ -939,6 +958,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); ReportUserActivity(nullptr); EXPECT_EQ(0, GetNumberOfDeferredDims()); @@ -967,20 +987,21 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); EXPECT_EQ(1, GetNumberOfDeferredDims()); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(6)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(6)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(3)); // 2nd ScreenDimImminent is not deferred despite model score says so. model_.set_inactivity_score(20); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(10)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(10)); ReportIdleEvent(data); EXPECT_EQ(1, GetNumberOfDeferredDims()); // Log when a SuspendImminent is received - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(3)); @@ -1035,16 +1056,18 @@ model_.set_inactivity_score(40); const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); EXPECT_EQ(1, GetNumberOfDeferredDims()); // 2nd ScreenDimImminent is not deferred despite model score says so. model_.set_inactivity_score(20); - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(10)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(10)); ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); EXPECT_EQ(1, GetNumberOfDeferredDims()); // Log when a SuspendImminent is received - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); + thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(20)); ReportSuspend(power_manager::SuspendImminent_Reason_IDLE, base::TimeDelta::FromSeconds(3)); @@ -1095,6 +1118,7 @@ const IdleEventNotifier::ActivityData data; ReportIdleEvent(data); + thread_bundle()->RunUntilIdle(); ReportUserActivity(nullptr); EXPECT_EQ(0, GetNumberOfDeferredDims());
diff --git a/chrome/browser/chromeos/shutdown_policy_browsertest.cc b/chrome/browser/chromeos/shutdown_policy_browsertest.cc index d8625c30..c2e2ab1 100644 --- a/chrome/browser/chromeos/shutdown_policy_browsertest.cc +++ b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
@@ -9,7 +9,7 @@ #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/command_line.h" #include "base/location.h" #include "base/macros.h"
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc index a33c722..6048586 100644 --- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc +++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -4,7 +4,7 @@ #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/ash_view_ids.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/callback.h" #include "base/command_line.h" #include "base/run_loop.h"
diff --git a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc index af4e61d..007abf8bdcb 100644 --- a/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
@@ -147,14 +147,7 @@ CheckIsMinimized(true); } -#if defined(OS_MACOSX) -// https://crbug.com/828031 -#define MAYBE_NormalToFullscreenWindow DISABLED_NormalToFullscreenWindow -#else -#define MAYBE_NormalToFullscreenWindow NormalToFullscreenWindow -#endif -IN_PROC_BROWSER_TEST_F(DevToolsManagerDelegateTest, - MAYBE_NormalToFullscreenWindow) { +IN_PROC_BROWSER_TEST_F(DevToolsManagerDelegateTest, NormalToFullscreenWindow) { #if defined(OS_MACOSX) ui::test::ScopedFakeNSWindowFullscreen faker; #endif @@ -183,7 +176,7 @@ } #if defined(OS_MACOSX) -// https://crbug.com/828031 +// MacViews does not yet implement maximized windows: https://crbug.com/836327 #define MAYBE_MaximizedToFullscreenWindow DISABLED_MaximizedToFullscreenWindow #else #define MAYBE_MaximizedToFullscreenWindow MaximizedToFullscreenWindow @@ -193,14 +186,8 @@ browser()->window()->Maximize(); CheckIsMaximized(true); -#if defined(OS_MACOSX) - ui::test::ScopedFakeNSWindowFullscreen faker; -#endif CheckIsFullscreen(false); SendCommand("fullscreen"); -#if defined(OS_MACOSX) - faker.FinishTransition(); -#endif CheckIsFullscreen(true); } @@ -225,14 +212,7 @@ CheckIsMaximized(false); } -#if defined(OS_MACOSX) -// https://crbug.com/828031 -#define MAYBE_ExitFullscreenWindow DISABLED_ExitFullscreenWindow -#else -#define MAYBE_ExitFullscreenWindow ExitFullscreenWindow -#endif -IN_PROC_BROWSER_TEST_F(DevToolsManagerDelegateTest, - MAYBE_ExitFullscreenWindow) { +IN_PROC_BROWSER_TEST_F(DevToolsManagerDelegateTest, ExitFullscreenWindow) { #if defined(OS_MACOSX) ui::test::ScopedFakeNSWindowFullscreen faker; #endif
diff --git a/chrome/browser/download/download_task_scheduler_impl.cc b/chrome/browser/download/download_task_scheduler_impl.cc index 325ae9b..d12556d 100644 --- a/chrome/browser/download/download_task_scheduler_impl.cc +++ b/chrome/browser/download/download_task_scheduler_impl.cc
@@ -49,6 +49,11 @@ void DownloadTaskSchedulerImpl::RunScheduledTask( download::DownloadTaskType task_type) { + if (task_type == download::DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK) { + NOTREACHED(); + return; + } + download::DownloadService* download_service = DownloadServiceFactory::GetForBrowserContext(context_); download_service->OnStartScheduledTask(
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc index 7f5bd8b..84d6446 100644 --- a/chrome/browser/extensions/api/tabs/tabs_test.cc +++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -1035,6 +1035,7 @@ #if defined(OS_MACOSX) if (base::mac::IsOS10_10()) return; // Fails when swarmed. http://crbug.com/660582 + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; #endif scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction());
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index f68b35a..c515ca8 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -675,7 +675,7 @@ }, { "name": "document-passive-event-listeners", - "owners": ["input-dev" ], + "owners": ["nzolghadr, input-dev" ], "expiry_milestone": 76 }, { @@ -1174,6 +1174,11 @@ "expiry_milestone": 78 }, { + "name": "enable-experimental-accessibility-labels", + "owners": [ "katie", "dmazzoni", "dtseng" ], + "expiry_milestone": 78 + }, + { "name": "enable-experimental-crostini-ui", "owners": [ "nverne", "benwells" ], "expiry_milestone": 76 @@ -1936,8 +1941,8 @@ }, { "name": "enable-touch-drag-drop", - "owners": ["input-dev" ], - "expiry_milestone": -1 + "owners": ["eirage", "input-dev" ], + "expiry_milestone": 78 }, { "name": "enable-touchable-app-context-menu", @@ -2762,13 +2767,13 @@ }, { "name": "passive-event-listeners-due-to-fling", - "owners": ["input-dev" ], + "owners": ["sahel", "input-dev" ], "expiry_milestone": 76 }, { "name": "passive-listener-default", - "owners": ["input-dev" ], - "expiry_milestone": 76 + "owners": ["nzolghadr", "input-dev" ], + "expiry_milestone": 78 }, { "name": "passwords-keyboard-accessory",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index b44def0..3ada28ad 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -692,6 +692,11 @@ const char kExperimentalAccessibilityAutoclickDescription[] = "Enable additional features for automatic clicks."; +const char kExperimentalAccessibilityLabelsName[] = + "Experimental accessibility image label features"; +const char kExperimentalAccessibilityLabelsDescription[] = + "Enable additional features for image labels for accessibility."; + const char kExperimentalAccessibilitySwitchAccessName[] = "Experimental feature Switch Access"; const char kExperimentalAccessibilitySwitchAccessDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2040a504..e658eb0 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -166,6 +166,9 @@ extern const char kExperimentalAccessibilityAutoclickName[]; extern const char kExperimentalAccessibilityAutoclickDescription[]; +extern const char kExperimentalAccessibilityLabelsName[]; +extern const char kExperimentalAccessibilityLabelsDescription[]; + extern const char kExperimentalAccessibilitySwitchAccessName[]; extern const char kExperimentalAccessibilitySwitchAccessDescription[];
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc index 952f260..1dc55cdc 100644 --- a/chrome/browser/notifications/notification_interactive_uitest.cc +++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -580,6 +580,9 @@ } IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayFullscreen) { +#if defined(OS_MACOSX) + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; +#endif ASSERT_TRUE(embedded_test_server()->Start()); AllowAllOrigins(); @@ -662,6 +665,9 @@ // Verify that a notification is actually displayed when the webpage that // creates it is fullscreen with the fullscreen notification flag turned on. IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayPopupNotification) { +#if defined(OS_MACOSX) + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; +#endif ASSERT_TRUE(embedded_test_server()->Start()); // Creates a simple notification.
diff --git a/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc index 373a206d..5622d2c 100644 --- a/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc +++ b/chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.cc
@@ -12,20 +12,13 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search/suggestions/image_decoder_impl.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "components/image_fetcher/core/image_decoder.h" -#include "components/image_fetcher/core/image_fetcher.h" -#include "components/image_fetcher/core/image_fetcher_impl.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h" #include "components/ntp_snippets/contextual/contextual_suggestions_features.h" #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_debugging_reporter.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.h" -#include "components/ntp_snippets/remote/cached_image_fetcher.h" -#include "components/ntp_snippets/remote/remote_suggestions_database.h" -#include "components/prefs/pref_service.h" #include "components/unified_consent/feature.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" @@ -39,9 +32,6 @@ using contextual_suggestions::ContextualSuggestionsFetcherImpl; using contextual_suggestions::ContextualContentSuggestionsService; -using ntp_snippets::CachedImageFetcher; -using ntp_snippets::RemoteSuggestionsDatabase; - namespace { bool AreContextualContentSuggestionsEnabled() { @@ -96,7 +86,6 @@ return nullptr; } - PrefService* pref_service = profile->GetPrefs(); content::StoragePartition* storage_partition = content::BrowserContext::GetDefaultStoragePartition(context); std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper> @@ -112,26 +101,12 @@ std::make_unique<ContextualSuggestionsFetcherImpl>( storage_partition->GetURLLoaderFactoryForBrowserProcess(), std::move(consent_helper), g_browser_process->GetApplicationLocale()); - const base::FilePath::CharType kDatabaseFolder[] = - FILE_PATH_LITERAL("contextualSuggestionsDatabase"); - base::FilePath database_dir(profile->GetPath().Append(kDatabaseFolder)); - auto contextual_suggestions_database = - std::make_unique<RemoteSuggestionsDatabase>(database_dir); - auto cached_image_fetcher = - std::make_unique<ntp_snippets::CachedImageFetcher>( - std::make_unique<image_fetcher::ImageFetcherImpl>( - std::make_unique<suggestions::ImageDecoderImpl>(), - content::BrowserContext::GetDefaultStoragePartition(profile) - ->GetURLLoaderFactoryForBrowserProcess()), - pref_service, contextual_suggestions_database.get()); auto reporter_provider = std::make_unique< contextual_suggestions::ContextualSuggestionsReporterProvider>( std::make_unique< contextual_suggestions::ContextualSuggestionsDebuggingReporter>()); auto* service = new ContextualContentSuggestionsService( - std::move(contextual_suggestions_fetcher), - std::move(cached_image_fetcher), - std::move(contextual_suggestions_database), std::move(reporter_provider)); + std::move(contextual_suggestions_fetcher), std::move(reporter_provider)); return service; }
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc index 4b546b7..4a2a165 100644 --- a/chrome/browser/previews/previews_lite_page_browsertest.cc +++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -974,7 +974,8 @@ VerifyPreviewNotLoaded(); histogram_tester.ExpectBucketCount( "Previews.ServerLitePage.BlacklistReasons", - PreviewsLitePageNavigationThrottle::BlacklistReason::kHostBlacklisted, + PreviewsLitePageNavigationThrottle::BlacklistReason:: + kHostBypassBlacklisted, 1); ClearDeciderState(); @@ -1121,10 +1122,8 @@ ClearDeciderState(); } -// This was previously marked DISABLE_ON_WIN_MAC(), but the test is also failing -// flakily on Linux, so now it is completely disabled. https://crbug.com/915775 IN_PROC_BROWSER_TEST_F(PreviewsLitePageServerBrowserTest, - DISABLED_LitePagePreviewsReportSavings) { + DISABLE_ON_WIN_MAC(LitePagePreviewsReportSavings)) { PrefService* prefs = browser()->profile()->GetPrefs(); prefs->SetBoolean(data_reduction_proxy::prefs::kDataUsageReportingEnabled, true); @@ -1136,6 +1135,10 @@ ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess)); VerifyPreviewLoaded(); + // Navigate to an untracked (no preview) page before checking reported savings + // to reduce flakiness. + ui_test_utils::NavigateToURL(browser(), GURL("http://www.google.com")); + EXPECT_EQ(GetTotalOriginalContentLength() - GetTotalDataUsage(), 40U); EXPECT_EQ(GetDataUsage(), 20U); }
diff --git a/chrome/browser/previews/previews_lite_page_decider.cc b/chrome/browser/previews/previews_lite_page_decider.cc index 89c0322..afd9a2b 100644 --- a/chrome/browser/previews/previews_lite_page_decider.cc +++ b/chrome/browser/previews/previews_lite_page_decider.cc
@@ -135,7 +135,7 @@ page_id_(base::RandUint64()), drp_settings_(nullptr), pref_service_(nullptr), - host_blacklist_(std::make_unique<base::DictionaryValue>()) { + host_bypass_blacklist_(std::make_unique<base::DictionaryValue>()) { if (!browser_context) return; @@ -148,15 +148,15 @@ DCHECK(!browser_context->IsOffTheRecord()); pref_service_ = Profile::FromBrowserContext(browser_context)->GetPrefs(); - host_blacklist_ = + host_bypass_blacklist_ = pref_service_->GetDictionary(kHostBlacklist)->CreateDeepCopy(); // Note: This switch has no effect if |drp_settings| was null since - // |host_blacklist_| would be empty anyways. + // |host_bypass_blacklist_| would be empty anyways. if (base::CommandLine::ForCurrentProcess()->HasSwitch( previews::switches::kClearLitePageRedirectLocalBlacklist)) { - host_blacklist_->Clear(); - pref_service_->Set(kHostBlacklist, *host_blacklist_); + host_bypass_blacklist_->Clear(); + pref_service_->Set(kHostBlacklist, *host_bypass_blacklist_); } // Add |this| as an observer to DRP, but if DRP is already initialized, check @@ -253,14 +253,14 @@ void PreviewsLitePageDecider::ClearBlacklist() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - host_blacklist_->Clear(); + host_bypass_blacklist_->Clear(); if (pref_service_) - pref_service_->Set(kHostBlacklist, *host_blacklist_); + pref_service_->Set(kHostBlacklist, *host_bypass_blacklist_); } void PreviewsLitePageDecider::ClearStateForTesting() { single_bypass_.clear(); - host_blacklist_->Clear(); + host_bypass_blacklist_->Clear(); } void PreviewsLitePageDecider::SetUserHasSeenUINotification() { @@ -369,21 +369,22 @@ base::Unretained(this))); } -void PreviewsLitePageDecider::BlacklistHost(const std::string& host, - base::TimeDelta duration) { +void PreviewsLitePageDecider::BlacklistBypassedHost(const std::string& host, + base::TimeDelta duration) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // If there is an existing entry, intentionally update it. - host_blacklist_->SetKey( + host_bypass_blacklist_->SetKey( host, base::Value((base::Time::Now() + duration).ToDoubleT())); - RemoveStaleEntries(host_blacklist_.get()); + RemoveStaleEntries(host_bypass_blacklist_.get()); if (pref_service_) - pref_service_->Set(kHostBlacklist, *host_blacklist_); + pref_service_->Set(kHostBlacklist, *host_bypass_blacklist_); } -bool PreviewsLitePageDecider::HostBlacklisted(const std::string& host) { +bool PreviewsLitePageDecider::HostBlacklistedFromBypass( + const std::string& host) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::Value* value = host_blacklist_->FindKey(host); + base::Value* value = host_bypass_blacklist_->FindKey(host); if (!value) return false;
diff --git a/chrome/browser/previews/previews_lite_page_decider.h b/chrome/browser/previews/previews_lite_page_decider.h index 8f908f0..e6d9cfda 100644 --- a/chrome/browser/previews/previews_lite_page_decider.h +++ b/chrome/browser/previews/previews_lite_page_decider.h
@@ -85,9 +85,9 @@ const std::string& host) override; bool NeedsToNotifyUser() override; void NotifyUser(content::WebContents* web_contents) override; - void BlacklistHost(const std::string& host, - base::TimeDelta duration) override; - bool HostBlacklisted(const std::string& host) override; + void BlacklistBypassedHost(const std::string& host, + base::TimeDelta duration) override; + bool HostBlacklistedFromBypass(const std::string& host) override; // data_reduction_proxy::DataReductionProxySettingsObserver: void OnProxyRequestHeadersChanged( @@ -122,7 +122,7 @@ // A dictionary of host string to base::Time. If a hostname is a member of // this dictionary, that host should be blacklisted from this preview until // after the time value. This is stored persistently in prefs. - std::unique_ptr<base::DictionaryValue> host_blacklist_; + std::unique_ptr<base::DictionaryValue> host_bypass_blacklist_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/previews/previews_lite_page_decider_unittest.cc b/chrome/browser/previews/previews_lite_page_decider_unittest.cc index 71be1a7c..0bde54a 100644 --- a/chrome/browser/previews/previews_lite_page_decider_unittest.cc +++ b/chrome/browser/previews/previews_lite_page_decider_unittest.cc
@@ -39,7 +39,7 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; }; -TEST_F(PreviewsLitePageDeciderTest, TestHostBlacklist) { +TEST_F(PreviewsLitePageDeciderTest, TestHostBypassBlacklist) { const int kBlacklistDurationDays = 30; const std::string kHost = "google.com"; const std::string kOtherHost = "chromium.org"; @@ -51,49 +51,49 @@ PreviewsLitePageNavigationThrottleManager* manager = decider.get(); // Simple happy case. - manager->BlacklistHost(kHost, kOneDay); - EXPECT_TRUE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kHost, kOneDay); + EXPECT_TRUE(manager->HostBlacklistedFromBypass(kHost)); decider->ClearStateForTesting(); // Old entries are deleted. - manager->BlacklistHost(kHost, kYesterday); - EXPECT_FALSE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kHost, kYesterday); + EXPECT_FALSE(manager->HostBlacklistedFromBypass(kHost)); decider->ClearStateForTesting(); // Oldest entry is thrown out. - manager->BlacklistHost(kHost, kOneDay); - EXPECT_TRUE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kHost, kOneDay); + EXPECT_TRUE(manager->HostBlacklistedFromBypass(kHost)); for (int i = 1; i <= kBlacklistDurationDays; i++) { - manager->BlacklistHost(kHost + base::IntToString(i), - kOneDay + base::TimeDelta::FromSeconds(i)); + manager->BlacklistBypassedHost(kHost + base::IntToString(i), + kOneDay + base::TimeDelta::FromSeconds(i)); } - EXPECT_FALSE(manager->HostBlacklisted(kHost)); + EXPECT_FALSE(manager->HostBlacklistedFromBypass(kHost)); decider->ClearStateForTesting(); // Oldest entry is not thrown out if there was a stale entry to remove. - manager->BlacklistHost(kHost, kOneDay); - EXPECT_TRUE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kHost, kOneDay); + EXPECT_TRUE(manager->HostBlacklistedFromBypass(kHost)); for (int i = 1; i <= kBlacklistDurationDays - 1; i++) { - manager->BlacklistHost(kHost + base::IntToString(i), - kOneDay + base::TimeDelta::FromSeconds(i)); + manager->BlacklistBypassedHost(kHost + base::IntToString(i), + kOneDay + base::TimeDelta::FromSeconds(i)); } - manager->BlacklistHost(kOtherHost, kYesterday); - EXPECT_TRUE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kOtherHost, kYesterday); + EXPECT_TRUE(manager->HostBlacklistedFromBypass(kHost)); decider->ClearStateForTesting(); } -TEST_F(PreviewsLitePageDeciderTest, TestClearBlacklist) { +TEST_F(PreviewsLitePageDeciderTest, TestClearHostBypassBlacklist) { const std::string kHost = "1.chromium.org"; std::unique_ptr<PreviewsLitePageDecider> decider = std::make_unique<PreviewsLitePageDecider>(nullptr); PreviewsLitePageNavigationThrottleManager* manager = decider.get(); - manager->BlacklistHost(kHost, base::TimeDelta::FromMinutes(1)); - EXPECT_TRUE(manager->HostBlacklisted(kHost)); + manager->BlacklistBypassedHost(kHost, base::TimeDelta::FromMinutes(1)); + EXPECT_TRUE(manager->HostBlacklistedFromBypass(kHost)); decider->ClearBlacklist(); - EXPECT_FALSE(manager->HostBlacklisted(kHost)); + EXPECT_FALSE(manager->HostBlacklistedFromBypass(kHost)); } TEST_F(PreviewsLitePageDeciderTest, TestServerUnavailable) {
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc index 172e4f8..9e5fe4b 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
@@ -306,8 +306,8 @@ } } - if (manager_->HostBlacklisted(url.host())) - blacklist_reasons.push_back(BlacklistReason::kHostBlacklisted); + if (manager_->HostBlacklistedFromBypass(url.host())) + blacklist_reasons.push_back(BlacklistReason::kHostBypassBlacklisted); // Record UMA for (BlacklistReason reason : blacklist_reasons) { @@ -562,7 +562,8 @@ chrome_proxy_header.find("host-blacklisted") != std::string::npos; if (blacklist_host) - manager_->BlacklistHost(GURL(original_url).host(), kBlacklistDuration); + manager_->BlacklistBypassedHost(GURL(original_url).host(), + kBlacklistDuration); UMA_HISTOGRAM_BOOLEAN("Previews.ServerLitePage.HostBlacklistedOnBypass", blacklist_host);
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.h b/chrome/browser/previews/previews_lite_page_navigation_throttle.h index e531a84..a0d073ef 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.h +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.h
@@ -44,8 +44,8 @@ kPathSuffixBlacklisted = 0, kNavigationToPreviewsDomain = 1, kNavigationToPrivateDomain = 2, - kHostBlacklisted = 3, - kMaxValue = kHostBlacklisted, + kHostBypassBlacklisted = 3, + kMaxValue = kHostBypassBlacklisted, }; // Reasons that a navigation is not eligible for this preview. This enum must
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h b/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h index 81b9a26..57f3493 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h
@@ -53,12 +53,14 @@ // Prompts |this| to display the required UI notifications to the user. virtual void NotifyUser(content::WebContents* web_contents) = 0; - // Blacklists the given |host| for the given |duration|. - virtual void BlacklistHost(const std::string& host, - base::TimeDelta duration) = 0; + // Blacklists the given |host| for the given |duration| in the server + // bypass blacklist for LitePageRedirects. + virtual void BlacklistBypassedHost(const std::string& host, + base::TimeDelta duration) = 0; - // Returns true if the given |host| is blacklisted. - virtual bool HostBlacklisted(const std::string& host) = 0; + // Returns true if the given |host| is blacklisted in the server bypass + // blacklist. + virtual bool HostBlacklistedFromBypass(const std::string& host) = 0; }; #endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_MANAGER_H_
diff --git a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html index 758591d..7193b7b2 100644 --- a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html +++ b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html
@@ -78,7 +78,8 @@ <oobe-text-button id="arc-tos-accept-button" inverse on-tap="onAccept_" disabled="[[arcTosButtonsDisabled]]"> - <div i18n-content="arcTermsOfServiceAcceptButton"></div> + <div id="arc-tos-accept-button-content" + i18n-content="arcTermsOfServiceAcceptButton"></div> </oobe-text-button> </div> </oobe-dialog>
diff --git a/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js b/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js index 2653942..3e285ee 100644 --- a/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js +++ b/chrome/browser/resources/chromeos/login/screen_arc_terms_of_service.js
@@ -616,7 +616,7 @@ this.setMetricsMode( loadTimeData.getString('arcTextMetricsManagedEnabled'), true); } - this.getElement_('arc-tos-accept-button').textContent = + this.getElement_('arc-tos-accept-button-content').textContent = loadTimeData.getString( isDemoModeSetup ? 'arcTermsOfServiceAcceptAndContinueButton' : 'arcTermsOfServiceAcceptButton');
diff --git a/chrome/browser/resources/feed_internals/BUILD.gn b/chrome/browser/resources/feed_internals/BUILD.gn new file mode 100644 index 0000000..2b2288c --- /dev/null +++ b/chrome/browser/resources/feed_internals/BUILD.gn
@@ -0,0 +1,19 @@ +# 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. + +import("//third_party/closure_compiler/compile_js.gni") + +js_type_check("closure_compile") { + deps = [ + ":feed_internals", + ] +} + +js_library("feed_internals") { + extra_deps = [ "//chrome/browser/ui/webui/feed_internals:mojo_bindings_js" ] + externs_list = [ + "$root_gen_dir/chrome/browser/ui/webui/feed_internals/feed_internals.mojom-lite.externs.js", + "$externs_path/mojo.js", + ] +}
diff --git a/chrome/browser/resources/feed_internals/OWNERS b/chrome/browser/resources/feed_internals/OWNERS new file mode 100644 index 0000000..4a7fc50 --- /dev/null +++ b/chrome/browser/resources/feed_internals/OWNERS
@@ -0,0 +1 @@ +file://components/feed/OWNERS
diff --git a/chrome/browser/resources/feed_internals/feed_internals.html b/chrome/browser/resources/feed_internals/feed_internals.html new file mode 100644 index 0000000..df5acf4 --- /dev/null +++ b/chrome/browser/resources/feed_internals/feed_internals.html
@@ -0,0 +1,24 @@ +<!-- +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. +--> + +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Feed Internals</title> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + + <script src="chrome://resources/js/mojo_bindings_lite.js"></script> + <script src="feed_internals.mojom-lite.js"></script> + + <script src="feed_internals.js"></script> +</head> + +<body> + TODO(chouinard): Implement this. +</body> +</html>
diff --git a/chrome/browser/resources/feed_internals/feed_internals.js b/chrome/browser/resources/feed_internals/feed_internals.js new file mode 100644 index 0000000..57f55000 --- /dev/null +++ b/chrome/browser/resources/feed_internals/feed_internals.js
@@ -0,0 +1,13 @@ +// 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. + +'use strict'; + +// Reference to the backend. +let pageHandler = null; + +document.addEventListener('DOMContentLoaded', function() { + // Setup backend mojo. + pageHandler = feedInternals.mojom.PageHandler.getProxy(); +});
diff --git a/chrome/browser/resources/ntp4/images/2x/closed_window.png b/chrome/browser/resources/ntp4/images/2x/closed_window.png deleted file mode 100644 index ca1fdd8..0000000 --- a/chrome/browser/resources/ntp4/images/2x/closed_window.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/ntp4/images/closed_window.png b/chrome/browser/resources/ntp4/images/closed_window.png deleted file mode 100644 index d92c9dda..0000000 --- a/chrome/browser/resources/ntp4/images/closed_window.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/omnibox/omnibox.css b/chrome/browser/resources/omnibox/omnibox.css index a7eedde..1314695 100644 --- a/chrome/browser/resources/omnibox/omnibox.css +++ b/chrome/browser/resources/omnibox/omnibox.css
@@ -154,6 +154,10 @@ font-size: 0; } +.pair-container { + align-items: center; +} + .cell-contents-and-description .pair-container, .cell-fill-and-inline .pair-container { display: flex; @@ -168,12 +172,20 @@ margin-right: 15px; } -.cell-contents-and-description .pair-item:first-child { +.cell-contents-and-description img.pair-item { + border-radius: 3px; + height: 28px; +} + +.cell-contents-and-description .pair-item.contents { color: blue; } +.cell-contents-and-description .pair-item.answer { + color: orange; +} + .cell-fill-and-inline .pair-container { - align-items: center; margin-right: -1px; } @@ -181,7 +193,7 @@ margin-right: 1px; } -.cell-fill-and-inline .pair-item:nth-child(2):not(:empty) { +.cell-fill-and-inline .pair-item.inline:not(:empty) { border: 1px solid; font-weight: bold; } @@ -190,6 +202,11 @@ color: red; } +.cell-destination-url img { + margin-right: 5px; + vertical-align: middle; +} + .accesskey { text-decoration: underline; text-transform: capitalize; @@ -207,6 +224,11 @@ border: 1px solid; } +img:not([src]), +.pair-item:empty:not(img) { + display: none; +} + omnibox-input { --action-color: rgb(66, 133, 244); --hover-color: #f2f2f2;
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js index b1b18ea..2190eab2 100644 --- a/chrome/browser/resources/omnibox/omnibox.js +++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -19,7 +19,8 @@ (function () { class BrowserProxy { - constructor() { + /** @param {!omnibox_output.OmniboxOutput} omniboxOutput */ + constructor(omniboxOutput) { /** @private {!mojom.OmniboxPageCallbackRouter} */ this.callbackRouter_ = new mojom.OmniboxPageCallbackRouter; @@ -28,7 +29,9 @@ // match. Response refers to the data returned from the C++ // AutocompleteController. this.callbackRouter_.handleNewAutocompleteResult.addListener( - result => omniboxOutput.addAutocompleteResponse(result)); + omniboxOutput.addAutocompleteResponse.bind(omniboxOutput)); + this.callbackRouter_.handleAnswerImageData.addListener( + omniboxOutput.updateAnswerImage.bind(omniboxOutput)); /** @private {!mojom.OmniboxPageHandlerProxy} */ this.handler_ = mojom.OmniboxPageHandler.getProxy(); @@ -43,7 +46,7 @@ } /** @type {!BrowserProxy} */ - const browserProxy = new BrowserProxy(); + let browserProxy; /** @type {!OmniboxInput} */ let omniboxInput; /** @type {!omnibox_output.OmniboxOutput} */ @@ -53,6 +56,7 @@ omniboxInput = /** @type {!OmniboxInput} */ ($('omnibox-input')); omniboxOutput = /** @type {!omnibox_output.OmniboxOutput} */ ($('omnibox-output')); + browserProxy = new BrowserProxy(omniboxOutput); omniboxInput.addEventListener('query-inputs-changed', event => { omniboxOutput.clearAutocompleteResponses();
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index c599c85..1083f300 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -65,6 +65,14 @@ } /** + * @param {string} url + * @param {string} data + */ + updateAnswerImage(url, data) { + this.matches.forEach(match => match.updateAnswerImage(url, data)); + } + + /** * Show or hide various output elements depending on display inputs. * 1) Show non-last result groups only if showIncompleteResults is true. * 2) Show the details section above each table if showDetails or @@ -102,7 +110,7 @@ get visibleTableText() { return this.resultsGroups_ .flatMap(resultsGroup => resultsGroup.visibleText) - .reduce((prev, cur) => `${prev}${cur}\n`, ''); + .join('\n'); } } @@ -326,8 +334,10 @@ /** @param {!mojom.AutocompleteMatch} match */ set match(match) { - /** @type {!Object} */ + /** @type {!Object<string, !OutputProperty>} */ this.properties = {}; + /** @type {!OutputProperty} */ + this.properties.contentsAndDescription; /** @type {?string} */ this.providerName = match.providerName || null; @@ -367,6 +377,15 @@ this.appendChild(this.additionalProperties); } + /** + * @param {string} url + * @param {string} data + */ + updateAnswerImage(url, data) { + if (this.properties.contentsAndDescription.value === url) + this.properties.contentsAndDescription.setAnswerImageData(data); + } + /** @param {boolean} showDetails */ updateVisibility(showDetails) { // Show certain columns only if they showDetails is true. @@ -398,7 +417,9 @@ * needs to be displayed for this match. */ get hasAdditionalProperties() { - return Object.keys(this.additionalProperties.value).length > 0; + return Object + .keys(/** @type {!Object} */ (this.additionalProperties.value)) + .length > 0; } /** @private @return {!Array<!OutputProperty>} */ @@ -446,7 +467,7 @@ class OutputProperty extends HTMLTableCellElement { /** * @param {Column} column - * @param {!Array<!Object>} values + * @param {!Array<*>} values * @return {!OutputProperty} */ static create(column, values) { @@ -457,16 +478,11 @@ return outputProperty; } - /** @return {!Object} */ - get value() { - return this.value_; - } - - /** @param {!Array<!Object>} values */ + /** @param {!Array<*>} values */ set values(values) { - /** @private {!Object} */ - this.value_ = values[0]; - /** @private {!Array<!Object>} */ + /** @type {*} */ + this.value = values[0]; + /** @private {!Array<*>} */ this.values_ = values; /** @override */ this.render_(); @@ -477,7 +493,7 @@ /** @return {string} */ get text() { - return this.value_ + ''; + return this.value + ''; } } @@ -538,6 +554,54 @@ } } + class OutputAnswerProperty extends OutputProperty { + constructor() { + super(); + + /** @private {!Element} */ + this.container_ = document.createElement('div'); + this.container_.classList.add('pair-container'); + this.appendChild(this.container_); + + /** @type {!Element} */ + this.image_ = document.createElement('img'); + this.image_.classList.add('pair-item', 'image'); + this.container_.appendChild(this.image_); + + /** @type {!Element} */ + this.contents_ = document.createElement('div'); + this.contents_.classList.add('pair-item', 'contents'); + this.container_.appendChild(this.contents_); + + /** @type {!Element} */ + this.description_ = document.createElement('div'); + this.description_.classList.add('pair-item', 'description'); + this.container_.appendChild(this.description_); + + /** @type {!Element} */ + this.answer_ = document.createElement('div'); + this.answer_.classList.add('pair-item', 'answer'); + this.container_.appendChild(this.answer_); + } + + /** @param {string} imageData */ + setAnswerImageData(imageData) { + this.image_.src = imageData; + } + + /** @private @override */ + render_() { + this.contents_.textContent = this.values_[1]; + this.description_.textContent = this.values_[2]; + this.answer_.textContent = this.values_[3]; + } + + /** @override @return {string} */ + get text() { + return this.values_.join('.'); + } + } + class OutputBooleanProperty extends OutputProperty { constructor() { super(); @@ -554,7 +618,7 @@ } get text() { - return (this.value_ ? 'is: ' : 'not: ') + this.name; + return (this.value ? 'is: ' : 'not: ') + this.name; } } @@ -579,7 +643,7 @@ /** @override @return {string} */ get text() { - return JSON.stringify(this.value_, null, 2); + return JSON.stringify(this.value, null, 2); } /** @@ -627,23 +691,37 @@ /** @override @return {string} */ get text() { - return this.value_.reduce( + return this.value.reduce( (prev, {key, value}) => `${prev}${key}: ${value}\n`, ''); } } - class OutputLinkProperty extends OutputProperty { + class OutputUrlProperty extends OutputProperty { constructor() { super(); + + /** @private {!Element} */ + this.container_ = document.createElement('div'); + this.container_.classList.add('pair-container'); + this.appendChild(this.container_); + + /** @private {!Element} */ + this.icon_ = document.createElement('img'); + this.container_.appendChild(this.icon_); + /** @private {!Element} */ this.link_ = document.createElement('a'); - this.appendChild(this.link_); + this.container_.appendChild(this.link_); } /** @private @override */ render_() { - this.link_.textContent = this.value_; - this.link_.href = this.value_; + if (this.values_[1]) + this.icon_.removeAttribute('src'); + else + this.icon_.src = `chrome://favicon/${this.value}`; + this.link_.textContent = this.value; + this.link_.href = this.value; } } @@ -657,7 +735,7 @@ /** @private @override */ render_() { - this.div_.textContent = this.value_; + this.div_.textContent = this.value; } } @@ -786,10 +864,11 @@ 'The result score. Higher is more relevant.', ['relevance'], OutputTextProperty), new Column( - ['Contents', 'Description'], '', 'contentsAndDescription', true, + ['Contents', 'Description', 'Answer'], '', 'contentsAndDescription', + true, 'The text that is presented identifying the result. / The page title ' + 'of the result.', - ['contents', 'description'], OutputPairProperty), + ['image', 'contents', 'description', 'answer'], OutputAnswerProperty), new Column( ['D'], '', 'allowedToBeDefaultMatch', true, 'Can Be Default\nA green checkmark indicates that the result can be ' + @@ -808,7 +887,7 @@ ['hasTabMatch'], OutputBooleanProperty), new Column( ['URL'], '', 'destinationUrl', true, 'The URL for the result.', - ['destinationUrl'], OutputLinkProperty), + ['destinationUrl', 'isSearchType'], OutputUrlProperty), new Column( ['Fill', 'Inline'], '', 'fillAndInline', false, 'The text shown in the omnibox when the result is selected. / The ' + @@ -876,6 +955,8 @@ 'output-overlapping-pair-property', OutputOverlappingPairProperty, {extends: 'td'}); customElements.define( + 'output-answer-property', OutputAnswerProperty, {extends: 'td'}); + customElements.define( 'output-boolean-property', OutputBooleanProperty, {extends: 'td'}); customElements.define( 'output-json-property', OutputJsonProperty, {extends: 'td'}); @@ -883,7 +964,7 @@ 'output-key-value-tuple-property', OutputKeyValueTuplesProperty, {extends: 'td'}); customElements.define( - 'output-link-property', OutputLinkProperty, {extends: 'td'}); + 'output-url-property', OutputUrlProperty, {extends: 'td'}); customElements.define( 'output-text-property', OutputTextProperty, {extends: 'td'});
diff --git a/chrome/browser/resources/print_preview/data/BUILD.gn b/chrome/browser/resources/print_preview/data/BUILD.gn index a93e13c..7909d63 100644 --- a/chrome/browser/resources/print_preview/data/BUILD.gn +++ b/chrome/browser/resources/print_preview/data/BUILD.gn
@@ -34,7 +34,6 @@ "..:native_layer", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:event_tracker", - "//ui/webui/resources/js:webui_listener_tracker", "//ui/webui/resources/js/cr:event_target", ] }
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index aaf4a73..39bb6471 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -126,10 +126,10 @@ * A data store that stores destinations and dispatches events when the * data store changes. * @param {!print_preview.UserInfo} userInfo User information repository. - * @param {!WebUIListenerTracker} listenerTracker Tracker for WebUI - * listeners added in DestinationStore constructor. + * @param {function(string, !Function):void} addListenerCallback Function + * to call to add Web UI listeners in DestinationStore constructor. */ - constructor(userInfo, listenerTracker) { + constructor(userInfo, addListenerCallback) { super(); /** @@ -279,7 +279,9 @@ this.reset_(); - this.addWebUIEventListeners_(listenerTracker); + addListenerCallback('printers-added', this.onPrintersAdded_.bind(this)); + addListenerCallback( + 'reload-printer-list', this.onDestinationsReload.bind(this)); } /** @@ -343,19 +345,6 @@ } /** - * Starts listening for relevant WebUI events and adds the listeners to - * |listenerTracker|. |listenerTracker| is responsible for removing the - * listeners when necessary. - * @param {!WebUIListenerTracker} listenerTracker - * @private - */ - addWebUIEventListeners_(listenerTracker) { - listenerTracker.add('printers-added', this.onPrintersAdded_.bind(this)); - listenerTracker.add( - 'reload-printer-list', this.onDestinationsReload.bind(this)); - } - - /** * @param {(?print_preview.Destination | * ?print_preview.RecentDestination)} destination * @return {boolean} Whether the destination is valid.
diff --git a/chrome/browser/resources/print_preview/new/BUILD.gn b/chrome/browser/resources/print_preview/new/BUILD.gn index f0ded25..8dc6030 100644 --- a/chrome/browser/resources/print_preview/new/BUILD.gn +++ b/chrome/browser/resources/print_preview/new/BUILD.gn
@@ -76,7 +76,7 @@ "//ui/webui/resources/cr_elements:cr_container_shadow_behavior", "//ui/webui/resources/js:event_tracker", "//ui/webui/resources/js:util", - "//ui/webui/resources/js:webui_listener_tracker", + "//ui/webui/resources/js:web_ui_listener_behavior", "//ui/webui/resources/js/cr/ui:focus_outline_manager", ] }
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html index 1141f96..9e47084 100644 --- a/chrome/browser/resources/print_preview/new/app.html +++ b/chrome/browser/resources/print_preview/new/app.html
@@ -8,7 +8,7 @@ <link rel="import" href="chrome://resources/html/cr/ui/focus_outline_manager.html"> <link rel="import" href="chrome://resources/html/event_tracker.html"> <link rel="import" href="chrome://resources/html/util.html"> -<link rel="import" href="chrome://resources/html/webui_listener_tracker.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="../cloud_print_interface.html"> <link rel="import" href="../cloud_print_interface_manager.html">
diff --git a/chrome/browser/resources/print_preview/new/app.js b/chrome/browser/resources/print_preview/new/app.js index abe88463..0ee80c6 100644 --- a/chrome/browser/resources/print_preview/new/app.js +++ b/chrome/browser/resources/print_preview/new/app.js
@@ -14,7 +14,11 @@ Polymer({ is: 'print-preview-app', - behaviors: [SettingsBehavior, CrContainerShadowBehavior], + behaviors: [ + SettingsBehavior, + CrContainerShadowBehavior, + WebUIListenerBehavior, + ], properties: { /** @@ -142,9 +146,6 @@ 'close': 'onCrDialogClose_', }, - /** @private {?WebUIListenerTracker} */ - listenerTracker_: null, - /** @private {?print_preview.NativeLayer} */ nativeLayer_: null, @@ -179,14 +180,13 @@ this.nativeLayer_ = print_preview.NativeLayer.getInstance(); this.documentInfo_ = new print_preview.DocumentInfo(); this.userInfo_ = new print_preview.UserInfo(); - this.listenerTracker_ = new WebUIListenerTracker(); - this.listenerTracker_.add( + this.addWebUIListener( 'use-cloud-print', this.onCloudPrintEnable_.bind(this)); - this.listenerTracker_.add('print-failed', this.onPrintFailed_.bind(this)); - this.listenerTracker_.add( + this.addWebUIListener('print-failed', this.onPrintFailed_.bind(this)); + this.addWebUIListener( 'print-preset-options', this.onPrintPresetOptions_.bind(this)); this.destinationStore_ = new print_preview.DestinationStore( - this.userInfo_, this.listenerTracker_); + this.userInfo_, this.addWebUIListener.bind(this)); this.invitationStore_ = new print_preview.InvitationStore(this.userInfo_); this.tracker_.add(window, 'keydown', this.onKeyDown_.bind(this)); this.$.previewArea.setPluginKeyEventCallback(this.onKeyDown_.bind(this)); @@ -216,7 +216,6 @@ /** @override */ detached: function() { - this.listenerTracker_.removeAll(); this.tracker_.removeAll(); },
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 b2894017..9768d00 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
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> @@ -14,440 +15,351 @@ <dom-module id="settings-site-settings-page"> <template> <style include="settings-shared"> - .settings-box iron-icon + .middle { - padding-inline-start: 20px; + cr-link-row { + --cr-icon-button-margin-start: 20px; + } + + /* Add min-height to prevent shifting as sublabels load. */ + .two-line { + --cr-section-min-height: var(--cr-section-two-line-min-height); } </style> <template is="dom-if" if="[[enableSiteSettings_]]"> <div class="settings-box first line-only"> <h2 class="first">$i18n{siteSettingsAllSites}</h2> </div> - <div class="settings-box first line-only" category$="[[ALL_SITES]]" - data-route="SITE_SETTINGS_ALL" on-click="onTapNavigate_" actionable> - <div class="start">$i18n{siteSettingsAllSitesDescription}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsAllSitesDescription}"></button> - </paper-icon-button-light> - </div> + <cr-link-row + data-route="SITE_SETTINGS_ALL" + icon-class="subpage-arrow" + id="all-sites" + label="$i18n{siteSettingsAllSitesDescription}" + on-click="onTapNavigate_"> + </cr-link-row> <div class="settings-box first line-only"> <h2>$i18n{siteSettingsPermissions}</h2> </div> </template> - <div id="cookies" class="settings-box two-line first" - category$="[[ContentSettingsTypes.COOKIES]]" - data-route="SITE_SETTINGS_COOKIES" on-click="onTapNavigate_" actionable> - <iron-icon icon="settings:cookie"></iron-icon> - <div class="middle"> - $i18n{siteSettingsCookies} - <div class="secondary" id="cookiesSecondary"> - [[defaultSettingLabel_( - default_.cookies, - '$i18nPolymer{siteSettingsCookiesAllowed}', - '$i18nPolymer{siteSettingsBlocked}', - '$i18nPolymer{deleteDataPostSession}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsCookies}" - aria-describedby="cookiesSecondary"></button> - </paper-icon-button-light> - </div> - <div id="location" class="settings-box two-line" - category$="[[ContentSettingsTypes.GEOLOCATION]]" - data-route="SITE_SETTINGS_LOCATION" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:location-on"></iron-icon> - <div class="middle"> - $i18n{siteSettingsLocation} - <div class="secondary" id="locationSecondary"> - [[defaultSettingLabel_( - default_.location, - '$i18nPolymer{siteSettingsAskBeforeAccessing}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsLocation}" - aria-describedby="locationSecondary"></button> - </paper-icon-button-light> - </div> - <div id="camera" class="settings-box two-line" - category$="[[ContentSettingsTypes.CAMERA]]" + + <cr-link-row + class="two-line" + data-route="SITE_SETTINGS_COOKIES" + icon-class="subpage-arrow" + id="cookies" + label="$i18n{siteSettingsCookies}" + on-click="onTapNavigate_" + start-icon="settings:cookie" + sub-label="[[defaultSettingLabel_( + default_.cookies, + '$i18nPolymer{siteSettingsCookiesAllowed}', + '$i18nPolymer{siteSettingsBlocked}', + '$i18nPolymer{deleteDataPostSession}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_LOCATION" + icon-class="subpage-arrow" + id="location" + label="$i18n{siteSettingsLocation}" + on-click="onTapNavigate_" + start-icon="settings:location-on" + sub-label="[[defaultSettingLabel_( + default_.location, + '$i18nPolymer{siteSettingsAskBeforeAccessing}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" data-route="SITE_SETTINGS_CAMERA" - on-click="onTapNavigate_" actionable> - <iron-icon icon="settings:videocam"></iron-icon> - <div class="middle"> - $i18n{siteSettingsCamera} - <div class="secondary" id="cameraSecondary"> - [[defaultSettingLabel_( - default_.mediaStreamCamera, - '$i18nPolymer{siteSettingsAskBeforeAccessing}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsCamera}" - aria-describedby="cameraSecondary"></button> - </paper-icon-button-light> - </div> - <div id="microphone" class="settings-box two-line" - category$="[[ContentSettingsTypes.MIC]]" - data-route="SITE_SETTINGS_MICROPHONE" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:mic"></iron-icon> - <div class="middle"> - $i18n{siteSettingsMic} - <div class="secondary" id="micSecondary"> - [[defaultSettingLabel_( - default_.mediaStreamMic, - '$i18nPolymer{siteSettingsAskBeforeAccessing}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsMic}" - aria-describedby="micSecondary"></button> - </paper-icon-button-light> - </div> + icon-class="subpage-arrow" + id="camera" + label="$i18n{siteSettingsCamera}" + on-click="onTapNavigate_" + start-icon="settings:videocam" + sub-label="[[defaultSettingLabel_( + default_.mediaStreamCamera, + '$i18nPolymer{siteSettingsAskBeforeAccessing}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_MICROPHONE" + icon-class="subpage-arrow" + id="microphone" + label="$i18n{siteSettingsMic}" + on-click="onTapNavigate_" + start-icon="settings:mic" + sub-label="[[defaultSettingLabel_( + default_.mediaStreamMic, + '$i18nPolymer{siteSettingsAskBeforeAccessing}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + <template is="dom-if" if="[[enableSensorsContentSetting_]]"> - <div id="sensors" class="settings-box two-line" - category$="[[ContentSettingsTypes.SENSORS]]" - data-route="SITE_SETTINGS_SENSORS" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:sensors"></iron-icon> - <div class="middle"> - $i18n{siteSettingsSensors} - <div class="secondary" id="sensorsSecondary"> - [[defaultSettingLabel_( - default_.sensors, - '$i18nPolymer{siteSettingsSensorsAllow}', - '$i18nPolymer{siteSettingsSensorsBlock}')]] - </div> - </div> - <button class="subpage-arrow" is="paper-icon-button-light" - aria-label="$i18n{siteSettingsSensors}" - aria-describedby="sensorsSecondary"></button> - </div> + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_SENSORS" + icon-class="subpage-arrow" + id="sensors" + label="$i18n{siteSettingsSensors}" + on-click="onTapNavigate_" + start-icon="settings:sensors" + sub-label="[[defaultSettingLabel_( + default_.sensors, + '$i18nPolymer{siteSettingsSensorsAllow}', + '$i18nPolymer{siteSettingsSensorsBlock}')]]"> + </cr-link-row> </template> - <div id="notifications" class="settings-box two-line" - category$="[[ContentSettingsTypes.NOTIFICATIONS]]" - data-route="SITE_SETTINGS_NOTIFICATIONS" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:notifications"></iron-icon> - <div class="middle"> - $i18n{siteSettingsNotifications} - <div class="secondary" id="notificationsSecondary"> - [[defaultSettingLabel_( - default_.notifications, - '$i18nPolymer{siteSettingsAskBeforeSending}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsNotifications}" - aria-describedby="notificationsSecondary"></button> - </paper-icon-button-light> - </div> - <div id="javascript" class="settings-box two-line" - category$="[[ContentSettingsTypes.JAVASCRIPT]]" - data-route="SITE_SETTINGS_JAVASCRIPT" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:code"></iron-icon> - <div class="middle"> - $i18n{siteSettingsJavascript} - <div class="secondary" id="javascriptSecondary"> - [[defaultSettingLabel_( - default_.javascript, - '$i18nPolymer{siteSettingsAllowed}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsJavascript}" - aria-describedby="javascriptSecondary"></button> - </paper-icon-button-light> - </div> - <div id="flash" class="settings-box two-line" - category$="[[ContentSettingsTypes.PLUGINS]]" - data-route="SITE_SETTINGS_FLASH" on-click="onTapNavigate_" actionable> - <iron-icon icon="cr:extension"></iron-icon> - <div class="middle"> - $i18n{siteSettingsFlash} - <div class="secondary" id="flashSecondary"> - [[defaultSettingLabel_( - default_.plugins, - '$i18nPolymer{siteSettingsFlashAskFirst}', - '$i18nPolymer{siteSettingsFlashBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsFlash}" - aria-describedby="flashSecondary"></button> - </paper-icon-button-light> - </div> - <div id="images" class="settings-box two-line" - category$="[[ContentSettingsTypes.IMAGES]]" - data-route="SITE_SETTINGS_IMAGES" on-click="onTapNavigate_" actionable> - <iron-icon icon="settings:photo"></iron-icon> - <div class="middle"> - $i18n{siteSettingsImages} - <div class="secondary" id="imagesSecondary"> - [[defaultSettingLabel_( - default_.images, - '$i18nPolymer{siteSettingsShowAll}', - '$i18nPolymer{siteSettingsDontShowImages}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsImages}" - aria-describedby="imagesSecondary"></button> - </paper-icon-button-light> - </div> - <div id="popups" category$="[[ContentSettingsTypes.POPUPS]]" - class="settings-box two-line" data-route="SITE_SETTINGS_POPUPS" - on-click="onTapNavigate_" actionable> - <iron-icon icon="cr:open-in-new"></iron-icon> - <div class="middle"> - $i18n{siteSettingsPopups} - <div class="secondary" id="popupsSecondary"> - [[defaultSettingLabel_( - default_.popups, - '$i18nPolymer{siteSettingsAllowed}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsPopups}" - aria-describedby="popupsSecondary"></button> - </paper-icon-button-light> - </div> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_NOTIFICATIONS" + icon-class="subpage-arrow" + id="notifications" + label="$i18n{siteSettingsNotifications}" + on-click="onTapNavigate_" + start-icon="settings:notifications" + sub-label="[[defaultSettingLabel_( + default_.notifications, + '$i18nPolymer{siteSettingsAskBeforeSending}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_JAVASCRIPT" + icon-class="subpage-arrow" + id="javascript" + label="$i18n{siteSettingsJavascript}" + on-click="onTapNavigate_" + start-icon="settings:code" + sub-label="[[defaultSettingLabel_( + default_.javascript, + '$i18nPolymer{siteSettingsAllowed}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_FLASH" + icon-class="subpage-arrow" + id="flash" + label="$i18n{siteSettingsFlash}" + on-click="onTapNavigate_" + start-icon="cr:extension" + sub-label="[[defaultSettingLabel_( + default_.plugins, + '$i18nPolymer{siteSettingsFlashAskFirst}', + '$i18nPolymer{siteSettingsFlashBlock}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_IMAGES" + icon-class="subpage-arrow" + id="images" + label="$i18n{siteSettingsImages}" + on-click="onTapNavigate_" + start-icon="settings:photo" + sub-label="[[defaultSettingLabel_( + default_.images, + '$i18nPolymer{siteSettingsShowAll}', + '$i18nPolymer{siteSettingsDontShowImages}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_POPUPS" + icon-class="subpage-arrow" + id="popups" + label="$i18n{siteSettingsPopups}" + on-click="onTapNavigate_" + start-icon="cr:open-in-new" + sub-label="[[defaultSettingLabel_( + default_.popups, + '$i18nPolymer{siteSettingsAllowed}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> + <template is="dom-if" if="[[enableSafeBrowsingSubresourceFilter_]]"> - <div id="ads" class="settings-box two-line" - category$="[[ContentSettingsTypes.ADS]]" - data-route="SITE_SETTINGS_ADS" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:ads"></iron-icon> - <div class="middle"> - $i18n{siteSettingsAds} - <div class="secondary" id="adsSecondary"> - [[defaultSettingLabel_( - default_.ads, - '$i18nPolymer{siteSettingsAllowed}', - '$i18nPolymer{siteSettingsAdsBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsAds}" - aria-describedby="adsSecondary"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_ADS" + icon-class="subpage-arrow" + id="ads" + label="$i18n{siteSettingsAds}" + on-click="onTapNavigate_" + start-icon="settings:ads" + sub-label="[[defaultSettingLabel_( + default_.ads, + '$i18nPolymer{siteSettingsAllowed}', + '$i18nPolymer{siteSettingsAdsBlock}')]]"> + </cr-link-row> </template> - <div id="background-sync" class="settings-box two-line" - category$="[[ContentSettingsTypes.BACKGROUND_SYNC]]" - data-route="SITE_SETTINGS_BACKGROUND_SYNC" on-click="onTapNavigate_" - actionable> - <iron-icon icon="cr:sync"></iron-icon> - <div class="middle"> - $i18n{siteSettingsBackgroundSync} - <div class="secondary" id="backgroundSyncSecondary"> - [[defaultSettingLabel_( - default_.backgroundSync, - '$i18nPolymer{siteSettingsAllowRecentlyClosedSites}', - '$i18nPolymer{siteSettingsBackgroundSyncBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsBackgroundSync}" - aria-describedby="backgroundSyncSecondary"></button> - </paper-icon-button-light> - </div> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_BACKGROUND_SYNC" + icon-class="subpage-arrow" + id="background-sync" + label="$i18n{siteSettingsBackgroundSync}" + on-click="onTapNavigate_" + start-icon="cr:sync" + sub-label="[[defaultSettingLabel_( + default_.backgroundSync, + '$i18nPolymer{siteSettingsAllowRecentlyClosedSites}', + '$i18nPolymer{siteSettingsBackgroundSyncBlocked}')]]"> + </cr-link-row> + <template is="dom-if" if="[[enableSoundContentSetting_]]"> - <div id="sound" class="settings-box two-line" - category$="[[ContentSettingsTypes.SOUND]]" - data-route="SITE_SETTINGS_SOUND" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:volume-up"></iron-icon> - <div class="middle"> - $i18n{siteSettingsSound} - <div class="secondary" id="soundSecondary"> - [[defaultSettingLabel_( - default_.sound, - '$i18nPolymer{siteSettingsSoundAllow}', - '$i18nPolymer{siteSettingsSoundBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsSound}" - aria-describedby="soundSecondary"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_SOUND" + icon-class="subpage-arrow" + id="sound" + label="$i18n{siteSettingsSound}" + on-click="onTapNavigate_" + start-icon="settings:volume-up" + sub-label="[[defaultSettingLabel_( + default_.sound, + '$i18nPolymer{siteSettingsSoundAllow}', + '$i18nPolymer{siteSettingsSoundBlock}')]]"> + </cr-link-row> </template> - <div id="automatic-downloads" class="settings-box two-line" - category$="[[ContentSettingsTypes.AUTOMATIC_DOWNLOADS]]" + + <cr-link-row + class="hr two-line" data-route="SITE_SETTINGS_AUTOMATIC_DOWNLOADS" - on-click="onTapNavigate_" actionable> - <iron-icon icon="cr:file-download"></iron-icon> - <div class="middle"> - $i18n{siteSettingsAutomaticDownloads} - <div class="secondary" id="automaticDownloadsSecondary"> - [[defaultSettingLabel_( - default_.multipleAutomaticDownloads, - '$i18nPolymer{siteSettingsAutoDownloadAsk}', - '$i18nPolymer{siteSettingsAutoDownloadBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsAutomaticDownloads}" - aria-describedby="automaticDownloadsSecondary"></button> - </paper-icon-button-light> - </div> - <div id="unsandboxed-plugins" class="settings-box two-line" - category$="[[ContentSettingsTypes.UNSANDBOXED_PLUGINS]]" + icon-class="subpage-arrow" + id="automatic-downloads" + label="$i18n{siteSettingsAutomaticDownloads}" + on-click="onTapNavigate_" + start-icon="cr:file-download" + sub-label="[[defaultSettingLabel_( + default_.multipleAutomaticDownloads, + '$i18nPolymer{siteSettingsAutoDownloadAsk}', + '$i18nPolymer{siteSettingsAutoDownloadBlock}')]]"> + </cr-link-row> + + <cr-link-row + class="hr two-line" data-route="SITE_SETTINGS_UNSANDBOXED_PLUGINS" - on-click="onTapNavigate_" actionable> - <iron-icon icon="cr:extension"></iron-icon> - <div class="middle"> - $i18n{siteSettingsUnsandboxedPlugins} - <div class="secondary" id="unsandboxedPluginsSecondary"> - [[defaultSettingLabel_( - default_.ppapiBroker, - '$i18nPolymer{siteSettingsUnsandboxedPluginsAsk}', - '$i18nPolymer{siteSettingsUnsandboxedPluginsBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsUnsandboxedPlugins}" - aria-describedby="unsandboxedPluginsSecondary"></button> - </paper-icon-button-light> - </div> + icon-class="subpage-arrow" + id="unsandboxed-plugins" + label="$i18n{siteSettingsUnsandboxedPlugins}" + on-click="onTapNavigate_" + start-icon="cr:extension" + sub-label="[[defaultSettingLabel_( + default_.ppapiBroker, + '$i18nPolymer{siteSettingsUnsandboxedPluginsAsk}', + '$i18nPolymer{siteSettingsUnsandboxedPluginsBlock}')]]"> + </cr-link-row> + <template is="dom-if" if="[[!isGuest_]]"> - <div id="protocol-handlers" class="settings-box two-line" - category$="[[ContentSettingsTypes.PROTOCOL_HANDLERS]]" + <cr-link-row + class="hr two-line" data-route="SITE_SETTINGS_HANDLERS" - on-click="onTapNavigate_" actionable> - <iron-icon icon="settings:protocol-handler"></iron-icon> - <div class="middle"> - $i18n{siteSettingsHandlers} - <div class="secondary" id="handlersSecondary"> - [[defaultSettingLabel_( - default_.registerProtocolHandler, - '$i18nPolymer{siteSettingsHandlersAsk}', - '$i18nPolymer{siteSettingsHandlersBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsHandlers}" - aria-describedby="handlersSecondary"></button> - </paper-icon-button-light> - </div> + icon-class="subpage-arrow" + id="protocol-handlers" + label="$i18n{siteSettingsHandlers}" + on-click="onTapNavigate_" + start-icon="settings:protocol-handler" + sub-label="[[defaultSettingLabel_( + default_.registerProtocolHandler, + '$i18nPolymer{siteSettingsHandlersAsk}', + '$i18nPolymer{siteSettingsHandlersBlocked}')]]"> + </cr-link-row> </template> - <div id="midi-devices" class="settings-box two-line" - category$="[[ContentSettingsTypes.MIDI_DEVICES]]" + + <cr-link-row + class="hr two-line" data-route="SITE_SETTINGS_MIDI_DEVICES" - on-click="onTapNavigate_" actionable> - <iron-icon icon="settings:midi"></iron-icon> - <div class="middle"> - $i18n{siteSettingsMidiDevices} - <div class="secondary" id="midiDevicesSecondary"> - [[defaultSettingLabel_( - default_.midiSysex, - '$i18nPolymer{siteSettingsMidiDevicesAsk}', - '$i18nPolymer{siteSettingsMidiDevicesBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsMidiDevices}" - aria-describedby="midiDevicesSecondary"></button> - </paper-icon-button-light> - </div> - <div id="zoom-levels" class="settings-box" - category$="[[ContentSettingsTypes.ZOOM_LEVELS]]" - data-route="SITE_SETTINGS_ZOOM_LEVELS" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:zoom-in"></iron-icon> - <div class="middle">$i18n{siteSettingsZoomLevels}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsZoomLevels}"></button> - </paper-icon-button-light> - </div> - <div id="usb-devices" class="settings-box two-line" - category$="[[ContentSettingsTypes.USB_DEVICES]]" - data-route="SITE_SETTINGS_USB_DEVICES" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:usb"></iron-icon> - <div class="middle"> - $i18n{siteSettingsUsbDevices} - <div class="secondary" id="usbDevicesSecondary"> - [[defaultSettingLabel_( - default_.usbDevices, - '$i18nPolymer{siteSettingsUsbDevicesAsk}', - '$i18nPolymer{siteSettingsUsbDevicesBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsUsbDevices}" - area-describedby="usbDevicesSecondary"></button> - </paper-icon-button-light> - </div> - <div id="pdf-documents" class="settings-box" - data-route="SITE_SETTINGS_PDF_DOCUMENTS" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:pdf"></iron-icon> - <div class="middle">$i18n{siteSettingsPdfDocuments}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsPdfDocuments}"></button> - </paper-icon-button-light> - </div> - <div id="protected-content" class="settings-box" - data-route="SITE_SETTINGS_PROTECTED_CONTENT" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:protected-content"></iron-icon> - <div class="middle">$i18n{siteSettingsProtectedContent}</div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsProtectedContent}"></button> - </paper-icon-button-light> - </div> + icon-class="subpage-arrow" + id="midi-devices" + label="$i18n{siteSettingsMidiDevices}" + on-click="onTapNavigate_" + start-icon="settings:midi" + sub-label="[[defaultSettingLabel_( + default_.midiSysex, + '$i18nPolymer{siteSettingsMidiDevicesAsk}', + '$i18nPolymer{siteSettingsMidiDevicesBlock}')]]"> + </cr-link-row> + + <cr-link-row + class="hr" + data-route="SITE_SETTINGS_ZOOM_LEVELS" + icon-class="subpage-arrow" + id="zoom-levels" + label="$i18n{siteSettingsZoomLevels}" + on-click="onTapNavigate_" + start-icon="settings:zoom-in"> + </cr-link-row> + + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_USB_DEVICES" + icon-class="subpage-arrow" + id="usb-devices" + label="$i18n{siteSettingsUsbDevices}" + on-click="onTapNavigate_" + start-icon="settings:usb" + sub-label="[[defaultSettingLabel_( + default_.usbDevices, + '$i18nPolymer{siteSettingsUsbDevicesAsk}', + '$i18nPolymer{siteSettingsUsbDevicesBlock}')]]"> + </cr-link-row> + + <cr-link-row + class="hr" + data-route="SITE_SETTINGS_PDF_DOCUMENTS" + icon-class="subpage-arrow" + id="pdf-documents" + label="$i18n{siteSettingsPdfDocuments}" + on-click="onTapNavigate_" + start-icon="settings:pdf"> + </cr-link-row> + + <cr-link-row + class="hr" + data-route="SITE_SETTINGS_PROTECTED_CONTENT" + icon-class="subpage-arrow" + id="protected-content" + label="$i18n{siteSettingsProtectedContent}" + on-click="onTapNavigate_" + start-icon="settings:protected-content"> + </cr-link-row> + <template is="dom-if" if="[[enableClipboardContentSetting_]]"> - <div id="clipboard" class="settings-box two-line" - category$="[[ContentSettingsTypes.CLIPBOARD]]" - data-route="SITE_SETTINGS_CLIPBOARD" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:clipboard"></iron-icon> - <div class="middle"> - $i18n{siteSettingsClipboard} - <div class="secondary" id="clipboardSecondary"> - [[defaultSettingLabel_( - default_.clipboard, - '$i18nPolymer{siteSettingsAskBeforeAccessing}', - '$i18nPolymer{siteSettingsBlocked}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsClipboard}" - aria-describedby="clipboardSecondary"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_CLIPBOARD" + icon-class="subpage-arrow" + id="clipboard" + label="$i18n{siteSettingsClipboard}" + on-click="onTapNavigate_" + start-icon="settings:clipboard" + sub-label="[[defaultSettingLabel_( + default_.clipboard, + '$i18nPolymer{siteSettingsAskBeforeAccessing}', + '$i18nPolymer{siteSettingsBlocked}')]]"> + </cr-link-row> </template> <template is="dom-if" if="[[enablePaymentHandlerContentSetting_]]"> - <div id="paymentHandler" class="settings-box two-line" - category$="[[ContentSettingsTypes.PAYMENT_HANDLER]]" - data-route="SITE_SETTINGS_PAYMENT_HANDLER" on-click="onTapNavigate_" - actionable> - <iron-icon icon="settings:payment-handler"></iron-icon> - <div class="middle"> - $i18n{siteSettingsPaymentHandler} - <div class="secondary" id="paymentHandlerSecondary"> - [[defaultSettingLabel_( - default_.paymentHandler, - '$i18nPolymer{siteSettingsPaymentHandlerAllow}', - '$i18nPolymer{siteSettingsPaymentHandlerBlock}')]] - </div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label="$i18n{siteSettingsPaymentHandler}" - aria-describedby="paymentHandlerSecondary"></button> - </paper-icon-button-light> - </div> + <cr-link-row + class="hr two-line" + data-route="SITE_SETTINGS_PAYMENT_HANDLER" + icon-class="subpage-arrow" + id="paymentHandler" + label="$i18n{siteSettingsClipboard}" + on-click="onTapNavigate_" + start-icon="settings:payment-handler" + sub-label="[[defaultSettingLabel_( + default_.paymentHandler, + '$i18nPolymer{siteSettingsPaymentHandlerAllow}', + '$i18nPolymer{siteSettingsPaymentHandlerBlock}')]]"> + </cr-link-row> </template> </template> <script src="site_settings_page.js"></script>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js index c6213ed..c589b22 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -137,7 +137,7 @@ const route = pair[0]; const id = pair[1]; this.focusConfig.set(route.path, () => this.async(() => { - cr.ui.focusWithoutInk(assert(this.$$(`#${id} .subpage-arrow button`))); + cr.ui.focusWithoutInk(assert(this.$$(`#${id}`))); })); }); },
diff --git a/chrome/browser/signin/force_signin_verifier.cc b/chrome/browser/signin/force_signin_verifier.cc index 6ad8616..5cc5185 100644 --- a/chrome/browser/signin/force_signin_verifier.cc +++ b/chrome/browser/signin/force_signin_verifier.cc
@@ -9,11 +9,12 @@ #include "base/bind.h" #include "base/metrics/histogram_macros.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "components/signin/core/browser/signin_manager.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "content/public/browser/network_service_instance.h" #include "google_apis/gaia/gaia_constants.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/primary_account_access_token_fetcher.h" +#include "services/identity/public/cpp/primary_account_mutator.h" namespace { const net::BackoffEntry::Policy kForceSigninVerifierBackoffPolicy = { @@ -37,13 +38,10 @@ "Signin.ForceSigninVerificationTime.Failure"; ForceSigninVerifier::ForceSigninVerifier(Profile* profile) - : OAuth2TokenService::Consumer("force_signin_verifier"), - has_token_verified_(false), + : has_token_verified_(false), backoff_entry_(&kForceSigninVerifierBackoffPolicy), creation_time_(base::TimeTicks::Now()), - oauth2_token_service_( - ProfileOAuth2TokenServiceFactory::GetForProfile(profile)), - signin_manager_(SigninManagerFactory::GetForProfile(profile)) { + identity_manager_(IdentityManagerFactory::GetForProfile(profile)) { content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); UMA_HISTOGRAM_BOOLEAN(kForceSigninVerificationMetricsName, ShouldSendRequest()); @@ -54,9 +52,29 @@ Cancel(); } -void ForceSigninVerifier::OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) { +void ForceSigninVerifier::OnAccessTokenFetchComplete( + GoogleServiceAuthError error, + identity::AccessTokenInfo token_info) { + if (error.state() != GoogleServiceAuthError::NONE) { + if (error.IsPersistentError()) { + UMA_HISTOGRAM_MEDIUM_TIMES(kForceSigninVerificationFailureTimeMetricsName, + base::TimeTicks::Now() - creation_time_); + has_token_verified_ = true; + CloseAllBrowserWindows(); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver( + this); + Cancel(); + } else { + backoff_entry_.InformOfRequest(false); + backoff_request_timer_.Start( + FROM_HERE, backoff_entry_.GetTimeUntilRelease(), + base::BindOnce(&ForceSigninVerifier::SendRequest, + base::Unretained(this))); + access_token_fetcher_.reset(); + } + return; + } + UMA_HISTOGRAM_MEDIUM_TIMES(kForceSigninVerificationSuccessTimeMetricsName, base::TimeTicks::Now() - creation_time_); has_token_verified_ = true; @@ -64,26 +82,6 @@ Cancel(); } -void ForceSigninVerifier::OnGetTokenFailure( - const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) { - if (error.IsPersistentError()) { - UMA_HISTOGRAM_MEDIUM_TIMES(kForceSigninVerificationFailureTimeMetricsName, - base::TimeTicks::Now() - creation_time_); - has_token_verified_ = true; - CloseAllBrowserWindows(); - content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver( - this); - Cancel(); - } else { - backoff_entry_.InformOfRequest(false); - backoff_request_timer_.Start( - FROM_HERE, backoff_entry_.GetTimeUntilRelease(), - base::Bind(&ForceSigninVerifier::SendRequest, base::Unretained(this))); - access_token_request_.reset(); - } -} - void ForceSigninVerifier::OnConnectionChanged( network::mojom::ConnectionType type) { // Try again immediately once the network is back and cancel any pending @@ -98,7 +96,7 @@ void ForceSigninVerifier::Cancel() { backoff_entry_.Reset(); backoff_request_timer_.Stop(); - access_token_request_.reset(); + access_token_fetcher_.reset(); content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } @@ -123,30 +121,39 @@ return; } - std::string account_id = signin_manager_->GetAuthenticatedAccountId(); - OAuth2TokenService::ScopeSet oauth2_scopes; + identity::ScopeSet oauth2_scopes; oauth2_scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope); - access_token_request_ = - oauth2_token_service_->StartRequest(account_id, oauth2_scopes, this); + // It is safe to use Unretained(this) here given that the callback + // will not be invoked if this object is deleted. + access_token_fetcher_ = + std::make_unique<identity::PrimaryAccountAccessTokenFetcher>( + "force_signin_verifier", identity_manager_, oauth2_scopes, + base::BindOnce(&ForceSigninVerifier::OnAccessTokenFetchComplete, + base::Unretained(this)), + identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate); } bool ForceSigninVerifier::ShouldSendRequest() { - return !has_token_verified_ && access_token_request_.get() == nullptr && - signin_manager_->IsAuthenticated(); + return !has_token_verified_ && access_token_fetcher_.get() == nullptr && + identity_manager_->HasPrimaryAccount(); } void ForceSigninVerifier::CloseAllBrowserWindows() { // Do not close window if there is ongoing reauth. If it fails later, the // signin process should take care of the signout. - if (signin_manager_->AuthInProgress()) + auto* primary_account_mutator = identity_manager_->GetPrimaryAccountMutator(); + if (!primary_account_mutator || + primary_account_mutator->LegacyIsPrimaryAccountAuthInProgress()) return; - signin_manager_->SignOutAndRemoveAllAccounts( + primary_account_mutator->ClearPrimaryAccount( + identity::PrimaryAccountMutator::ClearAccountsAction::kRemoveAll, signin_metrics::AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN, signin_metrics::SignoutDelete::IGNORE_METRIC); } -OAuth2TokenService::Request* ForceSigninVerifier::GetRequestForTesting() { - return access_token_request_.get(); +identity::PrimaryAccountAccessTokenFetcher* +ForceSigninVerifier::GetAccessTokenFetcherForTesting() { + return access_token_fetcher_.get(); } net::BackoffEntry* ForceSigninVerifier::GetBackoffEntryForTesting() {
diff --git a/chrome/browser/signin/force_signin_verifier.h b/chrome/browser/signin/force_signin_verifier.h index 1df2c5e1..74633ebc 100644 --- a/chrome/browser/signin/force_signin_verifier.h +++ b/chrome/browser/signin/force_signin_verifier.h
@@ -11,12 +11,17 @@ #include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "google_apis/gaia/oauth2_token_service.h" +#include "google_apis/gaia/google_service_auth_error.h" #include "net/base/backoff_entry.h" #include "services/network/public/cpp/network_connection_tracker.h" class Profile; -class SigninManager; + +namespace identity { +class IdentityManager; +class PrimaryAccountAccessTokenFetcher; +struct AccessTokenInfo; +} // namespace identity extern const char kForceSigninVerificationMetricsName[]; extern const char kForceSigninVerificationSuccessTimeMetricsName[]; @@ -26,18 +31,13 @@ // into memory by the first time via gaia server. It will retry on any transient // error. class ForceSigninVerifier - : public OAuth2TokenService::Consumer, - public network::NetworkConnectionTracker::NetworkConnectionObserver { + : public network::NetworkConnectionTracker::NetworkConnectionObserver { public: explicit ForceSigninVerifier(Profile* profile); ~ForceSigninVerifier() override; - // override OAuth2TokenService::Consumer - void OnGetTokenSuccess( - const OAuth2TokenService::Request* request, - const OAuth2AccessTokenConsumer::TokenResponse& token_response) override; - void OnGetTokenFailure(const OAuth2TokenService::Request* request, - const GoogleServiceAuthError& error) override; + void OnAccessTokenFetchComplete(GoogleServiceAuthError error, + identity::AccessTokenInfo token_info); // override network::NetworkConnectionTracker::NetworkConnectionObserver void OnConnectionChanged(network::mojom::ConnectionType type) override; @@ -66,12 +66,13 @@ virtual void CloseAllBrowserWindows(); - OAuth2TokenService::Request* GetRequestForTesting(); + identity::PrimaryAccountAccessTokenFetcher* GetAccessTokenFetcherForTesting(); net::BackoffEntry* GetBackoffEntryForTesting(); base::OneShotTimer* GetOneShotTimerForTesting(); private: - std::unique_ptr<OAuth2TokenService::Request> access_token_request_; + std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> + access_token_fetcher_; // Indicates whether the verification is finished successfully or with a // persistent error. @@ -80,8 +81,7 @@ base::OneShotTimer backoff_request_timer_; base::TimeTicks creation_time_; - OAuth2TokenService* oauth2_token_service_; - SigninManager* signin_manager_; + identity::IdentityManager* identity_manager_; DISALLOW_COPY_AND_ASSIGN(ForceSigninVerifier); };
diff --git a/chrome/browser/signin/force_signin_verifier_unittest.cc b/chrome/browser/signin/force_signin_verifier_unittest.cc index a74e8610..26c249e9 100644 --- a/chrome/browser/signin/force_signin_verifier_unittest.cc +++ b/chrome/browser/signin/force_signin_verifier_unittest.cc
@@ -7,14 +7,11 @@ #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" -#include "chrome/browser/signin/fake_signin_manager_builder.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/test/base/testing_profile.h" -#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" #include "content/public/browser/network_service_instance.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "services/identity/public/cpp/identity_test_environment.h" #include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,7 +25,9 @@ int FailureCount() { return GetBackoffEntryForTesting()->failure_count(); } - OAuth2TokenService::Request* request() { return GetRequestForTesting(); } + identity::PrimaryAccountAccessTokenFetcher* access_token_fetcher() { + return GetAccessTokenFetcherForTesting(); + } MOCK_METHOD0(CloseAllBrowserWindows, void(void)); }; @@ -38,20 +37,12 @@ public network::NetworkConnectionTracker::NetworkConnectionObserver { public: void SetUp() override { - TestingProfile::Builder builder; - builder.AddTestingFactory( - SigninManagerFactory::GetInstance(), - base::BindRepeating(&BuildFakeSigninManagerForTesting)); - builder.AddTestingFactory( - ProfileOAuth2TokenServiceFactory::GetInstance(), - base::BindRepeating(&BuildFakeProfileOAuth2TokenService)); - profile_ = builder.Build(); - FakeSigninManager* signin_manager_ = static_cast<FakeSigninManager*>( - SigninManagerFactory::GetForProfile(profile_.get())); - signin_manager_->SignIn("fake_id", "fake_username", "fake_password"); - - oauth2_token_service()->GetDelegate()->UpdateCredentials("fake_id", - "fake_token"); + profile_ = IdentityTestEnvironmentProfileAdaptor:: + CreateProfileForIdentityTestEnvironment(); + identity_test_env_profile_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get()); + account_info_ = + identity_test_env()->MakePrimaryAccountAvailable("email@test.com"); } void TearDown() override { verifier_.reset(); } @@ -60,14 +51,17 @@ wait_for_network_type_change_.QuitWhenIdle(); } - FakeProfileOAuth2TokenService* oauth2_token_service() { - return static_cast<FakeProfileOAuth2TokenService*>( - ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())); + identity::IdentityTestEnvironment* identity_test_env() { + return identity_test_env_profile_adaptor_->identity_test_env(); } std::unique_ptr<MockForceSigninVerifier> verifier_; content::TestBrowserThreadBundle bundle_; std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_profile_adaptor_; + + AccountInfo account_info_; base::RunLoop wait_for_network_type_change_; base::RunLoop wait_for_network_type_async_return_; @@ -83,17 +77,15 @@ TEST_F(ForceSigninVerifierTest, OnGetTokenSuccess) { verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->HasTokenBeenVerified()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); EXPECT_CALL(*verifier_.get(), CloseAllBrowserWindows()).Times(0); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - ASSERT_EQ(1u, service->GetPendingRequests().size()); - service->IssueAllTokensForAccount("fake_id", - OAuth2AccessTokenConsumer::TokenResponse()); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + account_info_.account_id, /*token=*/"", base::Time()); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_TRUE(verifier_->HasTokenBeenVerified()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); ASSERT_EQ(0, verifier_->FailureCount()); @@ -108,16 +100,15 @@ TEST_F(ForceSigninVerifierTest, OnGetTokenPersistentFailure) { verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->HasTokenBeenVerified()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); EXPECT_CALL(*verifier_.get(), CloseAllBrowserWindows()).Times(1); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - ASSERT_EQ(1u, service->GetPendingRequests().size()); - service->IssueErrorForAllPendingRequests(persistent_error_); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + persistent_error_); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_TRUE(verifier_->HasTokenBeenVerified()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); ASSERT_EQ(0, verifier_->FailureCount()); @@ -132,16 +123,15 @@ TEST_F(ForceSigninVerifierTest, OnGetTokenTransientFailure) { verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->HasTokenBeenVerified()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); EXPECT_CALL(*verifier_.get(), CloseAllBrowserWindows()).Times(0); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - ASSERT_EQ(1u, service->GetPendingRequests().size()); - service->IssueErrorForAllPendingRequests(transient_error_); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + transient_error_); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->HasTokenBeenVerified()); ASSERT_TRUE(verifier_->IsDelayTaskPosted()); ASSERT_EQ(1, verifier_->FailureCount()); @@ -158,12 +148,11 @@ content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - ASSERT_EQ(1u, service->GetPendingRequests().size()); - service->IssueErrorForAllPendingRequests(transient_error_); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + transient_error_); ASSERT_EQ(1, verifier_->FailureCount()); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_TRUE(verifier_->IsDelayTaskPosted()); network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType( @@ -172,7 +161,7 @@ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); ASSERT_EQ(0, verifier_->FailureCount()); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); } @@ -181,12 +170,11 @@ content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - ASSERT_EQ(1u, service->GetPendingRequests().size()); - service->IssueErrorForAllPendingRequests(transient_error_); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + transient_error_); ASSERT_EQ(1, verifier_->FailureCount()); - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); ASSERT_TRUE(verifier_->IsDelayTaskPosted()); network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType( @@ -195,7 +183,7 @@ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); ASSERT_EQ(0, verifier_->FailureCount()); - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); ASSERT_FALSE(verifier_->IsDelayTaskPosted()); } @@ -206,7 +194,7 @@ verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); // There is no network type at first. - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); // Waiting for the network type returns. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -214,7 +202,7 @@ wait_for_network_type_async_return_.Run(); // Get the type and send the request. - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); } TEST_F(ForceSigninVerifierTest, LaunchVerifierWithoutNetwork) { @@ -226,7 +214,7 @@ verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); // There is no network type. - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); // Waiting for the network type returns. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -234,7 +222,7 @@ wait_for_network_type_async_return_.Run(); // Get the type, there is no network connection, don't send the request. - ASSERT_EQ(nullptr, verifier_->request()); + ASSERT_EQ(nullptr, verifier_->access_token_fetcher()); // Network is resumed. content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); @@ -244,7 +232,7 @@ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); // Send the request. - ASSERT_NE(nullptr, verifier_->request()); + ASSERT_NE(nullptr, verifier_->access_token_fetcher()); } TEST_F(ForceSigninVerifierTest, ChangeNetworkFromWIFITo4GWithOnGoingRequest) { @@ -254,9 +242,8 @@ false); verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - EXPECT_EQ(nullptr, verifier_->request()); + EXPECT_EQ(nullptr, verifier_->access_token_fetcher()); // Waiting for the network type returns. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -264,9 +251,8 @@ wait_for_network_type_async_return_.Run(); // The network type if wifi, send the request. - auto* first_request = verifier_->request(); + auto* first_request = verifier_->access_token_fetcher(); EXPECT_NE(nullptr, first_request); - EXPECT_EQ(1u, service->GetPendingRequests().size()); // Network is changed to 4G. content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); @@ -276,8 +262,9 @@ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); // There is still one on-going request. - EXPECT_EQ(first_request, verifier_->request()); - EXPECT_EQ(1u, service->GetPendingRequests().size()); + EXPECT_EQ(first_request, verifier_->access_token_fetcher()); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + account_info_.account_id, /*token=*/"", base::Time()); } TEST_F(ForceSigninVerifierTest, ChangeNetworkFromWIFITo4GWithFinishedRequest) { @@ -287,9 +274,8 @@ false); verifier_ = std::make_unique<MockForceSigninVerifier>(profile_.get()); - FakeProfileOAuth2TokenService* service = oauth2_token_service(); - EXPECT_EQ(nullptr, verifier_->request()); + EXPECT_EQ(nullptr, verifier_->access_token_fetcher()); // Waiting for the network type returns. base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -297,12 +283,12 @@ wait_for_network_type_async_return_.Run(); // The network type if wifi, send the request. - EXPECT_NE(nullptr, verifier_->request()); + EXPECT_NE(nullptr, verifier_->access_token_fetcher()); // Finishes the request. - service->IssueAllTokensForAccount("fake_id", - OAuth2AccessTokenConsumer::TokenResponse()); - EXPECT_EQ(nullptr, verifier_->request()); + identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( + account_info_.account_id, /*token=*/"", base::Time()); + EXPECT_EQ(nullptr, verifier_->access_token_fetcher()); // Network is changed to 4G. content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); @@ -312,5 +298,5 @@ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); // No more request because it's verfied already. - EXPECT_EQ(nullptr, verifier_->request()); + EXPECT_EQ(nullptr, verifier_->access_token_fetcher()); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index b1723f8d..98b2856 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -564,6 +564,7 @@ deps += [ "//chrome/browser/ui/webui/eoc_internals:mojo_bindings", "//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings", + "//chrome/browser/ui/webui/feed_internals:mojo_bindings", "//chrome/browser/ui/webui/snippets_internals:mojo_bindings", ] } @@ -719,6 +720,10 @@ "webui/explore_sites_internals/explore_sites_internals_page_handler.h", "webui/explore_sites_internals/explore_sites_internals_ui.cc", "webui/explore_sites_internals/explore_sites_internals_ui.h", + "webui/feed_internals/feed_internals_page_handler.cc", + "webui/feed_internals/feed_internals_page_handler.h", + "webui/feed_internals/feed_internals_ui.cc", + "webui/feed_internals/feed_internals_ui.h", "webui/offline/offline_internals_ui.cc", "webui/offline/offline_internals_ui.h", "webui/offline/offline_internals_ui_message_handler.cc", @@ -2775,6 +2780,8 @@ "views/tabs/tab_controller.h", "views/tabs/tab_drag_controller.cc", "views/tabs/tab_drag_controller.h", + "views/tabs/tab_hover_card_bubble_view.cc", + "views/tabs/tab_hover_card_bubble_view.h", "views/tabs/tab_icon.cc", "views/tabs/tab_icon.h", "views/tabs/tab_strip.cc",
diff --git a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc index e508ca1c..061b016 100644 --- a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc +++ b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
@@ -6,7 +6,7 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/command_line.h" #include "base/macros.h" #include "build/build_config.h"
diff --git a/chrome/browser/ui/ash/network/networking_config_chromeos_browsertest.cc b/chrome/browser/ui/ash/network/networking_config_chromeos_browsertest.cc index 5cd935a7..2f28227 100644 --- a/chrome/browser/ui/ash/network/networking_config_chromeos_browsertest.cc +++ b/chrome/browser/ui/ash/network/networking_config_chromeos_browsertest.cc
@@ -4,7 +4,7 @@ #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/ash/shelf_browsertest.cc b/chrome/browser/ui/ash/shelf_browsertest.cc index 09df5f1d..c9bdcb08 100644 --- a/chrome/browser/ui/ash/shelf_browsertest.cc +++ b/chrome/browser/ui/ash/shelf_browsertest.cc
@@ -4,7 +4,7 @@ #include "ash/public/cpp/shelf_prefs.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shelf_test_api.mojom.h" +#include "ash/public/interfaces/shelf_test_api.test-mojom.h" #include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/ash/system_tray_client_browsertest.cc b/chrome/browser/ui/ash/system_tray_client_browsertest.cc index d56244c..2a45095 100644 --- a/chrome/browser/ui/ash/system_tray_client_browsertest.cc +++ b/chrome/browser/ui/ash/system_tray_client_browsertest.cc
@@ -6,7 +6,7 @@ #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/i18n/time_formatting.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/login/login_manager_test.h"
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc index 8e934eb..0fb85bba 100644 --- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -8,7 +8,7 @@ #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/interfaces/ash_message_center_controller.mojom.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/system_tray_test_api.mojom.h" +#include "ash/public/interfaces/system_tray_test_api.test-mojom.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/media/router/media_routes_observer.h"
diff --git a/chrome/browser/ui/ash/tablet_mode_client_test_util.cc b/chrome/browser/ui/ash/tablet_mode_client_test_util.cc index 6f48cd03..19131ed1 100644 --- a/chrome/browser/ui/ash/tablet_mode_client_test_util.cc +++ b/chrome/browser/ui/ash/tablet_mode_client_test_util.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/run_loop.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chrome/browser/ui/ash/tablet_mode_client_observer.h"
diff --git a/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc b/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc index 18059148..53b8af8 100644 --- a/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc +++ b/chrome/browser/ui/ash/time_to_first_present_recorder_browsertest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/time_to_first_present_recorder_test_api.mojom.h" +#include "ash/public/interfaces/time_to_first_present_recorder_test_api.test-mojom.h" #include "base/command_line.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/common/service_manager_connection.h"
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm index 3ff33b4..337c3e2 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -140,6 +140,10 @@ bridge_->GotFaviconData(item, image_result); } + void CancelFaviconRequest(HistoryMenuBridge::HistoryItem* item) { + bridge_->CancelFaviconRequest(item); + } + std::unique_ptr<MockBridge> bridge_; }; @@ -347,6 +351,9 @@ // Make sure the item was modified properly. EXPECT_TRUE(item.icon_requested); EXPECT_NE(base::CancelableTaskTracker::kBadTaskId, item.icon_task_id); + + // Cancel the request. + CancelFaviconRequest(&item); } TEST_F(HistoryMenuBridgeTest, GotFaviconData) { @@ -360,6 +367,9 @@ item.menu_item.reset([[NSMenuItem alloc] init]); GetFaviconForHistoryItem(&item); + // Cancel the request so there will be no race. + CancelFaviconRequest(&item); + // Pretend to be called back. favicon_base::FaviconImageResult image_result; image_result.image = gfx::Image::CreateFrom1xBitmap(bitmap);
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h index cef93c0..abe629b9 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h
@@ -105,6 +105,13 @@ void ToggleTabFullscreen_Internal(bool enter_fullscreen, bool retry_until_success); +#if defined(OS_MACOSX) + // On Mac, entering into the system fullscreen mode can tickle crashes in + // the WindowServer (c.f. https://crbug.com/828031), so provide a fake for + // testing. + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen_window_; +#endif + base::test::ScopedFeatureList scoped_feature_list_; base::WeakPtrFactory<FullscreenControllerTest> weak_ptr_factory_;
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc index 742f3f3e..8a0f983 100644 --- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc +++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -394,13 +394,8 @@ kFwd, kIgnoreCase, NULL, NULL)); } -#if defined(OS_WIN) -#define MAYBE_LargePage DISABLED_LargePage -#else -#define MAYBE_LargePage LargePage -#endif // Find in a very large page. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, MAYBE_LargePage) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, LargePage) { WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); ui_test_utils::NavigateToURL(browser(), GetURL("largepage.html")); @@ -409,15 +404,8 @@ kFwd, kIgnoreCase, NULL)); } -// https://crbug.com/825341: Flaky timeout on Win7 Tests (dbg)(1) -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_FindLongString DISABLED_FindLongString -#else -#define MAYBE_FindLongString FindLongString -#endif - // Find a very long string in a large page. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, MAYBE_FindLongString) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindLongString) { WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); ui_test_utils::NavigateToURL(browser(), GetURL("largepage.html")); @@ -445,9 +433,8 @@ kFwd, kIgnoreCase, NULL)); } -// http://crbug.com/369169, http://crbug.com/733286 // Search Back and Forward on a single occurrence. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, DISABLED_SingleOccurrence) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, SingleOccurrence) { WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); ui_test_utils::NavigateToURL(browser(), GetURL("FindRandomTests.html")); @@ -789,9 +776,7 @@ // Make sure we don't get into an infinite loop when text box contains very // large amount of text. -// Disable the test as it started being flaky, see http://crbug/367701. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, - DISABLED_FindRestarts_Issue70505) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindRestarts_Issue70505) { // First we navigate to our page. GURL url = GetURL(kLongTextareaPage); ui_test_utils::NavigateToURL(browser(), url); @@ -807,9 +792,7 @@ } // This tests bug 11761: FindInPage terminates search prematurely. -// This test is not expected to pass until bug 11761 is fixed. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, - DISABLED_FindInPagePrematureEnd) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindInPagePrematureEnd) { // First we navigate to our special focus tracking page. GURL url = GetURL(kPrematureEnd); ui_test_utils::NavigateToURL(browser(), url); @@ -891,18 +874,10 @@ EXPECT_TRUE(fully_visible); } -// FindDisappearOnNewTabAndHistory is flaky, at least on Mac. -// See http://crbug.com/43072 -#if defined(OS_MACOSX) -#define MAYBE_FindDisappearOnNewTabAndHistory DISABLED_FindDisappearOnNewTabAndHistory -#else -#define MAYBE_FindDisappearOnNewTabAndHistory FindDisappearOnNewTabAndHistory -#endif - // Make sure Find box disappears when History/Downloads page is opened, and // when a New Tab is opened. IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, - MAYBE_FindDisappearOnNewTabAndHistory) { + FindDisappearOnNewTabAndHistory) { // First we navigate to our special focus tracking page. GURL url = GetURL(kSimple); ui_test_utils::NavigateToURL(browser(), url); @@ -992,18 +967,9 @@ EXPECT_EQ(position.x(), start_position.x()); } -// FindNextInNewTabUsesPrepopulate times-out on Mac and Aura. -// See http://crbug.com/43070 -#if defined(OS_MACOSX) || defined(USE_AURA) -#define MAYBE_FindNextInNewTabUsesPrepopulate \ - DISABLED_FindNextInNewTabUsesPrepopulate -#else -#define MAYBE_FindNextInNewTabUsesPrepopulate FindNextInNewTabUsesPrepopulate -#endif - // Make sure F3 in a new tab works if Find has previous string to search for. IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, - MAYBE_FindNextInNewTabUsesPrepopulate) { + FindNextInNewTabUsesPrepopulate) { // First we navigate to any page. GURL url = GetURL(kSimple); ui_test_utils::NavigateToURL(browser(), url); @@ -1279,17 +1245,9 @@ EXPECT_EQ(ASCIIToUTF16("page"), GetFindBarText()); } -// TODO(rohitrao): Searching in incognito tabs does not work in browser tests in -// Linux views. Investigate and fix. http://crbug.com/40948 -#if defined(OS_LINUX) && defined(TOOLKIT_VIEWS) -#define MAYBE_NoIncognitoPrepopulate DISABLED_NoIncognitoPrepopulate -#else -#define MAYBE_NoIncognitoPrepopulate NoIncognitoPrepopulate -#endif - // This tests that search terms entered into an incognito find bar are not used // as prepopulate terms for non-incognito windows. -IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, MAYBE_NoIncognitoPrepopulate) { +IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, NoIncognitoPrepopulate) { FindBar* find_bar = browser()->GetFindBarController()->find_bar(); if (find_bar->HasGlobalFindPasteboard()) return;
diff --git a/chrome/browser/ui/find_bar/find_bar_host_interactive_uitest.cc b/chrome/browser/ui/find_bar/find_bar_host_interactive_uitest.cc index 1c08e1d..404669c1 100644 --- a/chrome/browser/ui/find_bar/find_bar_host_interactive_uitest.cc +++ b/chrome/browser/ui/find_bar/find_bar_host_interactive_uitest.cc
@@ -60,13 +60,7 @@ // This tests the FindInPage end-state, in other words: what is focused when you // close the Find box (ie. if you find within a link the link should be // focused). -// Flaky on CrOS. -#if defined(OS_CHROMEOS) -#define MAYBE_FindInPageEndState DISABLED_FindInPageEndState -#else -#define MAYBE_FindInPageEndState FindInPageEndState -#endif -IN_PROC_BROWSER_TEST_F(FindInPageInteractiveTest, MAYBE_FindInPageEndState) { +IN_PROC_BROWSER_TEST_F(FindInPageInteractiveTest, FindInPageEndState) { ASSERT_TRUE(embedded_test_server()->Start()); // Make sure Chrome is in the foreground, otherwise sending input
diff --git a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc index e114037..7b79a7bb 100644 --- a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc +++ b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc
@@ -18,6 +18,10 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/ui_base_features.h" +#if defined(OS_MACOSX) +#include "ui/base/test/scoped_fake_nswindow_fullscreen.h" +#endif + namespace { // Javascript snippet used to verify the keyboard lock API exists. @@ -103,6 +107,10 @@ base::test::ScopedFeatureList scoped_feature_list_; net::EmbeddedTestServer https_test_server_; +#if defined(OS_MACOSX) + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen_; +#endif + DISALLOW_COPY_AND_ASSIGN(KeyboardLockInteractiveBrowserTest); };
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index 5d7db03..684c64b 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -334,9 +334,9 @@ continue; } // TODO(jdonnelly, rhalavati): Create a helper function with Callback to - // create annotation and pass it to image_service, merging this annotation - // and the one in - // chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc + // create annotation and pass it to image_service, merging the annotations + // in omnibox_page_handler.cc, chrome_omnibox_client.cc, + // and chrome_autocomplete_provider_client.cc. constexpr net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("omnibox_result_change", R"( semantics {
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc index 616a072..60cc1a0d 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -15,6 +15,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/search.h" @@ -28,9 +29,7 @@ #include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_factory.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/toolbar/app_menu_model.h" -#include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" #include "components/favicon_base/favicon_types.h" #include "components/feature_engagement/buildflags.h" #include "components/prefs/scoped_user_pref_update.h" @@ -42,13 +41,9 @@ #include "ui/base/accelerators/accelerator.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/resources/grit/ui_resources.h" - -#if !defined(OS_MACOSX) -#include "chrome/app/vector_icons/vector_icons.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" -#endif +#include "ui/resources/grit/ui_resources.h" namespace { @@ -80,10 +75,6 @@ // shown in the menu. const int kMaxLocalEntries = 8; -// Index of the separator that follows the history menu item. Used as a -// reference position for inserting local entries. -const int kHistorySeparatorIndex = 1; - // Comparator function for use with std::sort that will sort sessions by // descending modified_time (i.e., most recent first). bool SortSessionsByRecency(const sync_sessions::SyncedSession* s1, @@ -131,11 +122,9 @@ return command_id - kFirstLocalWindowCommandId; } -#if !defined(OS_MACOSX) gfx::Image CreateFavicon(const gfx::VectorIcon& icon) { return gfx::Image(gfx::CreateVectorIcon(icon, 16, gfx::kChromeIconGrey)); } -#endif } // namespace @@ -172,9 +161,6 @@ GURL url; }; -const int RecentTabsSubMenuModel::kRecentlyClosedHeaderCommandId = 1120; -const int RecentTabsSubMenuModel::kDisabledRecentlyClosedHeaderCommandId = 1121; - RecentTabsSubMenuModel::RecentTabsSubMenuModel( ui::AcceleratorProvider* accelerator_provider, Browser* browser) @@ -183,14 +169,9 @@ session_sync_service_( SessionSyncServiceFactory::GetInstance()->GetForProfile( browser->profile())), - last_local_model_index_(kHistorySeparatorIndex), default_favicon_( ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( - IDR_DEFAULT_FAVICON)), -#if !defined(OS_MACOSX) - tab_restore_service_observer_(this), -#endif // !defined(OS_MACOSX) - weak_ptr_factory_(this) { + IDR_DEFAULT_FAVICON)) { // Invoke asynchronous call to load tabs from local last session, which does // nothing if the tabs have already been loaded or they shouldn't be loaded. // TabRestoreServiceChanged() will be called after the tabs are loaded. @@ -198,15 +179,9 @@ TabRestoreServiceFactory::GetForProfile(browser_->profile()); if (service) { service->LoadTabsFromLastSession(); - -// Mac doesn't support the dynamic menu. -#if !defined(OS_MACOSX) tab_restore_service_observer_.Add(service); -#endif } -// Mac doesn't support the dynamic menu. -#if !defined(OS_MACOSX) if (session_sync_service_) { // Using a weak pointer below for simplicity although, strictly speaking, // it's not needed because the subscription itself should take care. @@ -216,7 +191,6 @@ &RecentTabsSubMenuModel::OnForeignSessionUpdated, weak_ptr_factory_.GetWeakPtr())); } -#endif // !defined(OS_MACOSX) Build(); @@ -235,13 +209,10 @@ } bool RecentTabsSubMenuModel::IsCommandIdEnabled(int command_id) const { - if (command_id == kRecentlyClosedHeaderCommandId || - command_id == kDisabledRecentlyClosedHeaderCommandId || - command_id == IDC_RECENT_TABS_NO_DEVICE_TABS || - IsDeviceNameCommandId(command_id)) { - return false; - } - return true; + return command_id != kRecentlyClosedHeaderCommandId && + command_id != kDisabledRecentlyClosedHeaderCommandId && + command_id != IDC_RECENT_TABS_NO_DEVICE_TABS && + !IsDeviceNameCommandId(command_id); } bool RecentTabsSubMenuModel::GetAcceleratorForCommandId( @@ -433,13 +404,7 @@ InsertItemWithStringIdAt(++last_local_model_index_, kRecentlyClosedHeaderCommandId, IDS_RECENTLY_CLOSED); -#if defined(OS_MACOSX) - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetIcon(last_local_model_index_, - rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW)); -#else SetIcon(last_local_model_index_, CreateFavicon(kTabIcon)); -#endif int added_count = 0; for (const auto& entry : service->entries()) { @@ -549,12 +514,7 @@ // See comments in BuildLocalEntries() about usage of InsertItem*At(). InsertItemAt(curr_model_index, command_id, l10n_util::GetPluralStringFUTF16( IDS_RECENTLY_CLOSED_WINDOW, num_tabs)); -#if defined(OS_MACOSX) - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetIcon(curr_model_index, rb.GetNativeImageNamed(IDR_RECENTLY_CLOSED_WINDOW)); -#else SetIcon(curr_model_index, CreateFavicon(kTabIcon)); -#endif local_window_items_.push_back(window_id); } @@ -580,30 +540,6 @@ void RecentTabsSubMenuModel::AddDeviceFavicon( int index_in_menu, sync_pb::SyncEnums::DeviceType device_type) { -#if defined(OS_MACOSX) - int favicon_id = -1; - switch (device_type) { - case sync_pb::SyncEnums::TYPE_PHONE: - favicon_id = IDR_PHONE_FAVICON; - break; - - case sync_pb::SyncEnums::TYPE_TABLET: - favicon_id = IDR_TABLET_FAVICON; - break; - - case sync_pb::SyncEnums::TYPE_CROS: - case sync_pb::SyncEnums::TYPE_WIN: - case sync_pb::SyncEnums::TYPE_MAC: - case sync_pb::SyncEnums::TYPE_LINUX: - case sync_pb::SyncEnums::TYPE_OTHER: - case sync_pb::SyncEnums::TYPE_UNSET: - favicon_id = IDR_LAPTOP_FAVICON; - break; - } - - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - SetIcon(index_in_menu, rb.GetNativeImageNamed(favicon_id)); -#else const gfx::VectorIcon* favicon = nullptr; switch (device_type) { case sync_pb::SyncEnums::TYPE_PHONE: @@ -625,7 +561,6 @@ } SetIcon(index_in_menu, CreateFavicon(*favicon)); -#endif } void RecentTabsSubMenuModel::AddTabFavicon(int command_id, const GURL& url) {
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h index 87b2a6dc..e36446cf 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -56,8 +56,8 @@ public: // Command Id for recently closed items header or disabled item to which the // accelerator string will be appended. - static const int kRecentlyClosedHeaderCommandId; - static const int kDisabledRecentlyClosedHeaderCommandId; + static constexpr int kRecentlyClosedHeaderCommandId = 1120; + static constexpr int kDisabledRecentlyClosedHeaderCommandId = 1121; // Exposed for tests only: return the Command Id for the first entry in the // recently closed window items list. @@ -82,9 +82,12 @@ private: struct TabNavigationItem; - typedef std::vector<TabNavigationItem> TabNavigationItems; + using TabNavigationItems = std::vector<TabNavigationItem>; + using WindowItems = std::vector<SessionID>; - typedef std::vector<SessionID> WindowItems; + // Index of the separator that follows the history menu item. Used as a + // reference position for inserting local entries. + static constexpr int kHistorySeparatorIndex = 1; // Build the menu items by populating the menumodel. void Build(); @@ -174,7 +177,7 @@ // Index of the last local entry (recently closed tab or window) in the // menumodel. - int last_local_model_index_; + int last_local_model_index_ = kHistorySeparatorIndex; gfx::Image default_favicon_; @@ -184,16 +187,13 @@ // Time the menu is open for until a recent tab is selected. base::ElapsedTimer menu_opened_timer_; -// Mac doesn't support the dynamic menu. -#if !defined(OS_MACOSX) ScopedObserver<sessions::TabRestoreService, RecentTabsSubMenuModel> - tab_restore_service_observer_; -#endif + tab_restore_service_observer_{this}; std::unique_ptr<base::CallbackList<void()>::Subscription> foreign_session_updated_subscription_; - base::WeakPtrFactory<RecentTabsSubMenuModel> weak_ptr_factory_; + base::WeakPtrFactory<RecentTabsSubMenuModel> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(RecentTabsSubMenuModel); };
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc index 0ef7a74..5b457ce7 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
@@ -271,17 +271,8 @@ EXPECT_FALSE(model.GetURLAndTitleForItemAtIndex(6, &url, &title)); } -// TODO(sail): enable this test when dynamic model is enabled in -// RecentTabsSubMenuModel. -#if defined(OS_MACOSX) -#define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \ - DISABLED_RecentlyClosedTabsAndWindowsFromLastSession -#else -#define MAYBE_RecentlyClosedTabsAndWindowsFromLastSession \ - RecentlyClosedTabsAndWindowsFromLastSession -#endif TEST_F(RecentTabsSubMenuModelTest, - MAYBE_RecentlyClosedTabsAndWindowsFromLastSession) { + RecentlyClosedTabsAndWindowsFromLastSession) { DisableSync(); TabRestoreServiceFactory::GetInstance()->SetTestingFactory( @@ -508,13 +499,7 @@ EXPECT_TRUE(model.GetURLAndTitleForItemAtIndex(12, &url, &title)); } -// Mac doesn't support the dynamic menu. -#if defined(OS_MACOSX) -#define MAYBE_OtherDevicesDynamicUpdate DISABLED_OtherDevicesDynamicUpdate -#else -#define MAYBE_OtherDevicesDynamicUpdate OtherDevicesDynamicUpdate -#endif -TEST_F(RecentTabsSubMenuModelTest, MAYBE_OtherDevicesDynamicUpdate) { +TEST_F(RecentTabsSubMenuModelTest, OtherDevicesDynamicUpdate) { // Create menu with disabled synchronization. DisableSync();
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc index 97f9584..cf373a5 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_container.cc
@@ -32,6 +32,7 @@ #if BUILDFLAG(ENABLE_APP_LIST) #include "ash/public/cpp/app_list/app_list_constants.h" #include "third_party/skia/include/core/SkPaint.h" +#include "ui/native_theme/native_theme.h" #include "ui/views/background.h" #endif @@ -135,7 +136,8 @@ explicit AppListDialogContainer(views::View* dialog_body) : BaseDialogContainer(dialog_body, base::RepeatingClosure()) { SetBackground(std::make_unique<AppListOverlayBackground>()); - close_button_ = views::BubbleFrameView::CreateCloseButton(this); + close_button_ = views::BubbleFrameView::CreateCloseButton( + this, GetNativeTheme()->SystemDarkModeEnabled()); AddChildView(close_button_); } ~AppListDialogContainer() override {}
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.h b/chrome/browser/ui/views/frame/browser_frame_mac.h index 26dccf4..0e3b7ae 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mac.h +++ b/chrome/browser/ui/views/frame/browser_frame_mac.h
@@ -29,7 +29,7 @@ BrowserWindowTouchBarController* GetTouchBarController() const; // Overridden from views::NativeWidgetMac: - int SheetPositionY() override; + int32_t SheetOffsetY() override; void GetWindowFrameTitlebarHeight(bool* override_titlebar_height, float* titlebar_height) override; void OnFocusWindowToolbar() override;
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm index 9fc237d..4c59e51 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mac.mm +++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -118,15 +118,12 @@ //////////////////////////////////////////////////////////////////////////////// // BrowserFrameMac, views::NativeWidgetMac implementation: -int BrowserFrameMac::SheetPositionY() { +int32_t BrowserFrameMac::SheetOffsetY() { + // ModalDialogHost::GetDialogPosition() is relative to the host view. In + // practice, this ends up being the widget's content view. web_modal::WebContentsModalDialogHost* dialog_host = browser_view_->GetWebContentsModalDialogHost(); - NSView* view = dialog_host->GetHostView().GetNativeNSView(); - // Get the position of the host view relative to the window since - // ModalDialogHost::GetDialogPosition() is relative to the host view. - int host_view_y = - [view convertPoint:NSMakePoint(0, NSHeight([view frame])) toView:nil].y; - return host_view_y - dialog_host->GetDialogPosition(gfx::Size()).y(); + return dialog_host->GetDialogPosition(gfx::Size()).y(); } void BrowserFrameMac::GetWindowFrameTitlebarHeight(
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 20c5474e..123fb73 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -15,8 +15,8 @@ #include "ash/public/cpp/vector_icons/vector_icons.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shelf_test_api.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shelf_test_api.test-mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/shell.h" // mash-ok #include "ash/wm/overview/window_selector_controller.h" // mash-ok
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc index d3d963d5..adf434d 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -7,7 +7,7 @@ #include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/macros.h" #include "base/test/test_mock_time_task_runner.h" #include "chrome/browser/extensions/extension_browsertest.h"
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc index f8ebb69..72275a1 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -25,6 +25,10 @@ #include "ui/aura/test/env_test_helper.h" #endif +#if defined(OS_MACOSX) +#include "ui/base/test/scoped_fake_nswindow_fullscreen.h" +#endif + using ZoomBubbleBrowserTest = InProcessBrowserTest; namespace { @@ -42,6 +46,10 @@ // Test whether the zoom bubble is anchored and whether it is visible when in // non-immersive fullscreen. IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, NonImmersiveFullscreen) { +#if defined(OS_MACOSX) + ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen; +#endif + BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); content::WebContents* web_contents = browser_view->GetActiveWebContents();
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc index 820b6f5..c85d61e1 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
@@ -145,13 +145,7 @@ CastDialogView* dialog_ = nullptr; }; -// Flaky on Mac. https://crbug.com/843599 -#if defined(OS_MACOSX) -#define MAYBE_ShowAndHideDialog DISABLED_ShowAndHideDialog -#else -#define MAYBE_ShowAndHideDialog ShowAndHideDialog -#endif -TEST_F(CastDialogViewTest, MAYBE_ShowAndHideDialog) { +TEST_F(CastDialogViewTest, ShowAndHideDialog) { EXPECT_FALSE(CastDialogView::IsShowing()); EXPECT_EQ(nullptr, CastDialogView::GetCurrentDialogWidget());
diff --git a/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc b/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc index f2a9da5..5d30d90 100644 --- a/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc +++ b/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc
@@ -270,15 +270,7 @@ TestOpenDialogFromContextMenu(); } -// Disabled on macOS due to many timeouts. Seems fine on all other platforms. -// crbug.com/849146 -#if defined(OS_MACOSX) -#define MAYBE_OpenDialogFromAppMenu DISABLED_OpenDialogFromAppMenu -#else -#define MAYBE_OpenDialogFromAppMenu OpenDialogFromAppMenu -#endif -IN_PROC_BROWSER_TEST_F(MediaRouterWebUIBrowserTest, - MAYBE_OpenDialogFromAppMenu) { +IN_PROC_BROWSER_TEST_F(MediaRouterWebUIBrowserTest, OpenDialogFromAppMenu) { TestOpenDialogFromAppMenu(); } @@ -287,12 +279,8 @@ TestEphemeralToolbarIconForDialog(); } -// Flaky on chromeos, linux, win: https://crbug.com/658005 -// Flaky on MacViews: https://crbug.com/817408 -// TODO(https://crbug.com/678472): Replace this test case with a Views version. -// Close out the bugs above when doing so. IN_PROC_BROWSER_TEST_F(MediaRouterWebUIBrowserTest, - DISABLED_OpenDialogWithMediaRouterAction) { + OpenDialogWithMediaRouterAction) { // We start off at about:blank page. // Make sure there is 1 tab and media router is enabled. ASSERT_EQ(1, browser()->tab_strip_model()->count()); @@ -322,15 +310,7 @@ SetAlwaysShowActionPref(false); } -#if defined(MEMORY_SANITIZER) -// Flaky crashes. crbug.com/863945 -#define MAYBE_OpenDialogsInMultipleTabs DISABLED_OpenDialogsInMultipleTabs -#else -#define MAYBE_OpenDialogsInMultipleTabs OpenDialogsInMultipleTabs -#endif - -IN_PROC_BROWSER_TEST_F(MediaRouterWebUIBrowserTest, - MAYBE_OpenDialogsInMultipleTabs) { +IN_PROC_BROWSER_TEST_F(MediaRouterWebUIBrowserTest, OpenDialogsInMultipleTabs) { // Start with two tabs. chrome::NewTab(browser()); ASSERT_EQ(2, browser()->tab_strip_model()->count());
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc index e89d18f..6ddd485 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc
@@ -190,15 +190,8 @@ } #endif -#if defined(OS_MACOSX) -// https://crbug.com/828031 -#define MAYBE_LocationBarViewShown DISABLED_LocationBarViewShown -#else -#define MAYBE_LocationBarViewShown LocationBarViewShown -#endif - IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowViewBrowserTest, - MAYBE_LocationBarViewShown) { + LocationBarViewShown) { receiver_view_->ShowInactiveFullscreen(); receiver_view_->ExitFullscreen(); ASSERT_FALSE(receiver_view_->IsFullscreen()); @@ -211,15 +204,8 @@ EXPECT_LT(0, location_bar_view->height()); } -#if defined(OS_MACOSX) -// https://crbug.com/828031 -#define MAYBE_ShowPageInfoDialog DISABLED_ShowPageInfoDialog -#else -#define MAYBE_ShowPageInfoDialog ShowPageInfoDialog -#endif - IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowViewBrowserTest, - MAYBE_ShowPageInfoDialog) { + ShowPageInfoDialog) { content::NavigationController::LoadURLParams load_params(GURL("about:blank")); fake_delegate_->web_contents()->GetController().LoadURLWithParams( load_params);
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc index 2d68226..0771154 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -7,7 +7,7 @@ #include <memory> #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h"
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 1fe42b4..0a987432 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -35,6 +35,7 @@ #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_close_button.h" #include "chrome/browser/ui/views/tabs/tab_controller.h" +#include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" #include "chrome/browser/ui/views/tabs/tab_icon.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_style.h" @@ -176,8 +177,7 @@ focus_ring_ = views::FocusRing::Install(this); } -Tab::~Tab() { -} +Tab::~Tab() = default; void Tab::AnimationEnded(const gfx::Animation* animation) { if (animation == &title_animation_) @@ -396,6 +396,7 @@ } bool Tab::OnKeyPressed(const ui::KeyEvent& event) { + controller_->UpdateHoverCard(this, false); if (event.key_code() == ui::VKEY_SPACE && !IsSelected()) { controller_->SelectTab(this); return true; @@ -415,6 +416,7 @@ } // namespace bool Tab::OnMousePressed(const ui::MouseEvent& event) { + controller_->UpdateHoverCard(this, false); controller_->OnMouseEventInTab(this, event); // Allow a right click from touch to drag, which corresponds to a long click. @@ -511,6 +513,7 @@ hover_controller_.Show(GlowHoverController::SUBTLE); UpdateForegroundColors(); Layout(); + controller_->UpdateHoverCard(this, true); } void Tab::OnMouseExited(const ui::MouseEvent& event) { @@ -521,6 +524,7 @@ } void Tab::OnGestureEvent(ui::GestureEvent* event) { + controller_->UpdateHoverCard(this, false); switch (event->type()) { case ui::ET_GESTURE_TAP_DOWN: { // TAP_DOWN is only dispatched for the first touch point. @@ -720,8 +724,10 @@ if (old.pinned != data_.pinned) showing_alert_indicator_ = false; - if (data_.alert_state != old.alert_state || data_.title != old.title) + if (data_.alert_state != old.alert_state || data_.title != old.title) { TooltipTextChanged(); + controller_->UpdateHoverCard(this, mouse_hovered_); + } Layout(); SchedulePaint(); @@ -916,8 +922,6 @@ if (showing_icon_) available_width -= favicon_width; - // Show the close button if it's allowed to show on hover, even if it's - // forced to be hidden normally. showing_close_button_ &= large_enough_for_close_button; if (showing_close_button_) available_width -= close_button_width;
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index ba529af..ccf70fd3 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -108,6 +108,10 @@ virtual void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) = 0; + // Updates hover-card content, anchoring and visibility based on what tab is + // hovered and whether the card should be shown. + virtual void UpdateHoverCard(Tab* tab, bool should_show) = 0; + // Returns whether |tab| needs to be painted. When this returns true, |clip| // is set to the path which should be clipped out of the current tab's region // (for hit testing or painting), if any. |clip| is only non-empty when
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc new file mode 100644 index 0000000..877afbaa --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -0,0 +1,79 @@ +// 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. + +#include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/views/tabs/tab_renderer_data.h" +#include "components/url_formatter/url_formatter.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/layout_provider.h" +#include "ui/views/widget/widget.h" + +TabHoverCardBubbleView::TabHoverCardBubbleView(views::View* anchor_view, + TabRendererData data) + : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) { + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); + // Set so that when hovering over a tab in a inactive window that window will + // not become active. Setting this to false creates the need to explicitly + // hide the hovercard on press, touch, and keyboard events. + set_can_activate(false); + + title_label_ = new views::Label(); + domain_label_ = new views::Label(); + UpdateCardContent(data); + + title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + title_label_->SetMultiLine(false); + title_label_->SetFontList(views::Label::GetDefaultFontList().Derive( + 1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM)); + title_label_->SetEnabledColor(gfx::kGoogleGrey800); + domain_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + domain_label_->SetMultiLine(false); + domain_label_->SetEnabledColor(gfx::kGoogleGrey500); + + AddChildView(title_label_); + AddChildView(domain_label_); + widget_ = views::BubbleDialogDelegateView::CreateBubble(this); +} + +TabHoverCardBubbleView::~TabHoverCardBubbleView() = default; + +void TabHoverCardBubbleView::Show() { + widget_->Show(); +} + +void TabHoverCardBubbleView::Hide() { + widget_->Hide(); +} + +void TabHoverCardBubbleView::UpdateCardContent(TabRendererData data) { + title_label_->SetText(data.title); + + base::string16 domain = url_formatter::FormatUrl( + data.url, + url_formatter::kFormatUrlOmitUsernamePassword | + url_formatter::kFormatUrlOmitHTTPS | + url_formatter::kFormatUrlOmitHTTP | + url_formatter::kFormatUrlOmitTrailingSlashOnBareHostname | + url_formatter::kFormatUrlOmitTrivialSubdomains | + url_formatter::kFormatUrlTrimAfterHost, + net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr); + domain_label_->SetText(domain); +} + +void TabHoverCardBubbleView::UpdateCardAnchor(View* tab) { + views::BubbleDialogDelegateView::SetAnchorView(tab); +} + +int TabHoverCardBubbleView::GetDialogButtons() const { + return ui::DIALOG_BUTTON_NONE; +} + +gfx::Size TabHoverCardBubbleView::CalculatePreferredSize() const { + const gfx::Size size = BubbleDialogDelegateView::CalculatePreferredSize(); + return gfx::Size(240, size.height()); +}
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h new file mode 100644 index 0000000..c828a38 --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h
@@ -0,0 +1,47 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_ + +#include "ui/views/bubble/bubble_dialog_delegate_view.h" + +namespace views { +class Label; +class Widget; +} // namespace views +struct TabRendererData; + +// Dialog that displays an informational hover card containing page information. +class TabHoverCardBubbleView : public views::BubbleDialogDelegateView { + public: + TabHoverCardBubbleView(views::View* anchor_view, TabRendererData data); + + ~TabHoverCardBubbleView() override; + + // Creates (if not already created) and shows the widget. + void Show(); + + void Hide(); + + // Updates and formats title and domain with given data. + void UpdateCardContent(TabRendererData data); + + // Updates where the card should be anchored. + void UpdateCardAnchor(View* tab); + + // BubbleDialogDelegateView: + int GetDialogButtons() const override; + + private: + friend class TabHoverCardBubbleViewBrowserTest; + + views::Widget* widget_ = nullptr; + views::Label* title_label_; + views::Label* domain_label_; + + gfx::Size CalculatePreferredSize() const override; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_HOVER_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_browsertest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_browsertest.cc new file mode 100644 index 0000000..9cf3ca5 --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_browsertest.cc
@@ -0,0 +1,169 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/browser_features.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/tab.h" +#include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/ui_test_utils.h" +#include "ui/views/controls/label.h" +#include "ui/views/widget/widget.h" + +using views::Widget; + +class TabHoverCardBubbleViewBrowserTest : public DialogBrowserTest { + public: + TabHoverCardBubbleViewBrowserTest() = default; + ~TabHoverCardBubbleViewBrowserTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(features::kTabHoverCards); + DialogBrowserTest::SetUp(); + } + + static TabHoverCardBubbleView* GetHoverCard(const TabStrip* tabstrip) { + return tabstrip->hover_card_; + } + + static Widget* GetHoverCardWidget(const TabHoverCardBubbleView* hover_card) { + return hover_card->widget_; + } + + const base::string16& GetHoverCardTitle( + const TabHoverCardBubbleView* hover_card) { + return hover_card->title_label_->text(); + } + + const base::string16& GetHoverCardDomain( + const TabHoverCardBubbleView* hover_card) { + return hover_card->domain_label_->text(); + } + + void MouseExitTabStrip() { + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + ui::MouseEvent stop_hover_event(ui::ET_MOUSE_EXITED, gfx::Point(), + gfx::Point(), base::TimeTicks(), + ui::EF_NONE, 0); + tab_strip->OnMouseExited(stop_hover_event); + } + + void ClickMouseOnTab() { + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + Tab* tab = tab_strip->tab_at(0); + ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + base::TimeTicks(), ui::EF_NONE, 0); + tab->OnMousePressed(click_event); + } + + void HoverMouseOverTabAt(int index) { + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + Tab* tab = tab_strip->tab_at(index); + ui::MouseEvent hover_event(ui::ET_MOUSE_ENTERED, gfx::Point(), gfx::Point(), + base::TimeTicks(), ui::EF_NONE, 0); + tab->OnMouseEntered(hover_event); + } + + // DialogBrowserTest: + void ShowUi(const std::string& name) override { + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + Tab* tab = tab_strip->tab_at(0); + ui::MouseEvent hover_event(ui::ET_MOUSE_ENTERED, gfx::Point(), gfx::Point(), + base::TimeTicks(), ui::EF_NONE, 0); + tab->OnMouseEntered(hover_event); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TabHoverCardBubbleViewBrowserTest); + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewBrowserTest, + InvokeUi_tab_hover_card) { + ShowAndVerifyUi(); +} + +// Verify hover card is visible while hovering and not visible outside of the +// tabstrip. +IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewBrowserTest, + WidgetVisibleOnHover) { + ShowUi("default"); + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + TabHoverCardBubbleView* hover_card = GetHoverCard(tab_strip); + Widget* widget = GetHoverCardWidget(hover_card); + + EXPECT_TRUE(widget != nullptr); + EXPECT_TRUE(widget->IsVisible()); + MouseExitTabStrip(); + EXPECT_FALSE(widget->IsVisible()); +} + +// Verify hover card is not visible after clicking on a tab. +IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewBrowserTest, + WidgetNotVisibleOnClick) { + ShowUi("default"); + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + TabHoverCardBubbleView* hover_card = GetHoverCard(tab_strip); + Widget* widget = GetHoverCardWidget(hover_card); + + EXPECT_TRUE(widget != nullptr); + EXPECT_TRUE(widget->IsVisible()); + ClickMouseOnTab(); + EXPECT_FALSE(widget->IsVisible()); +} + +// Verify title, domain, and anchor are correctly updated when moving hover +// from one tab to another. +IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewBrowserTest, WidgetDataUpdate) { + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + TabRendererData newTabData = TabRendererData(); + newTabData.title = base::UTF8ToUTF16("Test Tab 2"); + newTabData.url = GURL("http://example.com/this/should/not/be/seen"); + tab_strip->AddTabAt(1, newTabData, false); + + ShowUi("default"); + TabHoverCardBubbleView* hover_card = GetHoverCard(tab_strip); + Widget* widget = GetHoverCardWidget(hover_card); + + EXPECT_TRUE(widget != nullptr); + EXPECT_TRUE(widget->IsVisible()); + HoverMouseOverTabAt(1); + EXPECT_TRUE(widget != nullptr); + EXPECT_TRUE(widget->IsVisible()); + Tab* tab = tab_strip->tab_at(1); + EXPECT_EQ(GetHoverCardTitle(hover_card), base::UTF8ToUTF16("Test Tab 2")); + EXPECT_EQ(GetHoverCardDomain(hover_card), base::UTF8ToUTF16("example.com")); + EXPECT_EQ(hover_card->GetAnchorView(), static_cast<views::View*>(tab)); +} + +// Verify inactive window remains inactive when showing a hover card for a tab +// in the inactive window. +IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewBrowserTest, + InactiveWindowStaysInactiveOnHover) { + ShowUi("default"); + BrowserView::GetBrowserViewForBrowser(browser())->Deactivate(); + ASSERT_FALSE(BrowserView::GetBrowserViewForBrowser(browser())->IsActive()); + TabStrip* tab_strip = + BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); + Tab* tab = tab_strip->tab_at(0); + ui::MouseEvent hover_event(ui::ET_MOUSE_ENTERED, gfx::Point(), gfx::Point(), + base::TimeTicks(), ui::EF_NONE, 0); + tab->OnMouseEntered(hover_event); + ASSERT_FALSE(BrowserView::GetBrowserViewForBrowser(browser())->IsActive()); +}
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 57e10c7f..54ea15c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -15,6 +15,7 @@ #include "base/compiler_specific.h" #include "base/containers/adapters.h" #include "base/containers/flat_map.h" +#include "base/feature_list.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -23,6 +24,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "cc/paint/paint_flags.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/defaults.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/layout_constants.h" @@ -33,6 +35,7 @@ #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" +#include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_layout.h" #include "chrome/browser/ui/views/tabs/tab_strip_observer.h" @@ -1158,6 +1161,29 @@ UpdateStackedLayoutFromMouseEvent(source, event); } +void TabStrip::UpdateHoverCard(Tab* tab, bool should_show) { + if (!base::FeatureList::IsEnabled(features::kTabHoverCards)) + return; + + if (!hover_card_ && !should_show) + return; + + // The view tracker is used to prevent us from accessing the hover card after + // it has been deleted by the owning widget. + if (!hover_card_ || !hover_card_view_tracker_.view()) { + hover_card_ = new TabHoverCardBubbleView(tab, tab->data()); + hover_card_view_tracker_.SetView(hover_card_); + } + + if (should_show) { + hover_card_->UpdateCardContent(tab->data()); + hover_card_->UpdateCardAnchor(tab); + hover_card_->Show(); + } else { + hover_card_->Hide(); + } +} + bool TabStrip::ShouldPaintTab(const Tab* tab, float scale, gfx::Path* clip) { if (!MaySetClip()) return true; @@ -2781,6 +2807,10 @@ SetResetToShrinkOnExit(true); } +void TabStrip::OnMouseExited(const ui::MouseEvent& event) { + UpdateHoverCard(nullptr, false); +} + void TabStrip::OnGestureEvent(ui::GestureEvent* event) { SetResetToShrinkOnExit(false); switch (event->type()) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index cfcd87a2..b335e94 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -34,11 +34,13 @@ #include "ui/views/view.h" #include "ui/views/view_model.h" #include "ui/views/view_targeter_delegate.h" +#include "ui/views/view_tracker.h" class NewTabButton; class StackedTabStripLayout; class Tab; class TabDragController; +class TabHoverCardBubbleView; class TabStripController; class TabStripObserver; @@ -276,6 +278,7 @@ const Tab* GetAdjacentTab(const Tab* tab, int offset) override; void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) override; + void UpdateHoverCard(Tab* tab, bool should_show) override; bool ShouldPaintTab(const Tab* tab, float scale, gfx::Path* clip) override; int GetStrokeThickness() const override; bool CanPaintThrobberToLayer() const override; @@ -329,6 +332,7 @@ friend class TabDragController; friend class TabDragControllerTest; + friend class TabHoverCardBubbleViewBrowserTest; friend class TabStripTest; // Used during a drop session of a url. Tracks the position of the drop as @@ -623,6 +627,7 @@ void OnMouseCaptureLost() override; void OnMouseMoved(const ui::MouseEvent& event) override; void OnMouseEntered(const ui::MouseEvent& event) override; + void OnMouseExited(const ui::MouseEvent& event) override; // ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override; @@ -647,6 +652,11 @@ views::ViewModelT<Tab> tabs_; TabsClosingMap tabs_closing_map_; + // The view tracker is used to keep track of if the hover card has been + // destroyed by its widget. + TabHoverCardBubbleView* hover_card_ = nullptr; + views::ViewTracker hover_card_view_tracker_; + std::unique_ptr<TabStripController> controller_; // The "New Tab" button.
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index e0e1abca..b213e97 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -85,6 +85,7 @@ } void OnMouseEventInTab(views::View* source, const ui::MouseEvent& event) override {} + void UpdateHoverCard(Tab* tab, bool hovered) override {} bool ShouldPaintTab(const Tab* tab, float scale, gfx::Path* clip) override { return true; }
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index f62f7be..294caa8 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -119,6 +119,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h" #include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h" +#include "chrome/browser/ui/webui/feed_internals/feed_internals_ui.h" #include "chrome/browser/ui/webui/offline/offline_internals_ui.h" #include "chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h" #include "chrome/browser/ui/webui/webapks_ui.h" @@ -534,9 +535,12 @@ if (url.host_piece() == chrome::kChromeUIOfflineInternalsHost) return &NewWebUI<OfflineInternalsUI>; if (url.host_piece() == chrome::kChromeUISnippetsInternalsHost && - !profile->IsOffTheRecord() && - !base::FeatureList::IsEnabled(feed::kInterestFeedContentSuggestions)) - return &NewWebUI<SnippetsInternalsUI>; + !profile->IsOffTheRecord()) { + if (base::FeatureList::IsEnabled(feed::kInterestFeedContentSuggestions)) + return &NewWebUI<FeedInternalsUI>; + else + return &NewWebUI<SnippetsInternalsUI>; + } if (url.host_piece() == chrome::kChromeUIWebApksHost) return &NewWebUI<WebApksUI>; #else // !defined(OS_ANDROID)
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc index dbb5da7..ab90e90 100644 --- a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc +++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" #include "ash/public/interfaces/constants.mojom.h" -#include "ash/public/interfaces/shell_test_api.mojom.h" +#include "ash/public/interfaces/shell_test_api.test-mojom.h" #include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/common/webui_url_constants.h"
diff --git a/chrome/browser/ui/webui/feed_internals/BUILD.gn b/chrome/browser/ui/webui/feed_internals/BUILD.gn new file mode 100644 index 0000000..a5a9762 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/BUILD.gn
@@ -0,0 +1,11 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojo_bindings") { + sources = [ + "feed_internals.mojom", + ] +}
diff --git a/chrome/browser/ui/webui/feed_internals/OWNERS b/chrome/browser/ui/webui/feed_internals/OWNERS new file mode 100644 index 0000000..ee60b75 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/OWNERS
@@ -0,0 +1,4 @@ +file://components/feed/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals.mojom b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom new file mode 100644 index 0000000..30142d68 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom
@@ -0,0 +1,11 @@ +// 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. + +module feed_internals.mojom; + +// Browser interface for the page. Consists of calls for data and hooks for +// interactivity. +interface PageHandler { + // TODO(chouinard): Implement this. +};
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc new file mode 100644 index 0000000..8732a01 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
@@ -0,0 +1,13 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h" + +#include <utility> + +FeedInternalsPageHandler::FeedInternalsPageHandler( + feed_internals::mojom::PageHandlerRequest request) + : binding_(this, std::move(request)) {} + +FeedInternalsPageHandler::~FeedInternalsPageHandler() = default;
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h new file mode 100644 index 0000000..9709dfe --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
@@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_ + +#include "base/macros.h" +#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +// Concrete implementation of feed_internals::mojom::PageHandler. +class FeedInternalsPageHandler : public feed_internals::mojom::PageHandler { + public: + explicit FeedInternalsPageHandler( + feed_internals::mojom::PageHandlerRequest request); + ~FeedInternalsPageHandler() override; + + private: + mojo::Binding<feed_internals::mojom::PageHandler> binding_; + + DISALLOW_COPY_AND_ASSIGN(FeedInternalsPageHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc b/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc new file mode 100644 index 0000000..2dc5355 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc
@@ -0,0 +1,40 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/feed_internals/feed_internals_ui.h" + +#include <utility> + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "content/public/browser/web_ui_data_source.h" + +FeedInternalsUI::FeedInternalsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui) { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUISnippetsInternalsHost); + + source->AddResourcePath("feed_internals.js", IDR_FEED_INTERNALS_JS); + source->AddResourcePath("feed_internals.mojom-lite.js", + IDR_FEED_INTERNALS_MOJO_JS); + source->SetDefaultResource(IDR_FEED_INTERNALS_HTML); + source->UseGzip(); + + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource::Add(profile, source); + // This class is the caller of the callback when an observer interface is + // triggered. So this base::Unretained is safe. + AddHandlerToRegistry(base::BindRepeating( + &FeedInternalsUI::BindFeedInternalsPageHandler, base::Unretained(this))); +} + +FeedInternalsUI::~FeedInternalsUI() = default; + +void FeedInternalsUI::BindFeedInternalsPageHandler( + feed_internals::mojom::PageHandlerRequest request) { + page_handler_ = + std::make_unique<FeedInternalsPageHandler>(std::move(request)); +}
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h b/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h new file mode 100644 index 0000000..7b6bed2 --- /dev/null +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_UI_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h" +#include "chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h" +#include "ui/webui/mojo_web_ui_controller.h" + +// UI controller for chrome://feed-internals, hooks up a concrete implementation +// of feed_internals::mojom::PageHandler to requests for that page handler +// that will come from the frontend. +class FeedInternalsUI : public ui::MojoWebUIController { + public: + explicit FeedInternalsUI(content::WebUI* web_ui); + ~FeedInternalsUI() override; + + private: + void BindFeedInternalsPageHandler( + feed_internals::mojom::PageHandlerRequest request); + + std::unique_ptr<FeedInternalsPageHandler> page_handler_; + + DISALLOW_COPY_AND_ASSIGN(FeedInternalsUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_FEED_INTERNALS_FEED_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/omnibox/omnibox.mojom b/chrome/browser/ui/webui/omnibox/omnibox.mojom index 2a1f4bc..6ea786b 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox.mojom +++ b/chrome/browser/ui/webui/omnibox/omnibox.mojom
@@ -20,11 +20,14 @@ string fill_into_edit; string inline_autocompletion; string destination_url; + string image; string contents; string description; + string answer; string transition; bool allowed_to_be_default_match; string type; + bool is_search_type; bool has_tab_match; string? associated_keyword; string keyword; @@ -66,4 +69,5 @@ interface OmniboxPage { HandleNewAutocompleteResult(OmniboxResult result); + HandleAnswerImageData(string image_url, string image_data); };
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc index f5414e3..c4af0cd9 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/auto_reset.h" +#include "base/base64.h" #include "base/bind.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" @@ -17,6 +18,8 @@ #include "base/values.h" #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" +#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" +#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -32,8 +35,84 @@ #include "components/search_engines/template_url.h" #include "content/public/browser/web_ui.h" #include "third_party/metrics_proto/omnibox_event.pb.h" +#include "ui/gfx/image/image.h" using bookmarks::BookmarkModel; +using OmniboxPageImageCallback = + base::RepeatingCallback<void(const SkBitmap& bitmap)>; + +namespace { + +using ImageReciever = std::function<void(std::string)>; + +class OmniboxPageImageObserver : public BitmapFetcherService::Observer { + public: + explicit OmniboxPageImageObserver(ImageReciever image_reciever) + : image_reciever_(image_reciever) {} + + void OnImageChanged(BitmapFetcherService::RequestId request_id, + const SkBitmap& bitmap) override { + auto data = gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes(); + std::string base_64; + base::Base64Encode(base::StringPiece(data->front_as<char>(), data->size()), + &base_64); + const char kDataUrlPrefix[] = "data:image/png;base64,"; + std::string data_url = GURL(kDataUrlPrefix + base_64).spec(); + image_reciever_(data_url); + } + + private: + const ImageReciever image_reciever_; + + DISALLOW_COPY_AND_ASSIGN(OmniboxPageImageObserver); +}; + +std::string SuggestionAnswerTypeToString(int answer_type) { + switch (answer_type) { + case SuggestionAnswer::ANSWER_TYPE_INVALID: + return "invalid"; + case SuggestionAnswer::ANSWER_TYPE_DICTIONARY: + return "dictionary"; + case SuggestionAnswer::ANSWER_TYPE_FINANCE: + return "finance"; + case SuggestionAnswer::ANSWER_TYPE_KNOWLEDGE_GRAPH: + return "knowledge graph"; + case SuggestionAnswer::ANSWER_TYPE_LOCAL: + return "local"; + case SuggestionAnswer::ANSWER_TYPE_SPORTS: + return "sports"; + case SuggestionAnswer::ANSWER_TYPE_SUNRISE: + return "sunrise"; + case SuggestionAnswer::ANSWER_TYPE_TRANSLATION: + return "translation"; + case SuggestionAnswer::ANSWER_TYPE_WEATHER: + return "weather"; + case SuggestionAnswer::ANSWER_TYPE_WHEN_IS: + return "when is"; + case SuggestionAnswer::ANSWER_TYPE_CURRENCY: + return "currency"; + case SuggestionAnswer::ANSWER_TYPE_LOCAL_TIME: + return "local time"; + case SuggestionAnswer::ANSWER_TYPE_PLAY_INSTALL: + return "play install"; + default: + return std::to_string(answer_type); + } +} + +std::string SuggestionAnswerImageLineToString( + const SuggestionAnswer::ImageLine& image_line) { + std::string string; + for (auto text_field : image_line.text_fields()) + string += base::UTF16ToUTF8(text_field.text()); + if (image_line.additional_text()) + string += " " + base::UTF16ToUTF8(image_line.additional_text()->text()); + if (image_line.status_text()) + string += " " + base::UTF16ToUTF8(image_line.status_text()->text()); + return string; +} + +} // namespace namespace mojo { @@ -69,6 +148,7 @@ result->inline_autocompletion = base::UTF16ToUTF8(input.inline_autocompletion); result->destination_url = input.destination_url.spec(); + result->image = input.ImageUrl().spec().c_str(); result->contents = base::UTF16ToUTF8(input.contents); // At this time, we're not bothering to send along the long vector that // represent contents classification. i.e., for each character, what @@ -77,10 +157,18 @@ // At this time, we're not bothering to send along the long vector that // represents description classification. i.e., for each character, what // type of text it is. + if (input.answer) { + result->answer = + SuggestionAnswerImageLineToString(input.answer->first_line()) + + " / " + + SuggestionAnswerImageLineToString(input.answer->second_line()) + + " / " + SuggestionAnswerTypeToString(input.answer->type()); + } result->transition = ui::PageTransitionGetCoreTransitionString(input.transition); result->allowed_to_be_default_match = input.allowed_to_be_default_match; result->type = AutocompleteMatchType::ToString(input.type); + result->is_search_type = AutocompleteMatch::IsSearchType(input.type); result->has_tab_match = input.has_tab_match; if (input.associated_keyword.get() != NULL) { result->associated_keyword = @@ -166,7 +254,72 @@ } } + // Obtain a vector of all image urls required. + std::vector<std::string> image_urls; + for (size_t i = 0; i < result->combined_results.size(); ++i) + image_urls.push_back(result->combined_results[i]->image); + for (size_t i = 0; i < result->results_by_provider.size(); ++i) { + const mojom::AutocompleteResultsForProvider& result_by_provider = + *result->results_by_provider[i]; + for (size_t j = 0; j < result_by_provider.results.size(); ++j) + image_urls.push_back(result_by_provider.results[j]->image); + } + page_->HandleNewAutocompleteResult(std::move(result)); + + // Fill in image data + BitmapFetcherService* image_service = + BitmapFetcherServiceFactory::GetForBrowserContext(profile_); + for (std::string image_url : image_urls) { + const ImageReciever handleAnswerImageData = [this, + image_url](std::string data) { + page_->HandleAnswerImageData(image_url, data); + }; + if (!image_url.empty()) { + // TODO(jdonnelly, rhalavati, manukh): Create a helper function with + // Callback to create annotation and pass it to image_service, merging + // the annotations in omnibox_page_handler.cc, chrome_omnibox_client.cc, + // and chrome_autocomplete_provider_client.cc. + auto traffic_annotation = net::DefineNetworkTrafficAnnotation( + "omnibox_debug_results_change", R"( + semantics { + sender: "Omnibox" + description: + "Chromium provides answers in the suggestion list for " + "certain queries that user types in the omnibox. This request " + "retrieves a small image (for example, an icon illustrating " + "the current weather conditions) when this can add information " + "to an answer." + trigger: + "Change of results for the query typed by the user in the " + "omnibox." + data: + "The only data sent is the path to an image. No user data is " + "included, although some might be inferrable (e.g. whether the " + "weather is sunny or rainy in the user's current location) " + "from the name of the image in the path." + destination: WEBSITE + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: + "You can enable or disable this feature via 'Use a prediction " + "service to help complete searches and URLs typed in the " + "address bar.' in Chromium's settings under Advanced. The " + "feature is enabled by default." + chrome_policy { + SearchSuggestEnabled { + policy_options {mode: MANDATORY} + SearchSuggestEnabled: false + } + } + })"); + image_service->RequestImage( + GURL(image_url), new OmniboxPageImageObserver(handleAnswerImageData), + traffic_annotation); + } + } } bool OmniboxPageHandler::LookupIsTypedHost(const base::string16& host,
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index ca41231..82b0a80 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -197,10 +197,7 @@ "//skia", ] - defines = [ - "VR_IMPLEMENTATION", - "VR_UI_IMPLEMENTATION", - ] + defines = [ "VR_UI_IMPLEMENTATION" ] if (use_command_buffer) { sources += [ @@ -258,6 +255,7 @@ "sounds_manager_audio_delegate.h", "ui_factory.cc", "ui_factory.h", + "vr_export.h", "vr_web_contents_observer.cc", "vr_web_contents_observer.h", ] @@ -317,10 +315,7 @@ deps += [ "//services/ws/public/cpp/gpu" ] } - defines = [ - "VR_IMPLEMENTATION", - "VR_UI_IMPLEMENTATION", - ] + defines = [ "VR_IMPLEMENTATION" ] if (!use_command_buffer) { sources += [ @@ -333,7 +328,7 @@ # vr_base contains common dependencies of vr_common and vr_ui. It exists because # vr_ui must not depend on vr_common. -source_set("vr_base") { +component("vr_base") { sources = [ "assets_component_update_status.h", "assets_load_status.h", @@ -392,7 +387,7 @@ "ui_support.h", "ui_test_input.h", "ui_unsupported_mode.h", - "vr_export.h", + "vr_base_export.h", "vr_geometry_util.cc", "vr_geometry_util.h", "vr_gl_util.cc", @@ -404,10 +399,7 @@ "keyboard_delegate_for_testing.h", ] - defines = [ - "VR_IMPLEMENTATION", - "VR_UI_IMPLEMENTATION", - ] + defines = [ "VR_BASE_IMPLEMENTATION" ] public_deps = [ ":vr_build_features",
diff --git a/chrome/browser/vr/assets_loader.h b/chrome/browser/vr/assets_loader.h index fc02813..cddcf5d8 100644 --- a/chrome/browser/vr/assets_loader.h +++ b/chrome/browser/vr/assets_loader.h
@@ -13,7 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/version.h" #include "chrome/browser/vr/assets_load_status.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace base { class DictionaryValue; @@ -40,7 +40,7 @@ // component will be made available on a different thread than the asset load // request. Internally, the function calls will be posted on the main thread. // The asset load may be performed on a worker thread. -class VR_EXPORT AssetsLoader { +class VR_BASE_EXPORT AssetsLoader { public: typedef base::OnceCallback<void(AssetsLoadStatus status, std::unique_ptr<Assets> assets,
diff --git a/chrome/browser/vr/browser_ui_interface.h b/chrome/browser/vr/browser_ui_interface.h index db96570..67dd786 100644 --- a/chrome/browser/vr/browser_ui_interface.h +++ b/chrome/browser/vr/browser_ui_interface.h
@@ -11,7 +11,7 @@ #include "chrome/browser/vr/model/capturing_state_model.h" #include "chrome/browser/vr/model/web_vr_model.h" #include "chrome/browser/vr/ui_unsupported_mode.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "components/security_state/core/security_state.h" namespace base { @@ -28,7 +28,7 @@ // The browser communicates state changes to the VR UI via this interface. // A GL thread would also implement this interface to provide a convenient way // to call these methods from the main thread. -class VR_EXPORT BrowserUiInterface { +class VR_BASE_EXPORT BrowserUiInterface { public: virtual ~BrowserUiInterface() {}
diff --git a/chrome/browser/vr/fov_rectangle.h b/chrome/browser/vr/fov_rectangle.h index 39f2a5ab..aff74c6 100644 --- a/chrome/browser/vr/fov_rectangle.h +++ b/chrome/browser/vr/fov_rectangle.h
@@ -8,7 +8,7 @@ #include <utility> #include "chrome/browser/vr/gl_texture_location.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr {
diff --git a/chrome/browser/vr/input_event.h b/chrome/browser/vr/input_event.h index cac699c9..87698bb3 100644 --- a/chrome/browser/vr/input_event.h +++ b/chrome/browser/vr/input_event.h
@@ -6,12 +6,12 @@ #define CHROME_BROWSER_VR_INPUT_EVENT_H_ #include "base/time/time.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/point_f.h" namespace vr { -class VR_EXPORT InputEvent { +class VR_BASE_EXPORT InputEvent { public: enum Type { kTypeUndefined = -1,
diff --git a/chrome/browser/vr/keyboard_delegate.h b/chrome/browser/vr/keyboard_delegate.h index 6de0daa..8c8dabc5 100644 --- a/chrome/browser/vr/keyboard_delegate.h +++ b/chrome/browser/vr/keyboard_delegate.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_VR_KEYBOARD_DELEGATE_H_ #include "base/memory/weak_ptr.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace gfx { class Point3F; @@ -20,7 +20,7 @@ struct CameraModel; struct TextInputInfo; -class VR_EXPORT KeyboardDelegate { +class VR_BASE_EXPORT KeyboardDelegate { public: virtual ~KeyboardDelegate() {}
diff --git a/chrome/browser/vr/keyboard_delegate_for_testing.h b/chrome/browser/vr/keyboard_delegate_for_testing.h index 5bf9dbc..e78485f 100644 --- a/chrome/browser/vr/keyboard_delegate_for_testing.h +++ b/chrome/browser/vr/keyboard_delegate_for_testing.h
@@ -11,6 +11,7 @@ #include "chrome/browser/vr/keyboard_delegate.h" #include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/ui_test_input.h" +#include "chrome/browser/vr/vr_base_export.h" namespace gfx { class Point3F; @@ -22,7 +23,7 @@ class KeyboardUiInterface; struct CameraModel; -class KeyboardDelegateForTesting : public KeyboardDelegate { +class VR_BASE_EXPORT KeyboardDelegateForTesting : public KeyboardDelegate { public: KeyboardDelegateForTesting(); ~KeyboardDelegateForTesting() override;
diff --git a/chrome/browser/vr/keyboard_ui_interface.h b/chrome/browser/vr/keyboard_ui_interface.h index f88e730..2837f4d 100644 --- a/chrome/browser/vr/keyboard_ui_interface.h +++ b/chrome/browser/vr/keyboard_ui_interface.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_VR_KEYBOARD_UI_INTERFACE_H_ #include "chrome/browser/vr/model/text_input_info.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { @@ -14,7 +14,7 @@ // that we have this interface to restrict the UI API to keyboard-specific // callback functions because the keyboard delegate doesn't need access to all // of the UI. -class VR_EXPORT KeyboardUiInterface { +class VR_BASE_EXPORT KeyboardUiInterface { public: virtual ~KeyboardUiInterface() {} virtual void OnInputEdited(const EditedText& info) = 0;
diff --git a/chrome/browser/vr/metrics/metrics_helper.h b/chrome/browser/vr/metrics/metrics_helper.h index 59bb6e8..d1ade64 100644 --- a/chrome/browser/vr/metrics/metrics_helper.h +++ b/chrome/browser/vr/metrics/metrics_helper.h
@@ -13,7 +13,7 @@ #include "chrome/browser/vr/assets_component_update_status.h" #include "chrome/browser/vr/assets_load_status.h" #include "chrome/browser/vr/mode.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace base { class Version; @@ -24,7 +24,7 @@ // Helper to collect VR UMA metrics. // // For thread-safety, all functions must be called in sequence. -class VR_EXPORT MetricsHelper { +class VR_BASE_EXPORT MetricsHelper { public: MetricsHelper(); ~MetricsHelper();
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.h b/chrome/browser/vr/metrics/session_metrics_helper.h index 3e0c907..eb8f0d4d 100644 --- a/chrome/browser/vr/metrics/session_metrics_helper.h +++ b/chrome/browser/vr/metrics/session_metrics_helper.h
@@ -10,7 +10,7 @@ #include "base/time/time.h" #include "chrome/browser/vr/mode.h" #include "chrome/browser/vr/ui_browser_interface.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "content/public/browser/web_contents_observer.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -147,7 +147,8 @@ // metrics that require state monitoring, such as durations, but also tracks // data we want attached to that, such as number of videos watched and how the // session was started. -class VR_EXPORT SessionMetricsHelper : public content::WebContentsObserver { +class VR_BASE_EXPORT SessionMetricsHelper + : public content::WebContentsObserver { public: // Returns the SessionMetricsHelper singleton if it has been created for the // WebContents.
diff --git a/chrome/browser/vr/model/assets.h b/chrome/browser/vr/model/assets.h index 291b131..47c146a 100644 --- a/chrome/browser/vr/model/assets.h +++ b/chrome/browser/vr/model/assets.h
@@ -8,13 +8,13 @@ #include <memory> #include "base/version.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" class SkBitmap; namespace vr { -struct VR_EXPORT Assets { +struct VR_BASE_EXPORT Assets { Assets(); ~Assets();
diff --git a/chrome/browser/vr/model/camera_model.h b/chrome/browser/vr/model/camera_model.h index fd2c29f..b6e5298 100644 --- a/chrome/browser/vr/model/camera_model.h +++ b/chrome/browser/vr/model/camera_model.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_MODEL_CAMERA_MODEL_H_ #define CHROME_BROWSER_VR_MODEL_CAMERA_MODEL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/transform.h" @@ -17,7 +17,7 @@ kRightEye, }; -struct VR_EXPORT CameraModel { +struct VR_BASE_EXPORT CameraModel { EyeType eye_type; gfx::Rect viewport; gfx::Transform view_matrix;
diff --git a/chrome/browser/vr/model/capturing_state_model.h b/chrome/browser/vr/model/capturing_state_model.h index 8058c7d..367c960 100644 --- a/chrome/browser/vr/model/capturing_state_model.h +++ b/chrome/browser/vr/model/capturing_state_model.h
@@ -5,11 +5,11 @@ #ifndef CHROME_BROWSER_VR_MODEL_CAPTURING_STATE_MODEL_H_ #define CHROME_BROWSER_VR_MODEL_CAPTURING_STATE_MODEL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { -struct VR_EXPORT CapturingStateModel { +struct VR_BASE_EXPORT CapturingStateModel { bool audio_capture_enabled = false; bool video_capture_enabled = false; bool screen_capture_enabled = false;
diff --git a/chrome/browser/vr/model/controller_model.h b/chrome/browser/vr/model/controller_model.h index c01b285..d1832f5 100644 --- a/chrome/browser/vr/model/controller_model.h +++ b/chrome/browser/vr/model/controller_model.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_VR_MODEL_CONTROLLER_MODEL_H_ #include "base/time/time.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/transform.h" @@ -16,7 +16,7 @@ // platform-specific VR subsystem (e.g., GVR). It is used by both the // UiInputManager (for generating gestures), and by the UI for rendering the // controller. -struct VR_EXPORT ControllerModel { +struct VR_BASE_EXPORT ControllerModel { enum ButtonState { kUp, kDown,
diff --git a/chrome/browser/vr/model/hosted_platform_ui.h b/chrome/browser/vr/model/hosted_platform_ui.h index 2a0dfe5..b6a5be6e 100644 --- a/chrome/browser/vr/model/hosted_platform_ui.h +++ b/chrome/browser/vr/model/hosted_platform_ui.h
@@ -6,12 +6,12 @@ #define CHROME_BROWSER_VR_MODEL_HOSTED_PLATFORM_UI_H_ #include "chrome/browser/vr/platform_ui_input_delegate.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/rect_f.h" namespace vr { typedef PlatformUiInputDelegate* PlatformUiInputDelegatePtr; -struct VR_EXPORT HostedPlatformUi { +struct VR_BASE_EXPORT HostedPlatformUi { bool hosted_ui_enabled = false; PlatformUiInputDelegatePtr delegate = nullptr; unsigned int texture_id = 0;
diff --git a/chrome/browser/vr/model/location_bar_state.h b/chrome/browser/vr/model/location_bar_state.h index b8109886..a07ec4f 100644 --- a/chrome/browser/vr/model/location_bar_state.h +++ b/chrome/browser/vr/model/location_bar_state.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_MODEL_LOCATION_BAR_STATE_H_ #define CHROME_BROWSER_VR_MODEL_LOCATION_BAR_STATE_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "components/security_state/core/security_state.h" #include "url/gurl.h" @@ -16,7 +16,7 @@ namespace vr { // Passes information obtained from LocationBarModel to the VR UI framework. -struct VR_EXPORT LocationBarState { +struct VR_BASE_EXPORT LocationBarState { public: LocationBarState(); LocationBarState(const GURL& url,
diff --git a/chrome/browser/vr/model/omnibox_suggestions.h b/chrome/browser/vr/model/omnibox_suggestions.h index 3f96980..75dd82f 100644 --- a/chrome/browser/vr/model/omnibox_suggestions.h +++ b/chrome/browser/vr/model/omnibox_suggestions.h
@@ -6,13 +6,13 @@ #define CHROME_BROWSER_VR_MODEL_OMNIBOX_SUGGESTIONS_H_ #include "base/strings/string16.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "components/omnibox/browser/autocomplete_match.h" #include "url/gurl.h" namespace vr { -struct VR_EXPORT Autocompletion { +struct VR_BASE_EXPORT Autocompletion { Autocompletion(); Autocompletion(const base::string16& new_input, const base::string16& new_suffix); @@ -28,7 +28,7 @@ base::string16 suffix; }; -struct VR_EXPORT OmniboxSuggestion { +struct VR_BASE_EXPORT OmniboxSuggestion { OmniboxSuggestion(); OmniboxSuggestion(const base::string16& new_contents, @@ -53,7 +53,7 @@ Autocompletion autocompletion; }; -struct VR_EXPORT OmniboxSuggestions { +struct VR_BASE_EXPORT OmniboxSuggestions { OmniboxSuggestions(); ~OmniboxSuggestions(); @@ -62,7 +62,7 @@ // This struct contains the minimal set of information required to construct an // AutocompleteInput on VR's behalf. -struct VR_EXPORT AutocompleteRequest { +struct VR_BASE_EXPORT AutocompleteRequest { base::string16 text; size_t cursor_position = 0; bool prevent_inline_autocomplete = false; @@ -77,7 +77,7 @@ }; // This struct represents the current request to the AutocompleteController. -struct VR_EXPORT AutocompleteStatus { +struct VR_BASE_EXPORT AutocompleteStatus { bool active = false; base::string16 input;
diff --git a/chrome/browser/vr/model/reticle_model.h b/chrome/browser/vr/model/reticle_model.h index 4a0c754..46ec333 100644 --- a/chrome/browser/vr/model/reticle_model.h +++ b/chrome/browser/vr/model/reticle_model.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_MODEL_RETICLE_MODEL_H_ #define CHROME_BROWSER_VR_MODEL_RETICLE_MODEL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/point3_f.h" namespace vr { @@ -19,7 +19,7 @@ // controller's laser. It is computed by the UiInputManager and is used by the // input manager in the production of gestures as well as by the Reticle element // in the scene. -struct VR_EXPORT ReticleModel { +struct VR_BASE_EXPORT ReticleModel { gfx::Point3F target_point; gfx::PointF target_local_point; int target_element_id = 0;
diff --git a/chrome/browser/vr/model/speech_recognition_model.h b/chrome/browser/vr/model/speech_recognition_model.h index bb77e5f..88b86b9 100644 --- a/chrome/browser/vr/model/speech_recognition_model.h +++ b/chrome/browser/vr/model/speech_recognition_model.h
@@ -6,11 +6,11 @@ #define CHROME_BROWSER_VR_MODEL_SPEECH_RECOGNITION_MODEL_H_ #include "base/strings/string16.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { -struct VR_EXPORT SpeechRecognitionModel { +struct VR_BASE_EXPORT SpeechRecognitionModel { int speech_recognition_state = 0; bool has_or_can_request_audio_permission = true; base::string16 recognition_result;
diff --git a/chrome/browser/vr/model/text_input_info.h b/chrome/browser/vr/model/text_input_info.h index cf47e8e..868863f 100644 --- a/chrome/browser/vr/model/text_input_info.h +++ b/chrome/browser/vr/model/text_input_info.h
@@ -11,12 +11,12 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/vr/text_edit_action.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { // Represents the state of an editable text field. -struct VR_EXPORT TextInputInfo { +struct VR_BASE_EXPORT TextInputInfo { public: TextInputInfo(); explicit TextInputInfo(base::string16 t); @@ -65,7 +65,7 @@ // A superset of TextInputInfo, consisting of a current and previous text field // state. A keyboard can return this structure, allowing clients to derive // deltas in keyboard state. -struct VR_EXPORT EditedText { +struct VR_BASE_EXPORT EditedText { public: EditedText(); EditedText(const EditedText& other);
diff --git a/chrome/browser/vr/model/web_vr_model.h b/chrome/browser/vr/model/web_vr_model.h index 476ee70d..43dae76 100644 --- a/chrome/browser/vr/model/web_vr_model.h +++ b/chrome/browser/vr/model/web_vr_model.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_MODEL_WEB_VR_MODEL_H_ #define CHROME_BROWSER_VR_MODEL_WEB_VR_MODEL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { @@ -35,7 +35,7 @@ kPromptBluetooth, }; -struct VR_EXPORT WebVrModel { +struct VR_BASE_EXPORT WebVrModel { WebVrState state = kWebVrNoTimeoutPending; bool has_received_permissions = false; bool showing_hosted_ui = false;
diff --git a/chrome/browser/vr/platform_ui_input_delegate.h b/chrome/browser/vr/platform_ui_input_delegate.h index 77e5d395..5daf9ea4 100644 --- a/chrome/browser/vr/platform_ui_input_delegate.h +++ b/chrome/browser/vr/platform_ui_input_delegate.h
@@ -15,7 +15,7 @@ #include "chrome/browser/vr/macros.h" #include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/text_edit_action.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/size.h" namespace base { @@ -32,7 +32,7 @@ // This class is responsible for processing all events and gestures for // PlatformUiElement. -class VR_EXPORT PlatformUiInputDelegate { +class VR_BASE_EXPORT PlatformUiInputDelegate { public: PlatformUiInputDelegate(); explicit PlatformUiInputDelegate(PlatformInputHandler* input_handler);
diff --git a/chrome/browser/vr/pose_util.h b/chrome/browser/vr/pose_util.h index 859f84e..cbf553f 100644 --- a/chrome/browser/vr/pose_util.h +++ b/chrome/browser/vr/pose_util.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_POSE_UTIL_H_ #define CHROME_BROWSER_VR_POSE_UTIL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/vector3d_f.h" namespace gfx { @@ -15,10 +15,10 @@ namespace vr { // Provides the direction the head is looking towards as a 3x1 unit vector. -VR_EXPORT gfx::Vector3dF GetForwardVector(const gfx::Transform& head_pose); +VR_BASE_EXPORT gfx::Vector3dF GetForwardVector(const gfx::Transform& head_pose); // Returns a vector heading upward from the viewer's head. -VR_EXPORT gfx::Vector3dF GetUpVector(const gfx::Transform& head_pose); +VR_BASE_EXPORT gfx::Vector3dF GetUpVector(const gfx::Transform& head_pose); } // namespace vr
diff --git a/chrome/browser/vr/render_info.h b/chrome/browser/vr/render_info.h index 087f9f76..6dac178 100644 --- a/chrome/browser/vr/render_info.h +++ b/chrome/browser/vr/render_info.h
@@ -6,14 +6,14 @@ #define CHROME_BROWSER_VR_RENDER_INFO_H_ #include "chrome/browser/vr/model/camera_model.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/transform.h" namespace vr { // Provides information for rendering such as the viewport and view/projection // matrix. -struct VR_EXPORT RenderInfo { +struct VR_BASE_EXPORT RenderInfo { gfx::Transform head_pose; CameraModel left_eye_model; CameraModel right_eye_model;
diff --git a/chrome/browser/vr/scheduler_ui_interface.h b/chrome/browser/vr/scheduler_ui_interface.h index c8407f6..d13610d 100644 --- a/chrome/browser/vr/scheduler_ui_interface.h +++ b/chrome/browser/vr/scheduler_ui_interface.h
@@ -8,11 +8,11 @@ #include <utility> #include "chrome/browser/vr/gl_texture_location.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { -class VR_EXPORT SchedulerUiInterface { +class VR_BASE_EXPORT SchedulerUiInterface { public: virtual ~SchedulerUiInterface() {}
diff --git a/chrome/browser/vr/speech_recognizer.h b/chrome/browser/vr/speech_recognizer.h index e209a5f..3ce7ca7 100644 --- a/chrome/browser/vr/speech_recognizer.h +++ b/chrome/browser/vr/speech_recognizer.h
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace content { class SpeechRecognitionManager; @@ -90,7 +90,7 @@ // SpeechRecognizer is a wrapper around the speech recognition engine that // simplifies its use from the UI thread. This class handles all setup/shutdown, // collection of results, error cases, and threading. -class VR_EXPORT SpeechRecognizer : public IOBrowserUIInterface { +class VR_BASE_EXPORT SpeechRecognizer : public IOBrowserUIInterface { public: // |shared_url_loader_factory_info| must be for a creating a // SharedURLLoaderFactory that can be used on the IO Thread.
diff --git a/chrome/browser/vr/text_edit_action.h b/chrome/browser/vr/text_edit_action.h index 833373cc..ffa025f 100644 --- a/chrome/browser/vr/text_edit_action.h +++ b/chrome/browser/vr/text_edit_action.h
@@ -8,7 +8,7 @@ #include <vector> #include "base/strings/string16.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { @@ -20,7 +20,7 @@ DELETE_TEXT, }; -class VR_EXPORT TextEditAction { +class VR_BASE_EXPORT TextEditAction { public: explicit TextEditAction(TextEditActionType type); TextEditAction(TextEditActionType type,
diff --git a/chrome/browser/vr/text_input_delegate.h b/chrome/browser/vr/text_input_delegate.h index e9ae347..834a4f5f 100644 --- a/chrome/browser/vr/text_input_delegate.h +++ b/chrome/browser/vr/text_input_delegate.h
@@ -7,13 +7,13 @@ #include "base/callback.h" #include "base/macros.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { struct TextInputInfo; -class VR_EXPORT TextInputDelegate { +class VR_BASE_EXPORT TextInputDelegate { public: TextInputDelegate(); virtual ~TextInputDelegate();
diff --git a/chrome/browser/vr/ui_browser_interface.h b/chrome/browser/vr/ui_browser_interface.h index 9635da9..757ec3a 100644 --- a/chrome/browser/vr/ui_browser_interface.h +++ b/chrome/browser/vr/ui_browser_interface.h
@@ -8,7 +8,7 @@ #include "chrome/browser/vr/exit_vr_prompt_choice.h" #include "chrome/browser/vr/model/omnibox_suggestions.h" #include "chrome/browser/vr/ui_unsupported_mode.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/size_f.h" #include "url/gurl.h" @@ -23,7 +23,7 @@ // An interface for the VR UI to communicate with VrShell. Many of the functions // in this interface are proxies to methods on VrShell. -class VR_EXPORT UiBrowserInterface { +class VR_BASE_EXPORT UiBrowserInterface { public: virtual ~UiBrowserInterface() = default;
diff --git a/chrome/browser/vr/ui_initial_state.h b/chrome/browser/vr/ui_initial_state.h index c8be12c..2f64f894 100644 --- a/chrome/browser/vr/ui_initial_state.h +++ b/chrome/browser/vr/ui_initial_state.h
@@ -5,13 +5,13 @@ #ifndef CHROME_BROWSER_VR_UI_INITIAL_STATE_H_ #define CHROME_BROWSER_VR_UI_INITIAL_STATE_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" namespace vr { // This class describes the initial state of a UI, and may be used by a UI // instances owner to specify a custom state on startup. -struct VR_EXPORT UiInitialState { +struct VR_BASE_EXPORT UiInitialState { UiInitialState(); UiInitialState(const UiInitialState& other); bool in_web_vr = false;
diff --git a/chrome/browser/vr/ui_support.h b/chrome/browser/vr/ui_support.h index c9183c61..e1e819c 100644 --- a/chrome/browser/vr/ui_support.h +++ b/chrome/browser/vr/ui_support.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_UI_SUPPORT_H_ #define CHROME_BROWSER_VR_UI_SUPPORT_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "components/url_formatter/url_formatter.h" #include "third_party/icu/source/common/unicode/uchar.h" #include "third_party/icu/source/common/unicode/uscript.h" @@ -20,10 +20,10 @@ // must supply wrappers for use by the module. For libraries that require only // one or two methods, it's more efficient to make wrappers. -VR_EXPORT UScriptCode UScriptGetScript(UChar32 codepoint, UErrorCode* err); +VR_BASE_EXPORT UScriptCode UScriptGetScript(UChar32 codepoint, UErrorCode* err); -VR_EXPORT base::string16 FormatUrlForVr(const GURL& gurl, - url::Parsed* new_parsed); +VR_BASE_EXPORT base::string16 FormatUrlForVr(const GURL& gurl, + url::Parsed* new_parsed); } // namespace vr
diff --git a/chrome/browser/vr/vr_base_export.h b/chrome/browser/vr/vr_base_export.h new file mode 100644 index 0000000..8fb9b51 --- /dev/null +++ b/chrome/browser/vr/vr_base_export.h
@@ -0,0 +1,29 @@ +// 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. + +#ifndef CHROME_BROWSER_VR_VR_BASE_EXPORT_H_ +#define CHROME_BROWSER_VR_VR_BASE_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(VR_BASE_IMPLEMENTATION) +#define VR_BASE_EXPORT __declspec(dllexport) +#else +#define VR_BASE_EXPORT __declspec(dllimport) +#endif // defined(VR_BASE_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(VR_BASE_IMPLEMENTATION) +#define VR_BASE_EXPORT __attribute__((visibility("default"))) +#else +#define VR_BASE_EXPORT +#endif // defined(VR_BASE_IMPLEMENTATION) +#endif + +#else // defined(COMPONENT_BUILD) +#define VR_BASE_EXPORT +#endif + +#endif // CHROME_BROWSER_VR_VR_BASE_EXPORT_H_
diff --git a/chrome/browser/vr/vr_geometry_util.h b/chrome/browser/vr/vr_geometry_util.h index 71dd25f2..0a8674f 100644 --- a/chrome/browser/vr/vr_geometry_util.h +++ b/chrome/browser/vr/vr_geometry_util.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_VR_VR_GEOMETRY_UTIL_H_ #define CHROME_BROWSER_VR_VR_GEOMETRY_UTIL_H_ -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "ui/gfx/geometry/rect.h" namespace gfx { @@ -17,14 +17,15 @@ namespace vr { -VR_EXPORT gfx::Rect CalculatePixelSpaceRect(const gfx::Size& texture_size, - const gfx::RectF& texture_rect); +VR_BASE_EXPORT gfx::Rect CalculatePixelSpaceRect( + const gfx::Size& texture_size, + const gfx::RectF& texture_rect); // Returns the normalized size of the element projected into screen space. // If (1, 1) the element fills the entire buffer. -VR_EXPORT gfx::SizeF CalculateScreenSize(const gfx::Transform& proj_matrix, - float distance, - const gfx::SizeF& size); +VR_BASE_EXPORT gfx::SizeF CalculateScreenSize(const gfx::Transform& proj_matrix, + float distance, + const gfx::SizeF& size); } // namespace vr
diff --git a/chrome/browser/vr/vr_gl_util.h b/chrome/browser/vr/vr_gl_util.h index 85ee60d..c9e90582 100644 --- a/chrome/browser/vr/vr_gl_util.h +++ b/chrome/browser/vr/vr_gl_util.h
@@ -9,7 +9,7 @@ #include <string> #include "chrome/browser/vr/gl_bindings.h" -#include "chrome/browser/vr/vr_export.h" +#include "chrome/browser/vr/vr_base_export.h" #include "third_party/skia/include/core/SkColor.h" #define SHADER(Src) "#version 100\n" #Src @@ -23,27 +23,28 @@ namespace vr { -VR_EXPORT std::array<float, 16> MatrixToGLArray(const gfx::Transform& matrix); +VR_BASE_EXPORT std::array<float, 16> MatrixToGLArray( + const gfx::Transform& matrix); // Compile a shader. -VR_EXPORT GLuint CompileShader(GLenum shader_type, - const GLchar* shader_source, - std::string& error); +VR_BASE_EXPORT GLuint CompileShader(GLenum shader_type, + const GLchar* shader_source, + std::string& error); // Compile and link a program. -VR_EXPORT GLuint CreateAndLinkProgram(GLuint vertex_shader_handle, - GLuint fragment_shader_handle, - std::string& error); +VR_BASE_EXPORT GLuint CreateAndLinkProgram(GLuint vertex_shader_handle, + GLuint fragment_shader_handle, + std::string& error); // Sets default texture parameters given a texture type. -VR_EXPORT void SetTexParameters(GLenum texture_type); +VR_BASE_EXPORT void SetTexParameters(GLenum texture_type); // Sets color uniforms given an SkColor. -VR_EXPORT void SetColorUniform(GLuint handle, SkColor c); +VR_BASE_EXPORT void SetColorUniform(GLuint handle, SkColor c); // Sets color uniforms (but not alpha) given an SkColor. The alpha is assumed to // be 1.0 in this case. -VR_EXPORT void SetOpaqueColorUniform(GLuint handle, SkColor c); +VR_BASE_EXPORT void SetOpaqueColorUniform(GLuint handle, SkColor c); } // namespace vr
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index d5c530d..7fb2b3d 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -432,6 +432,13 @@ const base::Feature kUseNewAcceptLanguageHeader{ "UseNewAcceptLanguageHeader", base::FEATURE_ENABLED_BY_DEFAULT}; +#if defined(OS_CHROMEOS) +// Enables usage of Parent Access Code to authorize certain actions on child +// user device. +const base::Feature kParentAccessCode{"ParentAccessCode", + base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + // Delegate permissions to cross-origin iframes when the feature has been // allowed by feature policy. const base::Feature kPermissionDelegation{"PermissionDelegation",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 125efbf99..323b99a 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -289,6 +289,11 @@ COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kUseNewAcceptLanguageHeader; +#if defined(OS_CHROMEOS) +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kParentAccessCode; +#endif + COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kPermissionDelegation;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index afd7fc3..a054566 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -806,6 +806,7 @@ "../browser/ui/omnibox/lookalike_url_navigation_observer_browsertest.cc", "../browser/ui/passwords/google_password_manager_navigation_throttle_browsertest.cc", "../browser/ui/tabs/pinned_tab_service_browsertest.cc", + "../browser/ui/views/tabs/tab_hover_card_bubble_view_browsertest.cc", # If this list is used on Android in the future, these browser / speech/* # files will probably not be applicable.
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc index 0e1fcd5..89ed72a2 100644 --- a/chrome/test/base/chrome_render_view_host_test_harness.cc +++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -61,6 +61,14 @@ int thread_bundle_options) : content::RenderViewHostTestHarness(thread_bundle_options) {} +ChromeRenderViewHostTestHarness::ChromeRenderViewHostTestHarness( + base::test::ScopedTaskEnvironment::MainThreadType main_thread_type, + base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode, + int thread_bundle_options) + : content::RenderViewHostTestHarness(main_thread_type, + execution_control_mode, + thread_bundle_options) {} + ChromeRenderViewHostTestHarness::~ChromeRenderViewHostTestHarness() = default; TestingProfile* ChromeRenderViewHostTestHarness::profile() {
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.h b/chrome/test/base/chrome_render_view_host_test_harness.h index 7581537..d510965 100644 --- a/chrome/test/base/chrome_render_view_host_test_harness.h +++ b/chrome/test/base/chrome_render_view_host_test_harness.h
@@ -16,6 +16,10 @@ : public content::RenderViewHostTestHarness { public: explicit ChromeRenderViewHostTestHarness(int thread_bundle_options = 0); + ChromeRenderViewHostTestHarness( + base::test::ScopedTaskEnvironment::MainThreadType main_thread_type, + base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode, + int thread_bundle_options = 0); ~ChromeRenderViewHostTestHarness() override; TestingProfile* profile();
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h index bb17390..86d4414 100644 --- a/chrome/test/base/in_process_browser_test.h +++ b/chrome/test/base/in_process_browser_test.h
@@ -22,7 +22,6 @@ #if defined(OS_MACOSX) #include "ui/base/test/scoped_fake_full_keyboard_access.h" -#include "ui/base/test/scoped_fake_nswindow_fullscreen.h" #endif namespace base { @@ -284,12 +283,6 @@ // more consistent with other platforms, where most views are focusable by // default. ui::test::ScopedFakeFullKeyboardAccess faked_full_keyboard_access_; - - // Don't allow browser tests to enter real fullscreen - it might trigger races - // in WindowServer in test configurations. This is a temporary debugging hack. - // TODO(ellyjones): Remove this or make it permanent - - // https://crbug.com/828031. - ui::test::ScopedFakeNSWindowFullscreen faked_fullscreen_; #endif // OS_MACOSX #if defined(OS_WIN)
diff --git a/chrome/test/chromedriver/chrome/ui_events.cc b/chrome/test/chromedriver/chrome/ui_events.cc index 6e1f485a..321e9bbeb 100644 --- a/chrome/test/chromedriver/chrome/ui_events.cc +++ b/chrome/test/chromedriver/chrome/ui_events.cc
@@ -22,18 +22,16 @@ y(y), modifiers(modifiers), buttons(buttons), - click_count(click_count) {} + click_count(click_count), + element_id(std::string()), + pointer_type(kMouse) {} MouseEvent::MouseEvent(const MouseEvent& other) = default; MouseEvent::~MouseEvent() {} -TouchEvent::TouchEvent(TouchEventType type, - int x, - int y) - : type(type), - x(x), - y(y) {} +TouchEvent::TouchEvent(TouchEventType type, int x, int y) + : type(type), x(x), y(y), element_id(std::string()) {} TouchEvent::TouchEvent(const TouchEvent& other) = default; @@ -45,7 +43,10 @@ modified_text(std::string()), unmodified_text(std::string()), key(std::string()), - key_code(ui::VKEY_UNKNOWN) {} + key_code(ui::VKEY_UNKNOWN), + location(0), + code(), + is_from_action(false) {} KeyEvent::KeyEvent(const KeyEvent& that) : type(that.type), @@ -53,7 +54,10 @@ modified_text(that.modified_text), unmodified_text(that.unmodified_text), key(that.key), - key_code(that.key_code) {} + key_code(that.key_code), + location(that.location), + code(that.code), + is_from_action(that.is_from_action) {} KeyEvent::~KeyEvent() {} @@ -91,6 +95,27 @@ return this; } +KeyEventBuilder* KeyEventBuilder::SetLocation(int location) { + key_event_.location = location; + return this; +} + +KeyEventBuilder* KeyEventBuilder::SetDefaultKey(const std::string& key) { + if (key_event_.key.size() == 0) + key_event_.key = key; + return this; +} + +KeyEventBuilder* KeyEventBuilder::SetCode(const std::string& code) { + key_event_.code = code; + return this; +} + +KeyEventBuilder* KeyEventBuilder::SetIsFromAction() { + key_event_.is_from_action = true; + return this; +} + KeyEvent KeyEventBuilder::Build() { DCHECK(key_event_.type != kInvalidEventType); return key_event_;
diff --git a/chrome/test/chromedriver/chrome/ui_events.h b/chrome/test/chromedriver/chrome/ui_events.h index bf327195..8b9930d 100644 --- a/chrome/test/chromedriver/chrome/ui_events.h +++ b/chrome/test/chromedriver/chrome/ui_events.h
@@ -29,6 +29,9 @@ kNoneMouseButton }; +// Specifies the event's pointer type. +enum PointerType { kMouse = 0, kPen }; + struct MouseEvent { MouseEvent(MouseEventType type, MouseButton button, @@ -49,6 +52,7 @@ // |click_count| should not be negative. int click_count; std::string element_id; + PointerType pointer_type; }; // Specifies the type of the touch event. @@ -100,6 +104,9 @@ std::string unmodified_text; std::string key; ui::KeyboardCode key_code; + int location; + std::string code; + bool is_from_action; }; class KeyEventBuilder { @@ -113,6 +120,10 @@ KeyEventBuilder* SetText(const std::string& unmodified_text, const std::string& modified_text); KeyEventBuilder* SetKeyCode(ui::KeyboardCode key_code); + KeyEventBuilder* SetLocation(int location); + KeyEventBuilder* SetDefaultKey(const std::string& key); + KeyEventBuilder* SetCode(const std::string& key); + KeyEventBuilder* SetIsFromAction(); KeyEvent Build(); void Generate(std::list<KeyEvent>* key_events);
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index ad5b2eb..f3132e92 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -122,6 +122,18 @@ } } +const char* GetAsString(PointerType type) { + switch (type) { + case kMouse: + return "mouse"; + case kPen: + return "pen"; + default: + NOTREACHED(); + return ""; + } +} + } // namespace WebViewImpl::WebViewImpl(const std::string& id, @@ -467,6 +479,7 @@ params.SetString("button", GetAsString(it->button)); params.SetInteger("buttons", it->buttons); params.SetInteger("clickCount", it->click_count); + params.SetString("pointerType", GetAsString(it->pointer_type)); Status status = client_->SendCommand("Input.dispatchMouseEvent", params); if (status.IsError()) return status; @@ -506,12 +519,28 @@ params.SetString("text", it->modified_text); params.SetString("unmodifiedText", it->unmodified_text); params.SetInteger("windowsVirtualKeyCode", it->key_code); - ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(it->key_code); - std::string code = ui::KeycodeConverter::DomCodeToCodeString(dom_code); + std::string code; + if (it->is_from_action) { + code = it->code; + } else { + ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(it->key_code); + code = ui::KeycodeConverter::DomCodeToCodeString(dom_code); + } if (!code.empty()) params.SetString("code", code); if (!it->key.empty()) params.SetString("key", it->key); + else if (it->is_from_action) + params.SetString("key", it->modified_text); + if (it->location != 0) { + // The |location| parameter in DevTools protocol only accepts 1 (left + // modifiers) and 2 (right modifiers). For location 3 (numeric keypad), + // it is necessary to set the |isKeypad| parameter. + if (it->location == 3) + params.SetBoolean("isKeypad", true); + else + params.SetInteger("location", it->location); + } Status status = client_->SendCommand("Input.dispatchKeyEvent", params); if (status.IsError()) return status;
diff --git a/chrome/test/chromedriver/key_converter.cc b/chrome/test/chromedriver/key_converter.cc index 612c9cc..e0d0eec 100644 --- a/chrome/test/chromedriver/key_converter.cc +++ b/chrome/test/chromedriver/key_converter.cc
@@ -9,6 +9,7 @@ #include "base/format_macros.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversion_utils.h" #include "base/strings/utf_string_conversions.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/chrome/ui_events.h" @@ -27,12 +28,13 @@ { kAltKeyModifierMask, ui::VKEY_MENU } }; -// TODO(kkania): Use this in KeyMap. // Ordered list of all the key codes corresponding to special WebDriver keys. -// These WebDriver keys are defined in the Unicode Private Use Area. -// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/value +// These keys are "special" in the sense that their code points are defined by +// the W3C spec (https://w3c.github.io/webdriver/#dfn-normalised-key-value), +// and are in the Unicode Private Use Area. All other keys have their code +// points defined by the Unicode standard. const ui::KeyboardCode kSpecialWebDriverKeys[] = { - ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, // \uE000 ui::VKEY_UNKNOWN, ui::VKEY_HELP, ui::VKEY_BACK, @@ -48,7 +50,7 @@ ui::VKEY_SPACE, ui::VKEY_PRIOR, // page up ui::VKEY_NEXT, // page down - ui::VKEY_END, + ui::VKEY_END, // \uE010 ui::VKEY_HOME, ui::VKEY_LEFT, ui::VKEY_UP, @@ -64,7 +66,7 @@ ui::VKEY_NUMPAD3, ui::VKEY_NUMPAD4, ui::VKEY_NUMPAD5, - ui::VKEY_NUMPAD6, + ui::VKEY_NUMPAD6, // \uE020 ui::VKEY_NUMPAD7, ui::VKEY_NUMPAD8, ui::VKEY_NUMPAD9, @@ -80,7 +82,7 @@ ui::VKEY_UNKNOWN, ui::VKEY_UNKNOWN, ui::VKEY_UNKNOWN, - ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, // \uE030 ui::VKEY_F1, ui::VKEY_F2, ui::VKEY_F3, @@ -92,13 +94,51 @@ ui::VKEY_F9, ui::VKEY_F10, ui::VKEY_F11, - ui::VKEY_F12}; + ui::VKEY_F12, + ui::VKEY_LWIN, // meta + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_DBE_DBCSCHAR, // \uE040 ZenkakuHankaku + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_UNKNOWN, + ui::VKEY_RSHIFT, // \uE050 + ui::VKEY_RCONTROL, + ui::VKEY_RMENU, + ui::VKEY_RWIN, // meta + ui::VKEY_PRIOR, // page up + ui::VKEY_NEXT, // page down + ui::VKEY_END, + ui::VKEY_HOME, + ui::VKEY_LEFT, + ui::VKEY_UP, + ui::VKEY_RIGHT, + ui::VKEY_DOWN, + ui::VKEY_INSERT, + ui::VKEY_DELETE, +}; const base::char16 kWebDriverNullKey = 0xE000U; const base::char16 kWebDriverShiftKey = 0xE008U; const base::char16 kWebDriverControlKey = 0xE009U; const base::char16 kWebDriverAltKey = 0xE00AU; const base::char16 kWebDriverCommandKey = 0xE03DU; +const base::char16 kWebDriverRightShiftKey = 0xE050U; +const base::char16 kWebDriverRightControlKey = 0xE051U; +const base::char16 kWebDriverRightAltKey = 0xE052U; +const base::char16 kWebDriverRightCommandKey = 0xE053U; // Returns whether the given key code has a corresponding printable char. // Notice: The given key code should be a special WebDriver key code. @@ -116,6 +156,10 @@ case kWebDriverControlKey: case kWebDriverAltKey: case kWebDriverCommandKey: + case kWebDriverRightShiftKey: + case kWebDriverRightControlKey: + case kWebDriverRightAltKey: + case kWebDriverRightCommandKey: return true; default: return false; @@ -168,6 +212,240 @@ return true; } +// The "normalised key value" table from W3C spec +// (https://w3c.github.io/webdriver/#dfn-normalised-key-value). +// The code point starts at \uE000 and must increase by 1 with each row, +// with placeholders (empty strings) used for unassigned code points. +const int kNormalisedKeyValueBase = 0xE000; +const char* const kNormalisedKeyValue[] = { + "Unidentified", // \uE000 + "Cancel", // \uE001 + "Help", // \uE002 + "Backspace", // \uE003 + "Tab", // \uE004 + "Clear", // \uE005 + "Return", // \uE006 + "Enter", // \uE007 + "Shift", // \uE008 + "Control", // \uE009 + "Alt", // \uE00A + "Pause", // \uE00B + "Escape", // \uE00C + " ", // \uE00D + "PageUp", // \uE00E + "PageDown", // \uE00F + "End", // \uE010 + "Home", // \uE011 + "ArrowLeft", // \uE012 + "ArrowUp", // \uE013 + "ArrowRight", // \uE014 + "ArrowDown", // \uE015 + "Insert", // \uE016 + "Delete", // \uE017 + ";", // \uE018 + "=", // \uE019 + "0", // \uE01A + "1", // \uE01B + "2", // \uE01C + "3", // \uE01D + "4", // \uE01E + "5", // \uE01F + "6", // \uE020 + "7", // \uE021 + "8", // \uE022 + "9", // \uE023 + "*", // \uE024 + "+", // \uE025 + ",", // \uE026 + "-", // \uE027 + ".", // \uE028 + "/", // \uE029 + "", + "", + "", + "", + "", + "", + "", + "F1", // \uE031 + "F2", // \uE032 + "F3", // \uE033 + "F4", // \uE034 + "F5", // \uE035 + "F6", // \uE036 + "F7", // \uE037 + "F8", // \uE038 + "F9", // \uE039 + "F10", // \uE03A + "F11", // \uE03B + "F12", // \uE03C + "Meta", // \uE03D + "", + "", + "ZenkakuHankaku", // \uE040 + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Shift", // \uE050 + "Control", // \uE051 + "Alt", // \uE052 + "Meta", // \uE053 + "PageUp", // \uE054 + "PageDown", // \uE055 + "End", // \uE056 + "Home", // \uE057 + "ArrowLeft", // \uE058 + "ArrowUp", // \uE059 + "ArrowRight", // \uE05A + "ArrowDown", // \uE05B + "Insert", // \uE05C + "Delete", // \uE05D +}; + +// The "code for key" table (https://w3c.github.io/webdriver/#dfn-code), +// with the following modifications: +// * Fixed some inconsistencies in the original table. +// See https://github.com/w3c/webdriver/pull/1384. +// * Replaced "OSLeft" and "OSRight" with "MetaLeft" and "MetaRight", to be +// compatible with Chrome. +// TODO(johnchen@chromium.org): Find a better way to handle this. +const struct { + base::char16 key; + base::char16 alternate_key; + std::string code; +} kCodeForKey[] = { + {'`', '~', "Backquote"}, + {'\\', '|', "Backslash"}, + {0xE003, 0, "Backspace"}, + {'[', '{', "BracketLeft"}, + {']', '}', "BracketRight"}, + {',', '<', "Comma"}, + {'0', ')', "Digit0"}, + {'1', '!', "Digit1"}, + {'2', '@', "Digit2"}, + {'3', '#', "Digit3"}, + {'4', '$', "Digit4"}, + {'5', '%', "Digit5"}, + {'6', '^', "Digit6"}, + {'7', '&', "Digit7"}, + {'8', '*', "Digit8"}, + {'9', '(', "Digit9"}, + {'=', '+', "Equal"}, + {'<', '>', "IntlBackslash"}, + {'a', 'A', "KeyA"}, + {'b', 'B', "KeyB"}, + {'c', 'C', "KeyC"}, + {'d', 'D', "KeyD"}, + {'e', 'E', "KeyE"}, + {'f', 'F', "KeyF"}, + {'g', 'G', "KeyG"}, + {'h', 'H', "KeyH"}, + {'i', 'I', "KeyI"}, + {'j', 'J', "KeyJ"}, + {'k', 'K', "KeyK"}, + {'l', 'L', "KeyL"}, + {'m', 'M', "KeyM"}, + {'n', 'N', "KeyN"}, + {'o', 'O', "KeyO"}, + {'p', 'P', "KeyP"}, + {'q', 'Q', "KeyQ"}, + {'r', 'R', "KeyR"}, + {'s', 'S', "KeyS"}, + {'t', 'T', "KeyT"}, + {'u', 'U', "KeyU"}, + {'v', 'V', "KeyV"}, + {'w', 'W', "KeyW"}, + {'x', 'X', "KeyX"}, + {'y', 'Y', "KeyY"}, + {'z', 'Z', "KeyZ"}, + {'-', '_', "Minus"}, + {'.', '>', "Period"}, + {'\'', '"', "Quote"}, + {';', ':', "Semicolon"}, + {'/', '?', "Slash"}, + {0xE00A, 0, "AltLeft"}, + {0xE052, 0, "AltRight"}, + {0xE009, 0, "ControlLeft"}, + {0xE051, 0, "ControlRight"}, + {0xE006, 0, "Enter"}, + {0xE03D, 0, "MetaLeft"}, + {0xE053, 0, "MetaRight"}, + {0xE008, 0, "ShiftLeft"}, + {0xE050, 0, "ShiftRight"}, + {' ', 0xE00D, "Space"}, + {0xE004, 0, "Tab"}, + {0xE017, 0, "Delete"}, + {0xE010, 0, "End"}, + {0xE002, 0, "Help"}, + {0xE011, 0, "Home"}, + {0xE016, 0, "Insert"}, + {0xE00F, 0, "PageDown"}, + {0xE00E, 0, "PageUp"}, + {0xE015, 0, "ArrowDown"}, + {0xE012, 0, "ArrowLeft"}, + {0xE014, 0, "ArrowRight"}, + {0xE013, 0, "ArrowUp"}, + {0xE00C, 0, "Escape"}, + {0xE031, 0, "F1"}, + {0xE032, 0, "F2"}, + {0xE033, 0, "F3"}, + {0xE034, 0, "F4"}, + {0xE035, 0, "F5"}, + {0xE036, 0, "F6"}, + {0xE037, 0, "F7"}, + {0xE038, 0, "F8"}, + {0xE039, 0, "F9"}, + {0xE03A, 0, "F10"}, + {0xE03B, 0, "F11"}, + {0xE03C, 0, "F12"}, + {0xE01A, 0xE05C, "Numpad0"}, + {0xE01B, 0xE056, "Numpad1"}, + {0xE01C, 0xE05B, "Numpad2"}, + {0xE01D, 0xE055, "Numpad3"}, + {0xE01E, 0xE058, "Numpad4"}, + {0xE01F, 0, "Numpad5"}, + {0xE020, 0xE05A, "Numpad6"}, + {0xE021, 0xE057, "Numpad7"}, + {0xE022, 0xE059, "Numpad8"}, + {0xE023, 0xE054, "Numpad9"}, + {0xE025, 0, "NumpadAdd"}, + {0xE026, 0, "NumpadComma"}, + {0xE028, 0xE05D, "NumpadDecimal"}, + {0xE029, 0, "NumpadDivide"}, + {0xE007, 0, "NumpadEnter"}, + {0xE024, 0, "NumpadMultiply"}, + {0xE027, 0, "NumpadSubtract"}, +}; + +// The "key location for key" table from W3C spec +// (https://w3c.github.io/webdriver/#dfn-key-location). For simplicity, it is +// implemented as a few 'if' statements, instead of as a true table. +int GetKeyLocation(uint32_t code_point) { + if (code_point >= 0xe007 && code_point <= 0xe00a) + return 1; + if (code_point >= 0xe01a && code_point <= 0xe029) + return 3; + if (code_point == 0xe03d) + return 1; + if (code_point >= 0xe050 && code_point <= 0xe053) + return 2; + if (code_point >= 0xe054 && code_point <= 0xe05d) + return 3; + return 0; +} + } // namespace Status ConvertKeysToKeyEvents(const base::string16& client_keys, @@ -205,19 +483,21 @@ // Press or release the modifier, and adjust |sticky_modifiers|. bool modifier_down = false; ui::KeyboardCode key_code = ui::VKEY_UNKNOWN; - if (key == kWebDriverShiftKey) { + if (key == kWebDriverShiftKey || key == kWebDriverRightShiftKey) { sticky_modifiers ^= kShiftKeyModifierMask; modifier_down = (sticky_modifiers & kShiftKeyModifierMask) != 0; key_code = ui::VKEY_SHIFT; - } else if (key == kWebDriverControlKey) { + } else if (key == kWebDriverControlKey || + key == kWebDriverRightControlKey) { sticky_modifiers ^= kControlKeyModifierMask; modifier_down = (sticky_modifiers & kControlKeyModifierMask) != 0; key_code = ui::VKEY_CONTROL; - } else if (key == kWebDriverAltKey) { + } else if (key == kWebDriverAltKey || key == kWebDriverRightAltKey) { sticky_modifiers ^= kAltKeyModifierMask; modifier_down = (sticky_modifiers & kAltKeyModifierMask) != 0; key_code = ui::VKEY_MENU; - } else if (key == kWebDriverCommandKey) { + } else if (key == kWebDriverCommandKey || + key == kWebDriverRightCommandKey) { sticky_modifiers ^= kMetaKeyModifierMask; modifier_down = (sticky_modifiers & kMetaKeyModifierMask) != 0; key_code = ui::VKEY_COMMAND; @@ -333,3 +613,164 @@ *modifiers = sticky_modifiers; return Status(kOk); } + +Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object, + base::DictionaryValue* input_state, + bool is_key_down, + std::vector<KeyEvent>* key_events) { + std::string raw_key; + if (!action_object->GetString("value", &raw_key)) + return Status(kUnknownError, "missing 'value'"); + + int32_t char_index = 0; + uint32_t code_point; + base::ReadUnicodeCharacter(raw_key.c_str(), raw_key.size(), &char_index, + &code_point); + + std::string key; + if (code_point >= kNormalisedKeyValueBase && + code_point < kNormalisedKeyValueBase + base::size(kNormalisedKeyValue)) { + key = kNormalisedKeyValue[code_point - kNormalisedKeyValueBase]; + } + if (key.size() == 0) + key = raw_key; + + base::DictionaryValue* pressed; + if (!input_state->GetDictionary("pressed", &pressed)) + return Status(kUnknownError, "missing 'pressed'"); + bool already_pressed = pressed->HasKey(key); + if (!is_key_down && !already_pressed) + return Status(kOk); + + std::string code; + if (code_point != 0) { + for (auto& mapping : kCodeForKey) { + if (mapping.key == code_point || mapping.alternate_key == code_point) { + code = mapping.code; + break; + } + } + } + + int modifiers; + if (!input_state->GetInteger("modifiers", &modifiers)) + return Status(kUnknownError, "missing 'modifiers'"); + + bool is_modifier_key = false; + bool is_special_key = false; + bool should_skip = false; + std::string unmodified_text, modified_text; + ui::KeyboardCode key_code = ui::VKEY_UNKNOWN; + std::string error_msg; + + is_modifier_key = IsModifierKey(code_point); + if (!is_modifier_key) + is_special_key = KeyCodeFromSpecialWebDriverKey(code_point, &key_code); + + if (is_modifier_key) { + int updated_modifier; + if (code_point == kWebDriverShiftKey) { + updated_modifier = kShiftKeyModifierMask; + key_code = ui::VKEY_SHIFT; + } else if (code_point == kWebDriverRightShiftKey) { + updated_modifier = kShiftKeyModifierMask; + key_code = ui::VKEY_RSHIFT; + } else if (code_point == kWebDriverControlKey) { + updated_modifier = kControlKeyModifierMask; + key_code = ui::VKEY_CONTROL; + } else if (code_point == kWebDriverRightControlKey) { + updated_modifier = kControlKeyModifierMask; + key_code = ui::VKEY_RCONTROL; + } else if (code_point == kWebDriverAltKey) { + updated_modifier = kAltKeyModifierMask; + key_code = ui::VKEY_MENU; + } else if (code_point == kWebDriverRightAltKey) { + updated_modifier = kAltKeyModifierMask; + key_code = ui::VKEY_RMENU; + } else if (code_point == kWebDriverCommandKey) { + updated_modifier = kMetaKeyModifierMask; + key_code = ui::VKEY_COMMAND; + } else if (code_point == kWebDriverRightCommandKey) { + updated_modifier = kMetaKeyModifierMask; + key_code = ui::VKEY_RWIN; + } else { + return Status(kUnknownError, "unknown modifier key"); + } + + if (is_key_down) + modifiers |= updated_modifier; + else + modifiers &= ~updated_modifier; + + input_state->SetInteger("modifiers", modifiers); + } else if (is_special_key || + KeyCodeFromShorthandKey(code_point, &key_code, &should_skip)) { + if (should_skip) + return Status(kOk); + if (key_code == ui::VKEY_RETURN) { + // For some reason Chrome expects a carriage return for the return key. + modified_text = unmodified_text = "\r"; + } else if (is_special_key && !IsSpecialKeyPrintable(key_code)) { + // To prevent char event for special keys like DELETE. + modified_text = unmodified_text = std::string(); + } else { + // WebDriver assumes a numpad key should translate to the number, + // which requires NumLock to be on with some platforms. This isn't + // formally in the spec, but is expected by their tests. + int webdriver_modifiers = 0; + if (key_code >= ui::VKEY_NUMPAD0 && key_code <= ui::VKEY_NUMPAD9) + webdriver_modifiers = kNumLockKeyModifierMask; + if (!ConvertKeyCodeToText(key_code, webdriver_modifiers, &unmodified_text, + &error_msg)) + return Status(kUnknownError, error_msg); + if (!ConvertKeyCodeToText(key_code, modifiers | webdriver_modifiers, + &modified_text, &error_msg)) + return Status(kUnknownError, error_msg); + } + } else { + int necessary_modifiers = 0; + ConvertCharToKeyCode(code_point, &key_code, &necessary_modifiers, + &error_msg); + if (!error_msg.empty()) + return Status(kUnknownError, error_msg); + if (key_code != ui::VKEY_UNKNOWN) { + modifiers |= necessary_modifiers; + if (!ConvertKeyCodeToText(key_code, 0, &unmodified_text, &error_msg)) + return Status(kUnknownError, error_msg); + if (!ConvertKeyCodeToText(key_code, modifiers, &modified_text, + &error_msg)) + return Status(kUnknownError, error_msg); + if (unmodified_text.empty() || modified_text.empty()) { + // To prevent char event for special cases like CTRL + x (cut). + unmodified_text.clear(); + modified_text.clear(); + } + } else { + // Do a best effort and use the raw key we were given. + unmodified_text = raw_key; + modified_text = raw_key; + } + } + + if (is_key_down) + pressed->SetBoolean(key, true); + else + pressed->Remove(key, nullptr); + + KeyEventBuilder builder; + builder.SetKeyCode(key_code) + ->SetModifiers(modifiers) + ->SetLocation(GetKeyLocation(code_point)) + ->SetDefaultKey(key) + ->SetCode(code) + ->SetIsFromAction(); + if (!is_modifier_key) + builder.SetText(unmodified_text, modified_text); + if (is_key_down) { + key_events->push_back(builder.SetType(kKeyDownEventType)->Build()); + } else { + key_events->push_back(builder.SetType(kKeyUpEventType)->Build()); + } + + return Status(kOk); +}
diff --git a/chrome/test/chromedriver/key_converter.h b/chrome/test/chromedriver/key_converter.h index ebed6b5..bc912bb9a 100644 --- a/chrome/test/chromedriver/key_converter.h +++ b/chrome/test/chromedriver/key_converter.h
@@ -9,6 +9,7 @@ #include <string> #include "base/strings/string16.h" +#include "base/values.h" #include "ui/events/keycodes/keyboard_codes.h" struct KeyEvent; @@ -24,4 +25,9 @@ int* modifiers, std::list<KeyEvent>* key_events); +Status ConvertKeyActionToKeyEvent(const base::DictionaryValue* action_object, + base::DictionaryValue* input_state, + bool is_key_down, + std::vector<KeyEvent>* client_key_events); + #endif // CHROME_TEST_CHROMEDRIVER_KEY_CONVERTER_H_
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 5548e4d..81b0a79 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -777,6 +777,74 @@ self._driver.PerformActions(actions) self.assertEquals(1, len(self._driver.FindElements('tag name', 'br'))) + def testActionsPause(self): + self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) + self._driver.ExecuteScript( + ''' + document.body.innerHTML + = "<input type='text' autofocus style='width:100px; height:100px'>"; + window.events = []; + const input = document.getElementsByTagName("input")[0]; + const listener + = e => window.events.push({type: e.type, time: e.timeStamp}); + input.addEventListener("keydown", listener); + input.addEventListener("keyup", listener); + input.addEventListener("mousedown", listener); + ''') + + # Actions on 3 devices, across 5 ticks, with 200 ms pause at each tick. + # Tick "key" device "pointer" device "none" device + # 0 "a" key down move for 200 ms pause 100 ms + # 1 pause 200 ms pointer down + # 2 "a" key up pointer up pause 200 ms + # 3 "b" key down pause 200 ms + # 4 "b" key up + actions = {'actions': [ + { + 'type': 'key', + 'id': 'key', + 'actions': [ + {'type': 'keyDown', 'value': 'a'}, + {'type': 'pause', 'duration': 200}, + {'type': 'keyUp', 'value': 'a'}, + {'type': 'keyDown', 'value': 'b'}, + {'type': 'keyUp', 'value': 'b'}, + ] + }, + { + 'type': 'pointer', + 'id': 'mouse', + 'actions': [ + {'type': 'pointerMove', 'duration': 200, 'x': 10, 'y': 10}, + {'type': 'pointerDown', 'button': 1}, + {'type': 'pointerUp', 'button': 1}, + {'type': 'pause', 'duration': 200}, + ] + }, + { + 'type': 'none', + 'id': 'none', + 'actions': [ + {'type': 'pause', 'duration': 100}, + {'type': 'pause'}, + {'type': 'pause', 'duration': 200}, + ] + } + ]} + + self._driver.PerformActions(actions) + events = self._driver.ExecuteScript('return window.events') + expected_events = ['keydown', 'mousedown', 'keyup', 'keydown', 'keyup'] + self.assertEquals(len(expected_events), len(events)) + for i in range(len(events)): + self.assertEqual(expected_events[i], events[i]['type']) + if i > 0: + elapsed_time = events[i]['time'] - events[i-1]['time'] + self.assertGreaterEqual(elapsed_time, 200) + # Elapsed time can be anything above 200 ms. Arbitrarily select 300 ms + # as the upper limit. + self.assertLessEqual(elapsed_time, 300) + def testPageLoadStrategyIsNormalByDefault(self): self.assertEquals('normal', self._driver.capabilities['pageLoadStrategy'])
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 329646a..fc359ad9 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversion_utils.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -171,6 +172,14 @@ } } +PointerType StringToPointerType(std::string pointer_type) { + CHECK(pointer_type == "pen" || pointer_type == "mouse"); + if (pointer_type == "pen") + return kPen; + else + return kMouse; +} + struct Cookie { Cookie(const std::string& name, const std::string& value, @@ -346,6 +355,39 @@ return Status(kOk); } +// Implements "compute the tick duration" algorithm from W3C spec +// (https://w3c.github.io/webdriver/#dfn-computing-the-tick-duration). +// For convenience, this function computes durations of all ticks, while the +// original algorithm computes duration of one tick. +void ComputeTickDurations(std::vector<int>* tick_durations, + const base::ListValue& actions_list) { + for (size_t i = 0; i < actions_list.GetSize(); i++) { + const base::DictionaryValue* action_sequence = nullptr; + actions_list.GetDictionary(i, &action_sequence); + const base::ListValue* actions = nullptr; + action_sequence->GetList("actions", &actions); + std::string type; + action_sequence->GetString("sourceType", &type); + + for (size_t j = 0; j < actions->GetSize(); j++) { + const base::DictionaryValue* action = nullptr; + actions->GetDictionary(j, &action); + std::string subtype; + action->GetString("subtype", &subtype); + + if (subtype == "pause" || + (type == "pointer" && subtype == "pointerMove")) { + if (j >= tick_durations->size()) + tick_durations->resize(j + 1); + int duration = 0; + GetOptionalInt(action, "duration", &duration); + if (duration > (*tick_durations)[j]) + (*tick_durations)[j] = duration; + } + } + } +} + Status ElementInViewCenter(Session* session, WebView* web_view, std::string element_id, @@ -995,17 +1037,14 @@ base::DictionaryValue tmp_state; tmp_state.SetString("id", id); if (type == "key") { - std::unique_ptr<base::ListValue> pressed(new base::ListValue); - bool alt = false; - bool shift = false; - bool ctrl = false; - bool meta = false; - - tmp_state.SetList("pressed", std::move(pressed)); - tmp_state.SetBoolean("alt", alt); - tmp_state.SetBoolean("shift", shift); - tmp_state.SetBoolean("ctrl", ctrl); - tmp_state.SetBoolean("meta", meta); + // Initialize a key input state object + // (https://w3c.github.io/webdriver/#dfn-key-input-state). + tmp_state.SetDictionary("pressed", + std::make_unique<base::DictionaryValue>()); + // For convenience, we use one integer property to encode four Boolean + // properties (alt, shift, ctrl, meta) from the spec, using values from + // enum KeyModifierMask. + tmp_state.SetInteger("modifiers", 0); } else if (type == "pointer") { std::unique_ptr<base::ListValue> pressed(new base::ListValue); int x = 0; @@ -1065,11 +1104,19 @@ return status; } else { std::string key; - // TODO: check if key is a single unicode code point - if (!action_item->GetString("value", &key)) { - return Status(kInvalidArgument, - "'value' must be a single unicode point"); + bool valid = action_item->GetString("value", &key); + if (valid) { + // check if key is a single unicode code point + int32_t char_index = 0; + uint32_t code_point; + valid = + base::ReadUnicodeCharacter(key.c_str(), key.size(), &char_index, + &code_point) && + static_cast<std::string::size_type>(char_index + 1) == key.size(); } + if (!valid) + return Status(kInvalidArgument, + "'value' must be a single Unicode code point"); action->SetString("value", key); } } else if (type == "pointer") { @@ -1085,7 +1132,7 @@ action->SetString("subtype", subtype); if (subtype == "pointerDown" || subtype == "pointerUp") { - if (pointer_type == "mouse") { + if (pointer_type == "mouse" || pointer_type == "pen") { int button; if (!action_item->GetInteger("button", &button) || button < 0 || button > 4) { @@ -1211,36 +1258,19 @@ action->GetString("subtype", &subtype); std::string id; action->GetString("id", &id); + + base::DictionaryValue* input_state; + if (!session->input_state_table.GetDictionary(id, &input_state)) + return Status(kUnknownError, "missing input state"); + if (subtype == "pause") { key_events.push_back(builder.SetType(kPauseEventType)->Build()); } else { - base::DictionaryValue dispatch_params; - base::string16 raw_key; - action->GetString("value", &raw_key); - base::char16 key = raw_key[0]; - // TODO: understand necessary_modifiers - int necessary_modifiers = 0; - ui::KeyboardCode key_code = ui::VKEY_UNKNOWN; - std::string error_msg; - ConvertCharToKeyCode(key, &key_code, &necessary_modifiers, - &error_msg); - if (!error_msg.empty()) - return Status(kUnknownError, error_msg); + Status status = ConvertKeyActionToKeyEvent( + action, input_state, subtype == "keyDown", &key_events); - if (subtype == "keyDown") - key_events.push_back(builder.SetType(kKeyDownEventType) - ->SetText(base::UTF16ToUTF8(raw_key), - base::UTF16ToUTF8(raw_key)) - ->SetKeyCode(key_code) - ->SetModifiers(0) - ->Build()); - else if (subtype == "keyUp") - key_events.push_back(builder.SetType(kKeyUpEventType) - ->SetText(base::UTF16ToUTF8(raw_key), - base::UTF16ToUTF8(raw_key)) - ->SetKeyCode(key_code) - ->SetModifiers(0) - ->Build()); + if (status.IsError()) + return status; } } longest_key_list_size = @@ -1288,7 +1318,7 @@ } } - if (pointer_type == "mouse") { + if (pointer_type == "mouse" || pointer_type == "pen") { int click_count = 0; if (action_type == "pointerDown" || action_type == "pointerUp") { pointer_action->GetString("button", &button_type); @@ -1298,6 +1328,7 @@ StringToMouseButton(button_type), x, y, 0, buttons, click_count); event.element_id = element_id; + event.pointer_type = StringToPointerType(pointer_type); mouse_events.push_back(event); if (action_type == "pointerDown") buttons |= StringToModifierMouseButton(button_type); @@ -1317,7 +1348,7 @@ } } - if (pointer_type == "mouse") { + if (pointer_type == "mouse" || pointer_type == "pen") { longest_mouse_list_size = std::max(mouse_events.size(), longest_mouse_list_size); mouse_events_list.push_back(mouse_events); @@ -1329,9 +1360,12 @@ } } + std::vector<int> tick_durations; + ComputeTickDurations(&tick_durations, actions_list); + size_t max_list_length = - std::max(std::max(longest_mouse_list_size, longest_touch_list_size), - longest_key_list_size); + std::max({longest_mouse_list_size, longest_touch_list_size, + longest_key_list_size, tick_durations.size()}); std::map<std::string, gfx::Point> element_center_point; for (size_t i = 0; i < max_list_length; i++) { std::list<MouseEvent> dispatch_mouse_events; @@ -1401,6 +1435,10 @@ if (status.IsError()) return status; } + if (i < tick_durations.size() && tick_durations[i] > 0) { + base::PlatformThread::Sleep( + base::TimeDelta::FromMilliseconds(tick_durations[i])); + } } return Status(kOk); }
diff --git a/chrome/test/data/prerender/prerender_loader_with_unload.html b/chrome/test/data/prerender/prerender_loader_with_unload.html index 53e3398..cb3a5a2 100644 --- a/chrome/test/data/prerender/prerender_loader_with_unload.html +++ b/chrome/test/data/prerender/prerender_loader_with_unload.html
@@ -6,10 +6,8 @@ <script> function UnloadHandler() { // Signal to the browser the unload happened by hitting a URL. Must - // be synchronous so the request isn't cancelled. - var xhr = new XMLHttpRequest(); - xhr.open('GET', '/unload-url', false); - xhr.send(); + // not be cancelled. + fetch('/unload-url', {method: 'GET', keepalive: true}); } addEventListener('unload', UnloadHandler, false);
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js index d0d7e78a..8057ee7 100644 --- a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js +++ b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js
@@ -22,13 +22,18 @@ let nativeLayer = null; /** @override */ + suiteSetup(function() { + print_preview_test_utils.setupTestListenerElement(); + }); + + /** @override */ setup(function() { // Create destinations. nativeLayer = new print_preview.NativeLayerStub(); print_preview.NativeLayer.setInstance(nativeLayer); const userInfo = new print_preview.UserInfo(); - destinationStore = new print_preview.DestinationStore( - userInfo, new WebUIListenerTracker()); + destinationStore = + print_preview_test_utils.createDestinationStore(userInfo); const localDestinations = []; const destinations = print_preview_test_utils.getDestinations( nativeLayer, localDestinations);
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_test.js b/chrome/test/data/webui/print_preview/destination_dialog_test.js index 1f96e5aa..81493ada 100644 --- a/chrome/test/data/webui/print_preview/destination_dialog_test.js +++ b/chrome/test/data/webui/print_preview/destination_dialog_test.js
@@ -34,13 +34,18 @@ let recentDestinations = []; /** @override */ + suiteSetup(function() { + print_preview_test_utils.setupTestListenerElement(); + }); + + /** @override */ setup(function() { // Create data classes nativeLayer = new print_preview.NativeLayerStub(); print_preview.NativeLayer.setInstance(nativeLayer); userInfo = new print_preview.UserInfo(); - destinationStore = new print_preview.DestinationStore( - userInfo, new WebUIListenerTracker()); + destinationStore = + print_preview_test_utils.createDestinationStore(userInfo); destinations = print_preview_test_utils.getDestinations( nativeLayer, localDestinations); recentDestinations =
diff --git a/chrome/test/data/webui/print_preview/destination_search_test.js b/chrome/test/data/webui/print_preview/destination_search_test.js index 39736c9..114ec68 100644 --- a/chrome/test/data/webui/print_preview/destination_search_test.js +++ b/chrome/test/data/webui/print_preview/destination_search_test.js
@@ -29,13 +29,18 @@ let nativeLayer = null; /** @override */ + suiteSetup(function() { + print_preview_test_utils.setupTestListenerElement(); + }); + + /** @override */ setup(function() { // Create data classes nativeLayer = new print_preview.NativeLayerStub(); print_preview.NativeLayer.setInstance(nativeLayer); userInfo = new print_preview.UserInfo(); - destinationStore = new print_preview.DestinationStore( - userInfo, new WebUIListenerTracker()); + destinationStore = + print_preview_test_utils.createDestinationStore(userInfo); nativeLayer.setLocalDestinationCapabilities( print_preview_test_utils.getCddTemplate('FooDevice', 'FooName')); destinationStore.init(
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js index b94cb19..67ece56 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test.js +++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -14,6 +14,11 @@ let destinationSettings = null; /** @override */ + suiteSetup(function() { + print_preview_test_utils.setupTestListenerElement(); + }); + + /** @override */ setup(function() { PolymerTest.clearBody(); const nativeLayer = new print_preview.NativeLayerStub(); @@ -37,8 +42,8 @@ // Set up the destination store, but no destination yet. Button is // disabled. const userInfo = new print_preview.UserInfo(); - const destinationStore = new print_preview.DestinationStore( - userInfo, new WebUIListenerTracker()); + const destinationStore = + print_preview_test_utils.createDestinationStore(userInfo); destinationStore.init( false /* isInAppKioskMode */, 'FooDevice' /* printerName */, '' /* serializedDefaultDestinationSelectionRulesStr */,
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index 571a4a9..25a7528 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -685,7 +685,7 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ - ROOT_PATH + 'ui/webui/resources/js/webui_listener_tracker.js', + ROOT_PATH + 'ui/webui/resources/js/web_ui_listener_behavior.js', ROOT_PATH + 'ui/webui/resources/js/cr/event_target.js', '../settings/test_util.js', '../test_browser_proxy.js', @@ -846,7 +846,7 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ - ROOT_PATH + 'ui/webui/resources/js/webui_listener_tracker.js', + ROOT_PATH + 'ui/webui/resources/js/web_ui_listener_behavior.js', '../settings/test_util.js', '../test_browser_proxy.js', 'native_layer_stub.js', @@ -1150,9 +1150,10 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ - ROOT_PATH + 'ui/webui/resources/js/webui_listener_tracker.js', + ROOT_PATH + 'ui/webui/resources/js/web_ui_listener_behavior.js', '../test_browser_proxy.js', 'native_layer_stub.js', + 'print_preview_test_utils.js', 'destination_settings_test.js', ]); }
diff --git a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js index da1f677f..d648b97 100644 --- a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js
@@ -73,7 +73,7 @@ get extraLibraries() { return super.extraLibraries.concat([ ROOT_PATH + 'chrome/test/data/webui/settings/test_util.js', - ROOT_PATH + 'ui/webui/resources/js/webui_listener_tracker.js', + ROOT_PATH + 'ui/webui/resources/js/web_ui_listener_behavior.js', '../test_browser_proxy.js', 'native_layer_stub.js', 'print_preview_test_utils.js',
diff --git a/chrome/test/data/webui/print_preview/print_preview_test_utils.js b/chrome/test/data/webui/print_preview/print_preview_test_utils.js index 84f7bf1..11286e8 100644 --- a/chrome/test/data/webui/print_preview/print_preview_test_utils.js +++ b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
@@ -291,18 +291,43 @@ new CustomEvent('input', {composed: true, bubbles: true})); } + function setupTestListenerElement() { + const domModule = document.createElement('dom-module'); + domModule.setAttribute('id', 'test-listener-element'); + domModule.appendChild(document.createElement('template')); + document.body.appendChild(domModule); + Polymer({ + is: 'test-listener-element', + behaviors: [WebUIListenerBehavior], + }); + } + + /** + * @param {!print_preview.UserInfo} userInfo + * @return {!print_preview.DestinationStore} + */ + function createDestinationStore(userInfo) { + const testListenerElement = document.createElement('test-listener-element'); + document.body.appendChild(testListenerElement); + return new print_preview.DestinationStore( + userInfo, + testListenerElement.addWebUIListener.bind(testListenerElement)); + } + return { - getDefaultInitialSettings: getDefaultInitialSettings, - getCddTemplate: getCddTemplate, - getCddTemplateWithAdvancedSettings: getCddTemplateWithAdvancedSettings, - getDefaultMediaSize: getDefaultMediaSize, - getDefaultOrientation: getDefaultOrientation, + createDestinationStore: createDestinationStore, createDestinationWithCertificateStatus: createDestinationWithCertificateStatus, + getCddTemplate: getCddTemplate, + getCddTemplateWithAdvancedSettings: getCddTemplateWithAdvancedSettings, + getDefaultInitialSettings: getDefaultInitialSettings, + getDefaultMediaSize: getDefaultMediaSize, + getDefaultOrientation: getDefaultOrientation, getDestinations: getDestinations, getMediaSizeCapabilityWithCustomNames: getMediaSizeCapabilityWithCustomNames, getPdfPrinter: getPdfPrinter, + setupTestListenerElement: setupTestListenerElement, triggerInputEvent: triggerInputEvent, }; });
diff --git a/chrome/utility/mash_service_factory.cc b/chrome/utility/mash_service_factory.cc index fa980b87..da86094 100644 --- a/chrome/utility/mash_service_factory.cc +++ b/chrome/utility/mash_service_factory.cc
@@ -11,7 +11,7 @@ #include "ash/components/quick_launch/quick_launch_application.h" #include "ash/components/shortcut_viewer/public/mojom/shortcut_viewer.mojom.h" #include "ash/components/shortcut_viewer/shortcut_viewer_application.h" -#include "ash/components/tap_visualizer/public/mojom/constants.mojom.h" +#include "ash/components/tap_visualizer/public/mojom/tap_visualizer.mojom.h" #include "ash/components/tap_visualizer/tap_visualizer_app.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h"
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 21a6e66..616026a6 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -166,6 +166,9 @@ <message name="IDS_ASH_ADD_USER_BUTTON" desc="Text shown on an add user button on login/locker screen"> Add Person </message> + <message name="IDS_ASH_PARENT_ACCESS_BUTTON" desc="Text shown on an parent access button on login/lock screen"> + Parent access + </message> <message name="IDS_ASH_SHELF_APPS_BUTTON" desc="Text shown on apps button on login screen."> Apps </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_ASH_PARENT_ACCESS_BUTTON.png.sha1 b/chromeos/chromeos_strings_grd/IDS_ASH_PARENT_ACCESS_BUTTON.png.sha1 new file mode 100644 index 0000000..84b93a1 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_ASH_PARENT_ACCESS_BUTTON.png.sha1
@@ -0,0 +1 @@ +0c66f67616eaa0fdc226f46282ff1e235ffa3f83 \ No newline at end of file
diff --git a/chromeos/network/network_state_test.cc b/chromeos/network/network_state_test.cc index a65cd93..7ca514a7 100644 --- a/chromeos/network/network_state_test.cc +++ b/chromeos/network/network_state_test.cc
@@ -57,6 +57,14 @@ network_state_handler_->Shutdown(); } +void NetworkStateTest::ClearDefaultServices() { + DBusThreadManager::Get() + ->GetShillServiceClient() + ->GetTestInterface() + ->ClearServices(); + base::RunLoop().RunUntilIdle(); +} + std::string NetworkStateTest::ConfigureService( const std::string& shill_json_string) { last_created_service_path_ = "";
diff --git a/chromeos/network/network_state_test.h b/chromeos/network/network_state_test.h index cad8250d..e12044f 100644 --- a/chromeos/network/network_state_test.h +++ b/chromeos/network/network_state_test.h
@@ -28,6 +28,9 @@ // Call this before TearDown() to shut down NetworkStateHandler. void ShutdownNetworkState(); + // Clears services that are set by fake shill service manager by default. + void ClearDefaultServices(); + // Configures a new service using Shill properties from |shill_json_string| // which must include a GUID and Type. Returns the service path, or "" if the // service could not be configured.
diff --git a/components/autofill/content/common/autofill_types.mojom b/components/autofill/content/common/autofill_types.mojom index ea443f0..b1ab281 100644 --- a/components/autofill/content/common/autofill_types.mojom +++ b/components/autofill/content/common/autofill_types.mojom
@@ -108,7 +108,10 @@ BUTTON_ELEMENT_SUBMIT_TYPE, BUTTON_ELEMENT_BUTTON_TYPE, INPUT_ELEMENT_SUBMIT_TYPE, - INPUT_ELEMENT_BUTTON_TYPE + INPUT_ELEMENT_BUTTON_TYPE, + HYPERLINK, + DIV, + SPAN }; // autofill::FormFieldData
diff --git a/components/autofill/content/common/autofill_types_struct_traits.cc b/components/autofill/content/common/autofill_types_struct_traits.cc index 9ea94763d..0a2bb00e 100644 --- a/components/autofill/content/common/autofill_types_struct_traits.cc +++ b/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -541,6 +541,12 @@ return autofill::mojom::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE; case autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE: return autofill::mojom::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE; + case autofill::ButtonTitleType::HYPERLINK: + return autofill::mojom::ButtonTitleType::HYPERLINK; + case autofill::ButtonTitleType::DIV: + return autofill::mojom::ButtonTitleType::DIV; + case autofill::ButtonTitleType::SPAN: + return autofill::mojom::ButtonTitleType::SPAN; } NOTREACHED(); return autofill::mojom::ButtonTitleType::NONE; @@ -566,6 +572,15 @@ case autofill::mojom::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE: *output = autofill::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE; return true; + case autofill::mojom::ButtonTitleType::HYPERLINK: + *output = autofill::ButtonTitleType::HYPERLINK; + return true; + case autofill::mojom::ButtonTitleType::DIV: + *output = autofill::ButtonTitleType::DIV; + return true; + case autofill::mojom::ButtonTitleType::SPAN: + *output = autofill::ButtonTitleType::SPAN; + return true; } NOTREACHED(); return false;
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 971072d2..bdc47a09 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -9,6 +9,7 @@ #include <map> #include <memory> #include <set> +#include <string> #include <utility> #include <vector> @@ -75,6 +76,13 @@ // Maximal length of all button titles. const int kMaxLengthForAllButtonTitles = 200; +// Text features to detect form submission buttons. Features are selected based +// on analysis of real forms and their buttons. +// TODO(crbug.com/910546): Consider to add more features (e.g. non-English +// features). +const char* const kButtonFeatures[] = {"button", "btn", "submit", + "boton" /* "button" in Spanish */}; + // A bit field mask for FillForm functions to not fill some fields. enum FieldFilterMask { FILTER_NONE = 0, @@ -366,15 +374,15 @@ // Helper function to add a button's |title| to the |list| and updates the // |total_length| of stored titles. Returns true iff the list still have free // capacity. -bool AddButtonTitleToList(base::string16&& title, +bool AddButtonTitleToList(base::string16 title, ButtonTitleType button_type, ButtonTitleList* list, int* total_length) { if (*total_length >= kMaxLengthForAllButtonTitles) return false; + title = base::CollapseWhitespace(std::move(title), false); if (title.empty()) return true; - title = base::CollapseWhitespace(std::move(title), false); TruncateString(&title, std::min(kMaxLengthForSingleButtonTitle, kMaxLengthForAllButtonTitles - *total_length)); @@ -383,6 +391,59 @@ return *total_length < kMaxLengthForAllButtonTitles; } +// Returns true iff |attribute| contains one of |kButtonFeatures|. +bool AttributeHasButtonFeature(const WebString& attribute) { + if (attribute.IsNull()) + return false; + std::string value = attribute.Utf8(); + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + for (const char* const button_feature : kButtonFeatures) { + if (value.find(button_feature, 0) != std::string::npos) + return true; + } + return false; +} + +// Returns true if |element|'s id, name or css class contain |kButtonFeatures|. +bool ElementAttributesHasButtonFeature(const WebElement& element) { + return AttributeHasButtonFeature(element.GetAttribute("id")) || + AttributeHasButtonFeature(element.GetAttribute("name")) || + AttributeHasButtonFeature(element.GetAttribute("class")); +} + +// Finds elements from |elements| that contains |kButtonFeatures|, adds them to +// |list| and updates the |total_length| of the |list|'s items. +// If |extract_value_attribute|, the "value" attribute is extracted as a button +// title. Otherwise, |WebElement::TextContent| (aka innerText in Javascript) is +// extracted as a title. +void FindElementsWithButtonFeatures(const WebElementCollection& elements, + ButtonTitleType button_type, + bool extract_value_attribute, + ButtonTitleList* list, + int* total_length) { + static base::NoDestructor<WebString> kValue("value"); + if (*total_length >= kMaxLengthForAllButtonTitles) + return; + for (WebElement item = elements.FirstItem(); + !item.IsNull() && *total_length < kMaxLengthForAllButtonTitles; + item = elements.NextItem()) { + if (!ElementAttributesHasButtonFeature(item)) + continue; + + base::string16 title = + extract_value_attribute + ? (item.HasAttribute(*kValue) ? item.GetAttribute(*kValue).Utf16() + : base::string16()) + : item.TextContent().Utf16(); + if (extract_value_attribute && title.empty()) + title = item.TextContent().Utf16(); + if (!AddButtonTitleToList(std::move(title), button_type, list, + total_length)) { + break; + } + } +} + // Helper for |InferLabelForElement()| that infers a label, if possible, from // a previous sibling of |element|, // e.g. Some Text <input ...> @@ -809,6 +870,9 @@ ButtonTitleList InferButtonTitlesForForm(const WebFormElement& form_element) { static base::NoDestructor<WebString> kSubmit("submit"); static base::NoDestructor<WebString> kButton("button"); + static base::NoDestructor<WebString> kA("a"); + static base::NoDestructor<WebString> kDiv("div"); + static base::NoDestructor<WebString> kSpan("span"); ButtonTitleList result; WebVector<WebFormControlElement> control_elements; @@ -821,7 +885,7 @@ control_element.FormControlTypeForAutofill() == *kButton; if (!is_submit_input && !is_button_input) continue; - base::string16&& title = control_element.Value().Utf16(); + base::string16 title = control_element.Value().Utf16(); if (!AddButtonTitleToList(std::move(title), is_submit_input ? ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE @@ -842,7 +906,7 @@ continue; } bool is_submit_type = type_attribute.IsNull() || type_attribute == *kSubmit; - base::string16&& title = item.TextContent().Utf16(); + base::string16 title = item.TextContent().Utf16(); if (!AddButtonTitleToList(std::move(title), is_submit_type ? ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE @@ -851,6 +915,15 @@ break; } } + FindElementsWithButtonFeatures( + form_element.GetElementsByHTMLTagName(*kA), ButtonTitleType::HYPERLINK, + true /* extract_value_attribute */, &result, &total_length); + FindElementsWithButtonFeatures( + form_element.GetElementsByHTMLTagName(*kDiv), ButtonTitleType::DIV, + false /* extract_value_attribute */, &result, &total_length); + FindElementsWithButtonFeatures( + form_element.GetElementsByHTMLTagName(*kSpan), ButtonTitleType::SPAN, + false /* extract_value_attribute */, &result, &total_length); return result; }
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index a05e245..a43be23 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -273,6 +273,10 @@ " <input type='button' value='\n Show\t password '>" " <button>Sign Up</button>" " <button type='button'>Register</button>" + " <a id='Submit' value='Create account'>" + " <div name='BTN'> Join </div>" + " <span class='button'> Start </span>" + " <a class='empty button' value=' \t \n'>" "</form>"; LoadHTML(kHtml); @@ -291,7 +295,11 @@ {base::UTF8ToUTF16("Sign Up"), autofill::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE}, {base::UTF8ToUTF16("Register"), - autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE}}; + autofill::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE}, + {base::UTF8ToUTF16("Create account"), + autofill::ButtonTitleType::HYPERLINK}, + {base::UTF8ToUTF16("Join"), autofill::ButtonTitleType::DIV}, + {base::UTF8ToUTF16("Start"), autofill::ButtonTitleType::SPAN}}; EXPECT_EQ(expected, actual); }
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 7d159ac..b646acb8 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -288,6 +288,32 @@ return HTML_TYPE_UNRECOGNIZED; } +// Helper function for explicit conversion between |ButtonTitleType| defined in +// "button_title_type.h" and "server.proto". +AutofillUploadContents_ButtonTitle_ButtonTitleType ToServerButtonTitleType( + autofill::ButtonTitleType input) { + switch (input) { + case ButtonTitleType::NONE: + return AutofillUploadContents::ButtonTitle::NONE; + case ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE: + return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_SUBMIT_TYPE; + case ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE: + return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_BUTTON_TYPE; + case ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE: + return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_SUBMIT_TYPE; + case ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE: + return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_BUTTON_TYPE; + case ButtonTitleType::HYPERLINK: + return AutofillUploadContents::ButtonTitle::HYPERLINK; + case ButtonTitleType::DIV: + return AutofillUploadContents::ButtonTitle::DIV; + case ButtonTitleType::SPAN: + return AutofillUploadContents::ButtonTitle::SPAN; + } + NOTREACHED(); + return AutofillUploadContents::ButtonTitle::NONE; +} + std::ostream& operator<<( std::ostream& out, const autofill::AutofillQueryResponseContents& response) { @@ -575,9 +601,7 @@ for (const ButtonTitleInfo& e : button_titles_) { auto* button_title = upload->add_button_title(); button_title->set_title(base::UTF16ToUTF8(e.first)); - button_title->set_type( - static_cast<AutofillUploadContents_ButtonTitle_ButtonTitleType>( - e.second)); + button_title->set_type(ToServerButtonTitleType(e.second)); } }
diff --git a/components/autofill/core/browser/proto/server.proto b/components/autofill/core/browser/proto/server.proto index 74472b38..35326fe 100644 --- a/components/autofill/core/browser/proto/server.proto +++ b/components/autofill/core/browser/proto/server.proto
@@ -384,6 +384,9 @@ BUTTON_ELEMENT_BUTTON_TYPE = 2; // <button type='button'> INPUT_ELEMENT_SUBMIT_TYPE = 3; // <input type='submit'> INPUT_ELEMENT_BUTTON_TYPE = 4; // <input type='button'> + HYPERLINK = 5; // e.g. <a class='button'> + DIV = 6; // e.g. <div id='submit'> + SPAN = 7; // e.g. <span name='btn'> } optional ButtonTitleType type = 2; }
diff --git a/components/autofill/core/common/button_title_type.h b/components/autofill/core/common/button_title_type.h index 7fd97142..bf3696d 100644 --- a/components/autofill/core/common/button_title_type.h +++ b/components/autofill/core/common/button_title_type.h
@@ -15,7 +15,10 @@ BUTTON_ELEMENT_SUBMIT_TYPE = 1, // <button type='submit'> BUTTON_ELEMENT_BUTTON_TYPE = 2, // <button type='button'> INPUT_ELEMENT_SUBMIT_TYPE = 3, // <input type='submit'> - INPUT_ELEMENT_BUTTON_TYPE = 4 // <input type='button'> + INPUT_ELEMENT_BUTTON_TYPE = 4, // <input type='button'> + HYPERLINK = 5, // e.g. <a class='button'> + DIV = 6, // e.g. <div id='submit'> + SPAN = 7 // e.g. <span name='btn'> }; } // namespace autofill
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java index 95b34c0..d1ca29e 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -35,8 +35,9 @@ static final int BACKGROUND_TASK_COMPONENT_UPDATE = 15; static final int BACKGROUND_TASK_DEPRECATED_EXPLORE_SITES_REFRESH = 16; static final int BACKGROUND_TASK_EXPLORE_SITES_REFRESH = 17; + static final int BACKGROUND_TASK_DOWNLOAD_AUTO_RESUMPTION = 18; // Keep this one at the end and increment appropriately when adding new tasks. - static final int BACKGROUND_TASK_COUNT = 18; + static final int BACKGROUND_TASK_COUNT = 19; static final String KEY_CACHED_UMA = "bts_cached_uma"; @@ -243,6 +244,8 @@ return BACKGROUND_TASK_DOWNLOAD_SERVICE; case TaskIds.DOWNLOAD_CLEANUP_JOB_ID: return BACKGROUND_TASK_DOWNLOAD_CLEANUP; + case TaskIds.DOWNLOAD_AUTO_RESUMPTION_JOB_ID: + return BACKGROUND_TASK_DOWNLOAD_AUTO_RESUMPTION; case TaskIds.WEBVIEW_VARIATIONS_SEED_FETCH_JOB_ID: return BACKGROUND_TASK_WEBVIEW_VARIATIONS; case TaskIds.OFFLINE_PAGES_PREFETCH_NOTIFICATION_JOB_ID:
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java index a885f1c..959377ad 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
@@ -26,6 +26,7 @@ public static final int WEBVIEW_VARIATIONS_SEED_FETCH_JOB_ID = 83; public static final int WEBAPK_UPDATE_JOB_ID = 91; public static final int DOWNLOAD_RESUMPTION_JOB_ID = 55; + public static final int DOWNLOAD_AUTO_RESUMPTION_JOB_ID = 56; public static final int FEED_REFRESH_JOB_ID = 22; public static final int COMPONENT_UPDATE_JOB_ID = 2; public static final int DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID = 100;
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java index 8a9dc167..905c63d 100644 --- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java +++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -71,6 +71,9 @@ assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DOWNLOAD_CLEANUP, BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId( TaskIds.DOWNLOAD_CLEANUP_JOB_ID)); + assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DOWNLOAD_AUTO_RESUMPTION, + BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId( + TaskIds.DOWNLOAD_AUTO_RESUMPTION_JOB_ID)); assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_WEBVIEW_VARIATIONS, BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId( TaskIds.WEBVIEW_VARIATIONS_SEED_FETCH_JOB_ID)); @@ -93,7 +96,7 @@ assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DEPRECATED_EXPLORE_SITES_REFRESH, BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId( TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID)); - assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 18); + assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 19); } @Test
diff --git a/components/cronet/native/cronet.idl b/components/cronet/native/cronet.idl index 4186fa1..77b1eed3 100644 --- a/components/cronet/native/cronet.idl +++ b/components/cronet/native/cronet.idl
@@ -1131,8 +1131,12 @@ }; /** + * This value indicates an invalid time. + */ +const int64 kInvalidTime = -1; + +/** * Information about a finished request. - * TODO(mef): Define this to include metrics. */ struct RequestFinishedInfo { /** @@ -1152,4 +1156,158 @@ */ CANCELED = 2, }; + + // TODO(caraitto): Move metrics fields to their own class once C generator + // supports struct within a struct. + + /* + * The below fields represent metrics collected for a single request. Most of + * these metrics are timestamps for events during the lifetime of the request, + * which can be used to build a detailed timeline for investigating + * performance. + * + * Events happen in this order: + * <ol> + * <li>{@link #request_start request start}</li> + * <li>{@link #dns_start DNS start}</li> + * <li>{@link #dns_end DNS end}</li> + * <li>{@link #connect_start connect start}</li> + * <li>{@link #ssl_start SSL start}</li> + * <li>{@link #ssl_end SSL end}</li> + * <li>{@link #connect_end connect end}</li> + * <li>{@link #sending_start sending start}</li> + * <li>{@link #sending_end sending end}</li> + * <li>{@link #response_start response start}</li> + * <li>{@link #request_end request end}</li> + * </ol> + * + * Start times are reported as the time when a request started blocking on + * the event, not when the event actually occurred, with the exception of + * push start and end. If a metric is not meaningful or not available, + * including cases when a request finished before reaching that stage, start + * and end times will be kInvalidTime. If no time was spent blocking on an + * event, start and end will be the same time. + * + * Timestamps are recorded using a clock that is guaranteed not to run + * backwards. All timestamps are correct relative to the system clock at the + * time of request start, and taking the difference between two timestamps + * will give the correct difference between the events. In order to preserve + * this property, timestamps for events other than request start are not + * guaranteed to match the system clock at the times they represent. + * + * Most timing metrics are taken from + * <a + * href="https://cs.chromium.org/chromium/src/net/base/load_timing_info.h">LoadTimingInfo</a>, + * which holds the information for <a href="http://w3c.github.io/navigation-timing/"></a> and + * <a href="https://www.w3.org/TR/resource-timing/"></a>. + * + * All time fields are expressed as the number of milleseconds since the UNIX + * epoch, or kInvalidTime. + */ + + /** + * Time when the request started, which corresponds to calling + * Cronet_UrlRequest_Start(). This timestamp will match the system clock at + * the time it represents. + */ + int64 request_start = kInvalidTime; + + /** + * Time when DNS lookup started. This and {@link #dns_end} will be set to + * non-kInvalidTime regardless of whether the result came from a DNS server + * or the local cache. Will equal kInvalidTime if the socket was reused (see + * {@link #socket_reused}). + */ + int64 dns_start = kInvalidTime; + + /** + * Time when DNS lookup finished. This and {@link dns_start} will return + * non-kInvalidTime regardless of whether the result came from a DNS server + * or the local cache. Will equal kInvalidTime if the socket was reused (see + * {@link #socket_reused}). + */ + int64 dns_end = kInvalidTime; + + /** + * Time when connection establishment started, typically when DNS resolution + * finishes. Will equal kInvalidTime if the socket was reused (see {@link + * #socket_reused}). + */ + int64 connect_start = kInvalidTime; + + /** + * Time when connection establishment finished, after TCP connection is + * established and, if using HTTPS, SSL handshake is completed. For QUIC + * 0-RTT, this represents the time of handshake confirmation and might happen + * later than {@link #sending_start}. Will equal kInvalidTime if the socket + * was reused (see {@link #socket_reused}). + */ + int64 connect_end = kInvalidTime; + + /** + * Time when SSL handshake started. For QUIC, this will be the same time as + * {@link #connect_start}. Will equal kInvalidTime if SSL is not used or if + * the socket was reused (see {@link #socket_reused}). + */ + int64 ssl_start = kInvalidTime; + + /** + * Time when SSL handshake finished. For QUIC, this will be the same time as + * {@link #connect_end}. Will equal kInvalidTime if SSL is not used or if the + * socket was reused (see {@link #socket_reused}). + */ + int64 ssl_end = kInvalidTime; + + /** + * Time when sending HTTP request headers started. + */ + int64 sending_start = kInvalidTime; + + /** + * Time when sending HTTP request body finished. (Sending request body + * happens after sending request headers.) + */ + int64 sending_end = kInvalidTime; + + /** + * Time when first byte of HTTP/2 server push was received. Will equal + * kInvalidTime if server push is not used. + */ + int64 push_start = kInvalidTime; + + /** + * Time when last byte of HTTP/2 server push was received. Will equal + * kInvalidTime if server push is not used. + */ + int64 push_end = kInvalidTime; + + /** + * Time when the end of the response headers was received. + */ + int64 response_start = kInvalidTime; + + /** + * Time when the request finished. + */ + int64 request_end = kInvalidTime; + + /** + * True if the socket was reused from a previous request, false otherwise. + * In HTTP/2 or QUIC, if streams are multiplexed in a single connection, + * this will be {@code true} for all streams after the first. When {@code + * true}, DNS, connection, and SSL times will be kInvalidTime. + */ + bool socket_reused = false; + + /** + * Returns total bytes sent over the network transport layer, or -1 if not + * collected. + */ + int64 sent_byte_count = -1; + + /** + * Total bytes received over the network transport layer, or -1 if not + * collected. Number of bytes does not include any previous redirects. + */ + int64 received_byte_count = -1; };
diff --git a/components/cronet/native/generated/cronet.idl_c.h b/components/cronet/native/generated/cronet.idl_c.h index b67abff4..07bf485e 100644 --- a/components/cronet/native/generated/cronet.idl_c.h +++ b/components/cronet/native/generated/cronet.idl_c.h
@@ -148,6 +148,9 @@ Cronet_UrlRequestStatusListener_Status_READING_RESPONSE = 14, } Cronet_UrlRequestStatusListener_Status; +// Declare constants +const int64_t Cronet_kInvalidTime = -1; + /////////////////////// // Concrete interface Cronet_Buffer. @@ -970,7 +973,116 @@ CRONET_EXPORT void Cronet_RequestFinishedInfo_Destroy( Cronet_RequestFinishedInfoPtr self); // Cronet_RequestFinishedInfo setters. +CRONET_EXPORT +void Cronet_RequestFinishedInfo_request_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t request_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_dns_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t dns_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_dns_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t dns_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_connect_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t connect_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_connect_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t connect_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_ssl_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t ssl_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_ssl_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t ssl_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_sending_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sending_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_sending_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sending_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_push_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t push_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_push_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t push_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_response_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t response_start); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_request_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t request_end); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_socket_reused_set( + Cronet_RequestFinishedInfoPtr self, + bool socket_reused); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_sent_byte_count_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sent_byte_count); +CRONET_EXPORT +void Cronet_RequestFinishedInfo_received_byte_count_set( + Cronet_RequestFinishedInfoPtr self, + int64_t received_byte_count); // Cronet_RequestFinishedInfo getters. +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_request_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_dns_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_dns_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_connect_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_connect_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_ssl_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_ssl_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_sending_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_sending_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_push_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_push_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_response_start_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_request_end_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +bool Cronet_RequestFinishedInfo_socket_reused_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_sent_byte_count_get( + Cronet_RequestFinishedInfoPtr self); +CRONET_EXPORT +int64_t Cronet_RequestFinishedInfo_received_byte_count_get( + Cronet_RequestFinishedInfoPtr self); #ifdef __cplusplus }
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct.cc b/components/cronet/native/generated/cronet.idl_impl_struct.cc index ae1cbb8..6ab68f7 100644 --- a/components/cronet/native/generated/cronet.idl_impl_struct.cc +++ b/components/cronet/native/generated/cronet.idl_impl_struct.cc
@@ -775,5 +775,208 @@ } // Struct Cronet_RequestFinishedInfo setters. +void Cronet_RequestFinishedInfo_request_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t request_start) { + DCHECK(self); + self->request_start = request_start; +} + +void Cronet_RequestFinishedInfo_dns_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t dns_start) { + DCHECK(self); + self->dns_start = dns_start; +} + +void Cronet_RequestFinishedInfo_dns_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t dns_end) { + DCHECK(self); + self->dns_end = dns_end; +} + +void Cronet_RequestFinishedInfo_connect_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t connect_start) { + DCHECK(self); + self->connect_start = connect_start; +} + +void Cronet_RequestFinishedInfo_connect_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t connect_end) { + DCHECK(self); + self->connect_end = connect_end; +} + +void Cronet_RequestFinishedInfo_ssl_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t ssl_start) { + DCHECK(self); + self->ssl_start = ssl_start; +} + +void Cronet_RequestFinishedInfo_ssl_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t ssl_end) { + DCHECK(self); + self->ssl_end = ssl_end; +} + +void Cronet_RequestFinishedInfo_sending_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sending_start) { + DCHECK(self); + self->sending_start = sending_start; +} + +void Cronet_RequestFinishedInfo_sending_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sending_end) { + DCHECK(self); + self->sending_end = sending_end; +} + +void Cronet_RequestFinishedInfo_push_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t push_start) { + DCHECK(self); + self->push_start = push_start; +} + +void Cronet_RequestFinishedInfo_push_end_set(Cronet_RequestFinishedInfoPtr self, + int64_t push_end) { + DCHECK(self); + self->push_end = push_end; +} + +void Cronet_RequestFinishedInfo_response_start_set( + Cronet_RequestFinishedInfoPtr self, + int64_t response_start) { + DCHECK(self); + self->response_start = response_start; +} + +void Cronet_RequestFinishedInfo_request_end_set( + Cronet_RequestFinishedInfoPtr self, + int64_t request_end) { + DCHECK(self); + self->request_end = request_end; +} + +void Cronet_RequestFinishedInfo_socket_reused_set( + Cronet_RequestFinishedInfoPtr self, + bool socket_reused) { + DCHECK(self); + self->socket_reused = socket_reused; +} + +void Cronet_RequestFinishedInfo_sent_byte_count_set( + Cronet_RequestFinishedInfoPtr self, + int64_t sent_byte_count) { + DCHECK(self); + self->sent_byte_count = sent_byte_count; +} + +void Cronet_RequestFinishedInfo_received_byte_count_set( + Cronet_RequestFinishedInfoPtr self, + int64_t received_byte_count) { + DCHECK(self); + self->received_byte_count = received_byte_count; +} // Struct Cronet_RequestFinishedInfo getters. +int64_t Cronet_RequestFinishedInfo_request_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->request_start; +} + +int64_t Cronet_RequestFinishedInfo_dns_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->dns_start; +} + +int64_t Cronet_RequestFinishedInfo_dns_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->dns_end; +} + +int64_t Cronet_RequestFinishedInfo_connect_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->connect_start; +} + +int64_t Cronet_RequestFinishedInfo_connect_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->connect_end; +} + +int64_t Cronet_RequestFinishedInfo_ssl_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->ssl_start; +} + +int64_t Cronet_RequestFinishedInfo_ssl_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->ssl_end; +} + +int64_t Cronet_RequestFinishedInfo_sending_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->sending_start; +} + +int64_t Cronet_RequestFinishedInfo_sending_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->sending_end; +} + +int64_t Cronet_RequestFinishedInfo_push_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->push_start; +} + +int64_t Cronet_RequestFinishedInfo_push_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->push_end; +} + +int64_t Cronet_RequestFinishedInfo_response_start_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->response_start; +} + +int64_t Cronet_RequestFinishedInfo_request_end_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->request_end; +} + +bool Cronet_RequestFinishedInfo_socket_reused_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->socket_reused; +} + +int64_t Cronet_RequestFinishedInfo_sent_byte_count_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->sent_byte_count; +} + +int64_t Cronet_RequestFinishedInfo_received_byte_count_get( + Cronet_RequestFinishedInfoPtr self) { + DCHECK(self); + return self->received_byte_count; +}
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct.h b/components/cronet/native/generated/cronet.idl_impl_struct.h index 0a47ffe..298f8071 100644 --- a/components/cronet/native/generated/cronet.idl_impl_struct.h +++ b/components/cronet/native/generated/cronet.idl_impl_struct.h
@@ -161,6 +161,23 @@ explicit Cronet_RequestFinishedInfo(Cronet_RequestFinishedInfo&& from); ~Cronet_RequestFinishedInfo(); + int64_t request_start = Cronet_kInvalidTime; + int64_t dns_start = Cronet_kInvalidTime; + int64_t dns_end = Cronet_kInvalidTime; + int64_t connect_start = Cronet_kInvalidTime; + int64_t connect_end = Cronet_kInvalidTime; + int64_t ssl_start = Cronet_kInvalidTime; + int64_t ssl_end = Cronet_kInvalidTime; + int64_t sending_start = Cronet_kInvalidTime; + int64_t sending_end = Cronet_kInvalidTime; + int64_t push_start = Cronet_kInvalidTime; + int64_t push_end = Cronet_kInvalidTime; + int64_t response_start = Cronet_kInvalidTime; + int64_t request_end = Cronet_kInvalidTime; + bool socket_reused = false; + int64_t sent_byte_count = -1; + int64_t received_byte_count = -1; + private: DISALLOW_ASSIGN(Cronet_RequestFinishedInfo); };
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc index 6a3b243..ba6106a 100644 --- a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc +++ b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc
@@ -259,6 +259,70 @@ Cronet_RequestFinishedInfoPtr second = Cronet_RequestFinishedInfo_Create(); // Copy values from |first| to |second|. + Cronet_RequestFinishedInfo_request_start_set( + second, Cronet_RequestFinishedInfo_request_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_request_start_get(first), + Cronet_RequestFinishedInfo_request_start_get(second)); + Cronet_RequestFinishedInfo_dns_start_set( + second, Cronet_RequestFinishedInfo_dns_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_dns_start_get(first), + Cronet_RequestFinishedInfo_dns_start_get(second)); + Cronet_RequestFinishedInfo_dns_end_set( + second, Cronet_RequestFinishedInfo_dns_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_dns_end_get(first), + Cronet_RequestFinishedInfo_dns_end_get(second)); + Cronet_RequestFinishedInfo_connect_start_set( + second, Cronet_RequestFinishedInfo_connect_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_connect_start_get(first), + Cronet_RequestFinishedInfo_connect_start_get(second)); + Cronet_RequestFinishedInfo_connect_end_set( + second, Cronet_RequestFinishedInfo_connect_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_connect_end_get(first), + Cronet_RequestFinishedInfo_connect_end_get(second)); + Cronet_RequestFinishedInfo_ssl_start_set( + second, Cronet_RequestFinishedInfo_ssl_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_ssl_start_get(first), + Cronet_RequestFinishedInfo_ssl_start_get(second)); + Cronet_RequestFinishedInfo_ssl_end_set( + second, Cronet_RequestFinishedInfo_ssl_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_ssl_end_get(first), + Cronet_RequestFinishedInfo_ssl_end_get(second)); + Cronet_RequestFinishedInfo_sending_start_set( + second, Cronet_RequestFinishedInfo_sending_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_sending_start_get(first), + Cronet_RequestFinishedInfo_sending_start_get(second)); + Cronet_RequestFinishedInfo_sending_end_set( + second, Cronet_RequestFinishedInfo_sending_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_sending_end_get(first), + Cronet_RequestFinishedInfo_sending_end_get(second)); + Cronet_RequestFinishedInfo_push_start_set( + second, Cronet_RequestFinishedInfo_push_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_push_start_get(first), + Cronet_RequestFinishedInfo_push_start_get(second)); + Cronet_RequestFinishedInfo_push_end_set( + second, Cronet_RequestFinishedInfo_push_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_push_end_get(first), + Cronet_RequestFinishedInfo_push_end_get(second)); + Cronet_RequestFinishedInfo_response_start_set( + second, Cronet_RequestFinishedInfo_response_start_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_response_start_get(first), + Cronet_RequestFinishedInfo_response_start_get(second)); + Cronet_RequestFinishedInfo_request_end_set( + second, Cronet_RequestFinishedInfo_request_end_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_request_end_get(first), + Cronet_RequestFinishedInfo_request_end_get(second)); + Cronet_RequestFinishedInfo_socket_reused_set( + second, Cronet_RequestFinishedInfo_socket_reused_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_socket_reused_get(first), + Cronet_RequestFinishedInfo_socket_reused_get(second)); + Cronet_RequestFinishedInfo_sent_byte_count_set( + second, Cronet_RequestFinishedInfo_sent_byte_count_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_sent_byte_count_get(first), + Cronet_RequestFinishedInfo_sent_byte_count_get(second)); + Cronet_RequestFinishedInfo_received_byte_count_set( + second, Cronet_RequestFinishedInfo_received_byte_count_get(first)); + EXPECT_EQ(Cronet_RequestFinishedInfo_received_byte_count_get(first), + Cronet_RequestFinishedInfo_received_byte_count_get(second)); Cronet_RequestFinishedInfo_Destroy(first); Cronet_RequestFinishedInfo_Destroy(second); }
diff --git a/components/cronet/tools/generators/c_templates/module_c.h.tmpl b/components/cronet/tools/generators/c_templates/module_c.h.tmpl index ef38db1..d7e87df0 100644 --- a/components/cronet/tools/generators/c_templates/module_c.h.tmpl +++ b/components/cronet/tools/generators/c_templates/module_c.h.tmpl
@@ -62,6 +62,11 @@ {% endfor %} +// Declare constants +{%- for constant in module.constants %} +{{constant|format_constant_declaration}}; +{%- endfor %} + {#--- Interface Stubs -#} {% for interface in interfaces %} {%- set interface_name = interface|get_name_for_kind %}
diff --git a/components/cronet/tools/generators/cronet_c_generator.py b/components/cronet/tools/generators/cronet_c_generator.py index 721539b..01b827a 100644 --- a/components/cronet/tools/generators/cronet_c_generator.py +++ b/components/cronet/tools/generators/cronet_c_generator.py
@@ -537,8 +537,8 @@ return "%sextern const char %s[]" % \ ((self.export_attribute + " ") if self.export_attribute else "", constant.name) - return "constexpr %s %s = %s" % ( - GetCppPodType(constant.kind), constant.name, + return "const %s %s_%s = %s" % ( + GetCppPodType(constant.kind), self.module.namespace, constant.name, self._ConstantValue(constant)) def _GetCppWrapperType(self, kind, add_same_module_namespaces=False):
diff --git a/components/download/internal/background_service/controller_impl.cc b/components/download/internal/background_service/controller_impl.cc index 717d390..eae2dc6 100644 --- a/components/download/internal/background_service/controller_impl.cc +++ b/components/download/internal/background_service/controller_impl.cc
@@ -401,6 +401,8 @@ case DownloadTaskType::CLEANUP_TASK: ScheduleCleanupTask(); break; + case DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK: + NOTREACHED(); } }
diff --git a/components/download/internal/background_service/stats.cc b/components/download/internal/background_service/stats.cc index ef8cf015..88aebf4a 100644 --- a/components/download/internal/background_service/stats.cc +++ b/components/download/internal/background_service/stats.cc
@@ -48,6 +48,8 @@ return "DownloadTask"; case DownloadTaskType::CLEANUP_TASK: return "CleanUpTask"; + case DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK: + return "DownloadAutoResumptionTask"; } NOTREACHED(); return std::string();
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc index a39e308..4b536f5 100644 --- a/components/download/internal/common/download_item_impl.cc +++ b/components/download/internal/common/download_item_impl.cc
@@ -588,10 +588,12 @@ } void DownloadItemImpl::UpdateResumptionInfo(bool user_resume) { - if (user_resume) + if (user_resume) { allow_metered_ |= delegate_->IsActiveNetworkMetered(); + bytes_wasted_ = 0; + } - auto_resume_count_ = user_resume ? 0 : auto_resume_count_++; + auto_resume_count_ = user_resume ? 0 : ++auto_resume_count_; } void DownloadItemImpl::Cancel(bool user_cancel) {
diff --git a/components/download/internal/common/download_item_impl_delegate.cc b/components/download/internal/common/download_item_impl_delegate.cc index 973248a..cc3fb6af5d 100644 --- a/components/download/internal/common/download_item_impl_delegate.cc +++ b/components/download/internal/common/download_item_impl_delegate.cc
@@ -5,7 +5,9 @@ #include "components/download/public/common/download_item_impl_delegate.h" #include "base/logging.h" +#include "build/build_config.h" #include "components/download/database/in_progress/download_entry.h" +#include "components/download/public/common/auto_resumption_handler.h" #include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_item_impl.h" @@ -94,7 +96,9 @@ } bool DownloadItemImplDelegate::IsActiveNetworkMetered() const { - return false; + return download::AutoResumptionHandler::Get() + ? download::AutoResumptionHandler::Get()->IsActiveNetworkMetered() + : false; } void DownloadItemImplDelegate::ReportBytesWasted(DownloadItemImpl* download) {}
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc index 276d856..abecb58 100644 --- a/components/download/internal/common/in_progress_download_manager.cc +++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -409,6 +409,12 @@ on_initialized_callbacks_.clear(); } +void InProgressDownloadManager::GetAllDownloads( + std::vector<download::DownloadItem*>* downloads) const { + for (auto& item : in_progress_downloads_) + downloads->push_back(item.get()); +} + DownloadItemImpl* InProgressDownloadManager::GetInProgressDownload( const std::string& guid) { for (auto& item : in_progress_downloads_) {
diff --git a/components/download/public/background_service/download_task_types.h b/components/download/public/background_service/download_task_types.h index 48fcfb35..5140f520 100644 --- a/components/download/public/background_service/download_task_types.h +++ b/components/download/public/background_service/download_task_types.h
@@ -15,6 +15,9 @@ // Task to remove unnecessary files from the system. CLEANUP_TASK = 1, + + // Task to invoke the download auto-resumption handler. + DOWNLOAD_AUTO_RESUMPTION_TASK = 2, }; } // namespace download
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn index 8de5574..e14fe35 100644 --- a/components/download/public/common/BUILD.gn +++ b/components/download/public/common/BUILD.gn
@@ -15,6 +15,8 @@ component("public") { sources = [ + "auto_resumption_handler.cc", + "auto_resumption_handler.h", "base_file.h", "download_content.h", "download_create_info.h", @@ -65,6 +67,9 @@ public_deps = [ ":interfaces", + "//components/download/network", + "//components/download/public/background_service:public", + "//services/network/public/cpp", ] deps = [
diff --git a/components/download/public/common/auto_resumption_handler.cc b/components/download/public/common/auto_resumption_handler.cc new file mode 100644 index 0000000..3e6dfa5 --- /dev/null +++ b/components/download/public/common/auto_resumption_handler.cc
@@ -0,0 +1,295 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/download/public/common/auto_resumption_handler.h" + +#include <vector> + +#include "base/feature_list.h" +#include "base/metrics/field_trial_params.h" +#include "base/strings/string_number_conversions.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/download/public/background_service/task_scheduler.h" +#include "url/gurl.h" + +namespace { + +static download::AutoResumptionHandler* g_auto_resumption_handler = nullptr; + +// The delay to wait for after a chrome restart before resuming all pending +// downloads so that tab loading doesn't get impacted. +const base::TimeDelta kAutoResumeStartupDelay = + base::TimeDelta::FromSeconds(10); + +// The interval at which various download updates are grouped together for +// computing the params for the task scheduler. +const base::TimeDelta kBatchDownloadUpdatesInterval = + base::TimeDelta::FromSeconds(1); + +// The delay to wait for before immediately retrying a download after it got +// interrupted due to network reasons. +const base::TimeDelta kDownloadImmediateRetryDelay = + base::TimeDelta::FromSeconds(1); + +// The task type to use for scheduling a task. +const download::DownloadTaskType kResumptionTaskType = + download::DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK; + +// The window start time after which the system should fire the task. +const int64_t kWindowStartTimeSeconds = 0; + +// The window end time before which the system should fire the task. +const int64_t kWindowEndTimeSeconds = 24 * 60 * 60; + +bool IsMetered(network::mojom::ConnectionType type) { + switch (type) { + case network::mojom::ConnectionType::CONNECTION_2G: + case network::mojom::ConnectionType::CONNECTION_3G: + case network::mojom::ConnectionType::CONNECTION_4G: + return true; + case network::mojom::ConnectionType::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_NONE: + case network::mojom::ConnectionType::CONNECTION_BLUETOOTH: + return false; + } + NOTREACHED(); + return false; +} + +bool IsConnected(network::mojom::ConnectionType type) { + switch (type) { + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_NONE: + case network::mojom::ConnectionType::CONNECTION_BLUETOOTH: + return false; + default: + return true; + } +} + +bool IsInterruptedDownloadAutoResumable(download::DownloadItem* download_item, + int auto_resumption_size_limit) { + if (!download_item->GetURL().SchemeIsHTTPOrHTTPS()) + return false; + + if (download_item->GetBytesWasted() > auto_resumption_size_limit) + return false; + + int interrupt_reason = download_item->GetLastReason(); + DCHECK_NE(interrupt_reason, download::DOWNLOAD_INTERRUPT_REASON_NONE); + return interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT || + interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED || + interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED || + interrupt_reason == download::DOWNLOAD_INTERRUPT_REASON_CRASH; +} + +} // namespace + +namespace download { + +AutoResumptionHandler::Config::Config() : auto_resumption_size_limit(0) {} + +// static +void AutoResumptionHandler::Create( + std::unique_ptr<download::NetworkStatusListener> network_listener, + std::unique_ptr<download::TaskManager> task_manager, + std::unique_ptr<Config> config) { + DCHECK(!g_auto_resumption_handler); + g_auto_resumption_handler = new AutoResumptionHandler( + std::move(network_listener), std::move(task_manager), std::move(config)); +} + +// static +AutoResumptionHandler* AutoResumptionHandler::Get() { + return g_auto_resumption_handler; +} + +AutoResumptionHandler::AutoResumptionHandler( + std::unique_ptr<download::NetworkStatusListener> network_listener, + std::unique_ptr<download::TaskManager> task_manager, + std::unique_ptr<Config> config) + : network_listener_(std::move(network_listener)), + task_manager_(std::move(task_manager)), + config_(std::move(config)), + weak_factory_(this) { + network_listener_->Start(this); +} + +AutoResumptionHandler::~AutoResumptionHandler() { + network_listener_->Stop(); +} + +void AutoResumptionHandler::SetResumableDownloads( + const std::vector<download::DownloadItem*>& downloads) { + resumable_downloads_.clear(); + for (auto* download : downloads) { + if (!IsAutoResumableDownload(download)) + continue; + resumable_downloads_.insert(std::make_pair(download->GetGuid(), download)); + download->RemoveObserver(this); + download->AddObserver(this); + } + + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AutoResumptionHandler::ResumePendingDownloads, + weak_factory_.GetWeakPtr()), + kAutoResumeStartupDelay); +} + +bool AutoResumptionHandler::IsActiveNetworkMetered() const { + return IsMetered(network_listener_->GetConnectionType()); +} + +void AutoResumptionHandler::OnNetworkChanged( + network::mojom::ConnectionType type) { + if (!IsConnected(type)) + return; + + ResumePendingDownloads(); +} + +void AutoResumptionHandler::OnDownloadStarted(download::DownloadItem* item) { + item->RemoveObserver(this); + item->AddObserver(this); + + OnDownloadUpdated(item); +} + +void AutoResumptionHandler::OnDownloadUpdated(download::DownloadItem* item) { + if (IsAutoResumableDownload(item)) + resumable_downloads_[item->GetGuid()] = item; + else + resumable_downloads_.erase(item->GetGuid()); + + if (item->GetState() == download::DownloadItem::INTERRUPTED && + IsAutoResumableDownload(item) && SatisfiesNetworkRequirements(item)) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AutoResumptionHandler::ResumeDownload, + weak_factory_.GetWeakPtr(), item), + kDownloadImmediateRetryDelay); + return; + } + RecomputeTaskParams(); +} + +void AutoResumptionHandler::OnDownloadRemoved(download::DownloadItem* item) { + resumable_downloads_.erase(item->GetGuid()); + RecomputeTaskParams(); +} + +void AutoResumptionHandler::ResumeDownload(download::DownloadItem* download) { + if (SatisfiesNetworkRequirements(download)) + download->Resume(false); + else + RecomputeTaskParams(); +} + +void AutoResumptionHandler::OnStartScheduledTask( + download::TaskFinishedCallback callback) { + task_manager_->OnStartScheduledTask(kResumptionTaskType, std::move(callback)); + ResumePendingDownloads(); +} + +bool AutoResumptionHandler::OnStopScheduledTask() { + task_manager_->OnStopScheduledTask(kResumptionTaskType); + RescheduleTaskIfNecessary(); + return false; +} + +void AutoResumptionHandler::RecomputeTaskParams() { + if (recompute_task_params_scheduled_) + return; + + recompute_task_params_scheduled_ = true; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AutoResumptionHandler::RescheduleTaskIfNecessary, + weak_factory_.GetWeakPtr()), + kBatchDownloadUpdatesInterval); +} + +void AutoResumptionHandler::RescheduleTaskIfNecessary() { + recompute_task_params_scheduled_ = false; + + bool has_resumable_downloads = false; + bool has_actionable_downloads = false; + bool can_download_on_metered = false; + for (auto iter = resumable_downloads_.begin(); + iter != resumable_downloads_.end(); ++iter) { + download::DownloadItem* download = iter->second; + if (!IsAutoResumableDownload(download)) + continue; + + has_resumable_downloads = true; + has_actionable_downloads |= SatisfiesNetworkRequirements(download); + can_download_on_metered |= download->AllowMetered(); + if (can_download_on_metered) + break; + } + + if (!has_actionable_downloads) + task_manager_->NotifyTaskFinished(kResumptionTaskType, false); + + if (!has_resumable_downloads) { + task_manager_->UnscheduleTask(kResumptionTaskType); + return; + } + + download::TaskManager::TaskParams task_params; + task_params.require_unmetered_network = !can_download_on_metered; + task_params.window_start_time_seconds = kWindowStartTimeSeconds; + task_params.window_end_time_seconds = kWindowEndTimeSeconds; + task_manager_->ScheduleTask(kResumptionTaskType, task_params); +} + +void AutoResumptionHandler::ResumePendingDownloads() { + for (auto iter = resumable_downloads_.begin(); + iter != resumable_downloads_.end(); ++iter) { + download::DownloadItem* download = iter->second; + if (!IsAutoResumableDownload(download)) + continue; + + if (SatisfiesNetworkRequirements(download)) + download->Resume(false); + } +} + +bool AutoResumptionHandler::SatisfiesNetworkRequirements( + download::DownloadItem* download) { + if (!IsConnected(network_listener_->GetConnectionType())) + return false; + + return download->AllowMetered() || !IsActiveNetworkMetered(); +} + +bool AutoResumptionHandler::IsAutoResumableDownload( + download::DownloadItem* item) { + if (item->IsDangerous()) + return false; + + switch (item->GetState()) { + case download::DownloadItem::IN_PROGRESS: + return !item->IsPaused(); + case download::DownloadItem::COMPLETE: + case download::DownloadItem::CANCELLED: + return false; + case download::DownloadItem::INTERRUPTED: + return !item->IsPaused() && + IsInterruptedDownloadAutoResumable( + item, config_->auto_resumption_size_limit); + case download::DownloadItem::MAX_DOWNLOAD_STATE: + NOTREACHED(); + } + + return false; +} + +} // namespace download
diff --git a/components/download/public/common/auto_resumption_handler.h b/components/download/public/common/auto_resumption_handler.h new file mode 100644 index 0000000..c0bb504 --- /dev/null +++ b/components/download/public/common/auto_resumption_handler.h
@@ -0,0 +1,90 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_AUTO_RESUMPTION_HANDLER_H_ +#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_AUTO_RESUMPTION_HANDLER_H_ + +#include <stddef.h> + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/download/network/network_status_listener.h" +#include "components/download/public/background_service/task_manager.h" +#include "components/download/public/common/download_export.h" +#include "components/download/public/common/download_item.h" + +namespace download { + +// Handles auto-resumptions for downloads. Listens to network changes and +// schecules task to resume downloads accordingly. +class COMPONENTS_DOWNLOAD_EXPORT AutoResumptionHandler + : public download::NetworkStatusListener::Observer, + public download::DownloadItem::Observer { + public: + struct COMPONENTS_DOWNLOAD_EXPORT Config { + Config(); + ~Config() = default; + + int auto_resumption_size_limit; + }; + + // Creates the singleton instance of AutoResumptionHandler. + static void Create( + std::unique_ptr<download::NetworkStatusListener> network_listener, + std::unique_ptr<download::TaskManager> task_manager, + std::unique_ptr<Config> config); + + // Returns the singleton instance of the AutoResumptionHandler. + static AutoResumptionHandler* Get(); + + AutoResumptionHandler( + std::unique_ptr<download::NetworkStatusListener> network_listener, + std::unique_ptr<download::TaskManager> task_manager, + std::unique_ptr<Config> config); + ~AutoResumptionHandler() override; + + void SetResumableDownloads( + const std::vector<download::DownloadItem*>& downloads); + bool IsActiveNetworkMetered() const; + void OnStartScheduledTask(download::TaskFinishedCallback callback); + bool OnStopScheduledTask(); + + void OnDownloadStarted(download::DownloadItem* item); + + // DownloadItem::Observer overrides. + void OnDownloadUpdated(download::DownloadItem* item) override; + void OnDownloadRemoved(download::DownloadItem* item) override; + + private: + // NetworkStatusListener::Observer implementation. + void OnNetworkChanged(network::mojom::ConnectionType type) override; + + void ResumePendingDownloads(); + void RecomputeTaskParams(); + void RescheduleTaskIfNecessary(); + void ResumeDownload(download::DownloadItem* download); + bool SatisfiesNetworkRequirements(download::DownloadItem* download); + bool IsAutoResumableDownload(download::DownloadItem* item); + + std::unique_ptr<download::NetworkStatusListener> network_listener_; + + std::unique_ptr<download::TaskManager> task_manager_; + + std::unique_ptr<Config> config_; + + std::map<std::string, download::DownloadItem*> resumable_downloads_; + + bool recompute_task_params_scheduled_ = false; + + base::WeakPtrFactory<AutoResumptionHandler> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AutoResumptionHandler); +}; + +} // namespace download + +#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_AUTO_RESUMPTION_HANDLER_H_
diff --git a/components/download/public/common/in_progress_download_manager.h b/components/download/public/common/in_progress_download_manager.h index d76534f..563d97d 100644 --- a/components/download/public/common/in_progress_download_manager.h +++ b/components/download/public/common/in_progress_download_manager.h
@@ -122,6 +122,9 @@ // Called to remove an in-progress download. void RemoveInProgressDownload(const std::string& guid); + // Called to get all in-progress downloads. + void GetAllDownloads(std::vector<download::DownloadItem*>* downloads) const; + // Called to retrieve an in-progress download. DownloadItemImpl* GetInProgressDownload(const std::string& guid);
diff --git a/components/leveldb_proto/shared_proto_database.cc b/components/leveldb_proto/shared_proto_database.cc index d306534..6f349388 100644 --- a/components/leveldb_proto/shared_proto_database.cc +++ b/components/leveldb_proto/shared_proto_database.cc
@@ -30,7 +30,8 @@ db_dir_(db_dir), db_wrapper_(std::make_unique<ProtoLevelDBWrapper>(task_runner_)), db_(std::make_unique<LevelDB>(client_name.c_str())), - weak_factory_(this) { + weak_factory_( + std::make_unique<base::WeakPtrFactory<SharedProtoDatabase>>(this)) { DETACH_FROM_SEQUENCE(on_task_runner_); } @@ -45,7 +46,7 @@ task_runner_->PostTaskAndReply( FROM_HERE, base::DoNothing(), base::BindOnce(&SharedProtoDatabase::RunInitCallback, - weak_factory_.GetWeakPtr(), std::move(callback))); + weak_factory_->GetWeakPtr(), std::move(callback))); } void SharedProtoDatabase::RunInitCallback( @@ -89,7 +90,7 @@ db_wrapper_->InitWithDatabase( db_.get(), db_dir_, options, false /* destroy_on_corruption */, base::BindOnce(&SharedProtoDatabase::OnDatabaseInit, - weak_factory_.GetWeakPtr(), std::move(callback), + weak_factory_->GetWeakPtr(), std::move(callback), std::move(callback_task_runner))); } @@ -117,7 +118,9 @@ base::BindOnce(std::move(callback), status)); } -SharedProtoDatabase::~SharedProtoDatabase() = default; +SharedProtoDatabase::~SharedProtoDatabase() { + task_runner_->DeleteSoon(FROM_HERE, std::move(weak_factory_)); +} LevelDB* SharedProtoDatabase::GetLevelDBForTesting() const { return db_.get();
diff --git a/components/leveldb_proto/shared_proto_database.h b/components/leveldb_proto/shared_proto_database.h index 8ab5f5b..18b8750 100644 --- a/components/leveldb_proto/shared_proto_database.h +++ b/components/leveldb_proto/shared_proto_database.h
@@ -116,7 +116,7 @@ scoped_refptr<base::SequencedTaskRunner>>> outstanding_init_requests_; - base::WeakPtrFactory<SharedProtoDatabase> weak_factory_; + std::unique_ptr<base::WeakPtrFactory<SharedProtoDatabase>> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SharedProtoDatabase); }; @@ -150,7 +150,7 @@ auto current_task_runner = base::SequencedTaskRunnerHandle::Get(); task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::Init, weak_factory_.GetWeakPtr(), + base::BindOnce(&SharedProtoDatabase::Init, weak_factory_->GetWeakPtr(), create_if_missing, base::BindOnce(&GetClientInitCallback<T>, std::move(callback), std::move(client)), @@ -167,7 +167,7 @@ auto current_task_runner = base::SequencedTaskRunnerHandle::Get(); task_runner_->PostTask( FROM_HERE, - base::BindOnce(&SharedProtoDatabase::Init, weak_factory_.GetWeakPtr(), + base::BindOnce(&SharedProtoDatabase::Init, weak_factory_->GetWeakPtr(), create_if_missing, std::move(callback), std::move(current_task_runner))); return GetClientInternal<T>(client_namespace, type_prefix);
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc index 0fd2a63a2..3a88cdca 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
@@ -14,17 +14,11 @@ #include "components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h" #include "components/ntp_snippets/contextual/contextual_suggestions_features.h" #include "components/ntp_snippets/contextual/contextual_suggestions_result.h" -#include "components/ntp_snippets/remote/cached_image_fetcher.h" -#include "components/ntp_snippets/remote/remote_suggestions_database.h" #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h" -#include "ui/gfx/image/image.h" namespace contextual_suggestions { using ntp_snippets::ContentSuggestion; -using ntp_snippets::ImageDataFetchedCallback; -using ntp_snippets::ImageFetchedCallback; -using ntp_snippets::CachedImageFetcher; using ntp_snippets::RemoteSuggestionsDatabase; namespace { @@ -37,15 +31,10 @@ ContextualContentSuggestionsService::ContextualContentSuggestionsService( std::unique_ptr<ContextualSuggestionsFetcher> contextual_suggestions_fetcher, - std::unique_ptr<CachedImageFetcher> image_fetcher, - std::unique_ptr<RemoteSuggestionsDatabase> contextual_suggestions_database, std::unique_ptr<ContextualSuggestionsReporterProvider> reporter_provider) - : contextual_suggestions_database_( - std::move(contextual_suggestions_database)), - fetch_cache_(kFetchCacheCapacity), + : fetch_cache_(kFetchCacheCapacity), contextual_suggestions_fetcher_( std::move(contextual_suggestions_fetcher)), - image_fetcher_(std::move(image_fetcher)), reporter_provider_(std::move(reporter_provider)) {} ContextualContentSuggestionsService::~ContextualContentSuggestionsService() = @@ -70,15 +59,6 @@ } } -void ContextualContentSuggestionsService::FetchContextualSuggestionImage( - const ContentSuggestion::ID& suggestion_id, - const GURL& image_url, - ImageFetchedCallback callback) { - image_fetcher_->FetchSuggestionImage(suggestion_id, image_url, - ImageDataFetchedCallback(), - std::move(callback)); -} - void ContextualContentSuggestionsService::FetchDone( const GURL& url, FetchClustersCallback callback,
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h index d2f4b7a..de7dcde 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
@@ -12,7 +12,6 @@ #include "base/callback.h" #include "base/optional.h" -#include "components/image_fetcher/core/image_fetcher.h" #include "components/keyed_service/core/keyed_service.h" #include "components/ntp_snippets/callbacks.h" #include "components/ntp_snippets/content_suggestion.h" @@ -22,27 +21,18 @@ #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.h" #include "services/metrics/public/cpp/ukm_source_id.h" -namespace ntp_snippets { -class CachedImageFetcher; -class RemoteSuggestionsDatabase; -} // namespace ntp_snippets - namespace contextual_suggestions { static constexpr int kFetchCacheCapacity = 10; class ContextualContentSuggestionsServiceProxy; -// Retrieves contextual suggestions for a given URL and fetches images -// for contextual suggestion, using caching. +// Retrieves contextual suggestions for a given URL using caching. class ContextualContentSuggestionsService : public KeyedService { public: ContextualContentSuggestionsService( std::unique_ptr<ContextualSuggestionsFetcher> contextual_suggestions_fetcher, - std::unique_ptr<ntp_snippets::CachedImageFetcher> image_fetcher, - std::unique_ptr<ntp_snippets::RemoteSuggestionsDatabase> - contextual_suggestions_database, std::unique_ptr< contextual_suggestions::ContextualSuggestionsReporterProvider> reporter_provider); @@ -54,13 +44,6 @@ FetchClustersCallback callback, ReportFetchMetricsCallback metrics_callback); - // Fetches an image pointed to by |url| and internally caches it using - // |suggestion_id|. Asynchronous if cache or network is queried. - virtual void FetchContextualSuggestionImage( - const ntp_snippets::ContentSuggestion::ID& suggestion_id, - const GURL& url, - ntp_snippets::ImageFetchedCallback callback); - void FetchDone(const GURL& url, FetchClustersCallback callback, ReportFetchMetricsCallback metrics_callback, @@ -82,9 +65,6 @@ void BelowConfidenceThresholdFetchDone( FetchClustersCallback callback, ReportFetchMetricsCallback metrics_callback); - // Cache for images of contextual suggestions, needed by CachedImageFetcher. - std::unique_ptr<ntp_snippets::RemoteSuggestionsDatabase> - contextual_suggestions_database_; // Cache of contextual suggestions fetch results, keyed by the context url. ContextualSuggestionsCache fetch_cache_; @@ -92,15 +72,9 @@ // Performs actual network request to fetch contextual suggestions. std::unique_ptr<ContextualSuggestionsFetcher> contextual_suggestions_fetcher_; - std::unique_ptr<ntp_snippets::CachedImageFetcher> image_fetcher_; - std::unique_ptr<contextual_suggestions::ContextualSuggestionsReporterProvider> reporter_provider_; - // Look up by ContentSuggestion::ID::id_within_category() aka std::string to - // get image URL. - std::map<std::string, GURL> image_url_by_id_; - DISALLOW_COPY_AND_ASSIGN(ContextualContentSuggestionsService); };
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc index 2cd0e8d..1329c359 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.cc
@@ -49,36 +49,29 @@ weak_ptr_factory_.GetWeakPtr(), last_ukm_source_id_, url.spec())); } -void ContextualContentSuggestionsServiceProxy::FetchContextualSuggestionImage( - const std::string& suggestion_id, - ntp_snippets::ImageFetchedCallback callback) { +std::string +ContextualContentSuggestionsServiceProxy::GetContextualSuggestionImageUrl( + const std::string& suggestion_id) { auto suggestion_iter = suggestions_.find(suggestion_id); if (suggestion_iter == suggestions_.end()) { DVLOG(1) << "Unkown suggestion ID: " << suggestion_id; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), gfx::Image())); - return; + return ""; } std::string& image_id = suggestion_iter->second.image_id; - GURL image_url = ImageUrlFromId(image_id); - - FetchImageImpl(image_url, image_id, std::move(callback)); + return ImageUrlFromId(image_id).spec(); } -void ContextualContentSuggestionsServiceProxy::FetchContextualSuggestionFavicon( - const std::string& suggestion_id, - ntp_snippets::ImageFetchedCallback callback) { +std::string +ContextualContentSuggestionsServiceProxy::GetContextualSuggestionFaviconUrl( + const std::string& suggestion_id) { auto suggestion_iter = suggestions_.find(suggestion_id); if (suggestion_iter == suggestions_.end()) { DVLOG(1) << "Unkown suggestion ID: " << suggestion_id; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), gfx::Image())); - return; + return ""; } - FetchImageImpl(GURL(suggestion_iter->second.favicon_image_url), - suggestion_iter->second.favicon_image_id, std::move(callback)); + return suggestion_iter->second.favicon_image_url; } void ContextualContentSuggestionsServiceProxy::ClearState() { @@ -115,19 +108,6 @@ last_ukm_source_id_ = ukm::kInvalidSourceId; } -void ContextualContentSuggestionsServiceProxy::FetchImageImpl( - const GURL& image_url, - const std::string& image_id, - ntp_snippets::ImageFetchedCallback callback) { - ntp_snippets::ContentSuggestion::ID synthetic_cache_id( - ntp_snippets::Category::FromKnownCategory( - ntp_snippets::KnownCategories::CONTEXTUAL), - image_id); - - service_->FetchContextualSuggestionImage(synthetic_cache_id, image_url, - std::move(callback)); -} - void ContextualContentSuggestionsServiceProxy::CacheSuggestions( FetchClustersCallback callback, ContextualSuggestionsResult result) {
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h index 64c82075..19828d79 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy.h
@@ -34,17 +34,12 @@ void FetchContextualSuggestions(const GURL& url, FetchClustersCallback callback); - // Fetches an image for a contextual suggestion with specified - // |suggestion_id|. - void FetchContextualSuggestionImage( - const std::string& suggestion_id, - ntp_snippets::ImageFetchedCallback callback); + // Get the URL for the given suggestion id. + std::string GetContextualSuggestionImageUrl(const std::string& suggestion_id); - // Fetches a favicon for a contextual suggestion with specified - // |suggestion_id|. - void FetchContextualSuggestionFavicon( - const std::string& suggestion_id, - ntp_snippets::ImageFetchedCallback callback); + // Get the URL for the given suggestion id. + std::string GetContextualSuggestionFaviconUrl( + const std::string& suggestion_id); // Clears the state of the proxy. void ClearState(); @@ -58,10 +53,6 @@ void FlushMetrics(); private: - void FetchImageImpl(const GURL& image_url, - const std::string& image_id, - ntp_snippets::ImageFetchedCallback callback); - void CacheSuggestions(FetchClustersCallback callback, ContextualSuggestionsResult result); // Pointer to the service.
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc index 674543a..ca36b2e 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_proxy_unittest.cc
@@ -12,7 +12,6 @@ #include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h" #include "components/ntp_snippets/contextual/contextual_suggestions_test_utils.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_metrics_reporter.h" -#include "components/ntp_snippets/remote/cached_image_fetcher.h" #include "components/ntp_snippets/remote/remote_suggestions_database.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,6 +26,11 @@ static constexpr char kTestPeekText[] = "Test peek test"; static constexpr char kValidFromUrl[] = "http://some.url"; +static constexpr char kImageId[] = "id"; +// Keep the string after tbn: in sync with the above constant for image id. +static constexpr char kImageUrl[] = "http://www.google.com/images?q=tbn:id"; +static constexpr char kFaviconUrl[] = "http://google.com/cats.fav"; + class FakeContextualContentSuggestionsService : public ContextualContentSuggestionsService { public: @@ -50,7 +54,7 @@ FakeContextualContentSuggestionsService:: FakeContextualContentSuggestionsService() - : ContextualContentSuggestionsService(nullptr, nullptr, nullptr, nullptr) {} + : ContextualContentSuggestionsService(nullptr, nullptr) {} FakeContextualContentSuggestionsService:: ~FakeContextualContentSuggestionsService() {} @@ -90,6 +94,30 @@ EXPECT_TRUE(mock_cluster_callback.has_run); } +TEST_F(ContextualContentSuggestionsServiceProxyTest, GetImageUrl) { + auto suggestion = SuggestionBuilder(GURL(kValidFromUrl)) + .ImageId(kImageId) + .FaviconImageUrl(kFaviconUrl) + .Build(); + auto cluster = + ClusterBuilder(kValidFromUrl).AddSuggestion(suggestion).Build(); + MockClustersCallback mock_cluster_callback; + + proxy()->FetchContextualSuggestions(GURL(kValidFromUrl), + mock_cluster_callback.ToOnceCallback()); + service()->RunClustersCallback(ContextualSuggestionsResult( + kTestPeekText, std::vector<Cluster>({cluster}), PeekConditions(), + ServerExperimentInfos())); + + EXPECT_EQ(kImageUrl, proxy()->GetContextualSuggestionImageUrl(suggestion.id)); + EXPECT_EQ(kFaviconUrl, + proxy()->GetContextualSuggestionFaviconUrl(suggestion.id)); + + // Id not found. + EXPECT_EQ("", proxy()->GetContextualSuggestionImageUrl("")); + EXPECT_EQ("", proxy()->GetContextualSuggestionFaviconUrl("")); +} + // TODO(fgorski): More tests will be added, once we have the suggestions // restructured.
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc index c732147..ae4ea73 100644 --- a/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc +++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service_unittest.cc
@@ -15,7 +15,6 @@ #include "base/strings/string_number_conversions.h" #include "base/test/mock_callback.h" #include "base/test/scoped_task_environment.h" -#include "components/image_fetcher/core/image_fetcher_impl.h" #include "components/ntp_snippets/category_info.h" #include "components/ntp_snippets/content_suggestion.h" #include "components/ntp_snippets/contextual/contextual_suggestion.h" @@ -23,23 +22,16 @@ #include "components/ntp_snippets/contextual/contextual_suggestions_test_utils.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_debugging_reporter.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.h" -#include "components/ntp_snippets/remote/cached_image_fetcher.h" #include "components/ntp_snippets/remote/json_to_categories.h" -#include "components/ntp_snippets/remote/remote_suggestions_database.h" +#include "components/ntp_snippets/remote/request_throttler.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_unittest_util.h" -using ntp_snippets::CachedImageFetcher; using ntp_snippets::Category; using ntp_snippets::ContentSuggestion; using ntp_snippets::KnownCategories; -using ntp_snippets::ImageFetchedCallback; -using ntp_snippets::ImageDataFetchedCallback; -using ntp_snippets::RemoteSuggestionsDatabase; using ntp_snippets::RequestThrottler; using testing::_; @@ -80,26 +72,6 @@ PeekConditions peek_conditions_; }; -// Always fetches a fake image if the given URL is valid. -class FakeCachedImageFetcher : public CachedImageFetcher { - public: - explicit FakeCachedImageFetcher(PrefService* pref_service) - : CachedImageFetcher(std::unique_ptr<image_fetcher::ImageFetcher>(), - pref_service, - nullptr) {} - - void FetchSuggestionImage(const ContentSuggestion::ID&, - const GURL& image_url, - ImageDataFetchedCallback image_data_callback, - ImageFetchedCallback callback) override { - gfx::Image image; - if (image_url.is_valid()) { - image = gfx::test::CreateImage(); - } - std::move(callback).Run(image); - } -}; - } // namespace class ContextualContentSuggestionsServiceTest : public testing::Test { @@ -116,8 +88,6 @@ std::move(debugging_reporter)); source_ = std::make_unique<ContextualContentSuggestionsService>( std::move(fetcher), - std::make_unique<FakeCachedImageFetcher>(&pref_service_), - std::unique_ptr<RemoteSuggestionsDatabase>(), std::move(reporter_provider)); }
diff --git a/components/omnibox/browser/suggestion_answer.cc b/components/omnibox/browser/suggestion_answer.cc index 0adf61d..de02c03 100644 --- a/components/omnibox/browser/suggestion_answer.cc +++ b/components/omnibox/browser/suggestion_answer.cc
@@ -292,7 +292,7 @@ second_line_.Equals(answer.second_line_); } -void SuggestionAnswer::AddImageURLsTo(std::vector<GURL>* urls) const { +void SuggestionAnswer::AddImageURLsTo(URLs* urls) const { // Note: first_line_.image_url() is not used in practice (so it's ignored). if (image_url_.is_valid()) urls->push_back(image_url_);
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index ea1777e..d572d9a 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -27,6 +27,7 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/accessibility_browser_test_utils.h" +#include "ui/base/ui_base_features.h" #if defined(OS_MACOSX) #include "base/mac/mac_util.h" @@ -1882,6 +1883,12 @@ RunHtmlTest(FILE_PATH_LITERAL("video.html")); } +// TODO(crbug.com/916003): Fix race condition. +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + DISABLED_AccessibilityVideoControls) { + RunHtmlTest(FILE_PATH_LITERAL("video-controls.html")); +} + IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityWbr) { RunHtmlTest(FILE_PATH_LITERAL("wbr.html")); }
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc index 09b41c2d..86ceb74 100644 --- a/content/browser/devtools/protocol/input_handler.cc +++ b/content/browser/devtools/protocol/input_handler.cc
@@ -176,6 +176,15 @@ return blink::WebInputEvent::kUndefined; } +blink::WebPointerProperties::PointerType GetPointerType( + const std::string& type) { + if (type == Input::DispatchMouseEvent::PointerTypeEnum::Mouse) + return blink::WebPointerProperties::PointerType::kMouse; + if (type == Input::DispatchMouseEvent::PointerTypeEnum::Pen) + return blink::WebPointerProperties::PointerType::kPen; + return blink::WebPointerProperties::PointerType::kMouse; +} + bool GenerateTouchPoints( blink::WebTouchEvent* event, blink::WebInputEvent::Type type, @@ -598,6 +607,7 @@ Maybe<int> click_count, Maybe<double> delta_x, Maybe<double> delta_y, + Maybe<std::string> pointer_type, std::unique_ptr<DispatchMouseEventCallback> callback) { blink::WebInputEvent::Type type = GetMouseEventType(event_type); if (type == blink::WebInputEvent::kUndefined) { @@ -642,7 +652,7 @@ mouse_event->button = button; mouse_event->click_count = click_count.fromMaybe(0); - mouse_event->pointer_type = blink::WebPointerProperties::PointerType::kMouse; + mouse_event->pointer_type = GetPointerType(pointer_type.fromMaybe("")); gfx::PointF point; RenderWidgetHostImpl* widget_host =
diff --git a/content/browser/devtools/protocol/input_handler.h b/content/browser/devtools/protocol/input_handler.h index 62cc8405..0d9f46d 100644 --- a/content/browser/devtools/protocol/input_handler.h +++ b/content/browser/devtools/protocol/input_handler.h
@@ -70,6 +70,7 @@ Maybe<int> click_count, Maybe<double> delta_x, Maybe<double> delta_y, + Maybe<std::string> pointer_type, std::unique_ptr<DispatchMouseEventCallback> callback) override; void DispatchTouchEvent(
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index 70fc8ad..6cdb9cd 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -2146,27 +2146,27 @@ parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(false); + download->Resume(true); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(false); + download->Resume(true); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(false); + download->Resume(true); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(false); + download->Resume(true); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(false); + download->Resume(true); WaitForCompletion(download); EXPECT_EQ(expected_hash, download->GetHash());
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 644ddcb9..163932d 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -774,11 +774,6 @@ return browser_context_->IsOffTheRecord(); } -bool DownloadManagerImpl::IsActiveNetworkMetered() const { - // TODO(shaktisahu): Call ChromeDownloadManagerDelegate to get this. - return false; -} - void DownloadManagerImpl::ReportBytesWasted( download::DownloadItemImpl* download) { in_progress_manager_->ReportBytesWasted(download);
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h index d596137..b94e85c 100644 --- a/content/browser/download/download_manager_impl.h +++ b/content/browser/download/download_manager_impl.h
@@ -257,7 +257,6 @@ base::Optional<download::DownloadEntry> GetInProgressEntry( download::DownloadItemImpl* download) override; bool IsOffTheRecord() const override; - bool IsActiveNetworkMetered() const override; void ReportBytesWasted(download::DownloadItemImpl* download) override; // Drops a download before it is created.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 1897079..93938ee 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2269,15 +2269,12 @@ associated_registry->AddInterface(base::Bind( &RenderProcessHostImpl::CreateRendererHost, base::Unretained(this))); - // TODO(lukasza): https://crbug.com/891872: Stop vending out non-origin-bound - // URLLoaderFactories to the renderer process. if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - const base::Optional<url::Origin> kNoOrigin = base::nullopt; AddUIThreadInterface( registry.get(), - base::BindRepeating(&RenderProcessHostImpl::CreateURLLoaderFactory, - base::Unretained(this), kNoOrigin, - nullptr /* header_client */)); + base::BindRepeating( + &RenderProcessHostImpl::CreateURLLoaderFactoryForRendererProcess, + base::Unretained(this))); } registry->AddInterface( @@ -2536,10 +2533,28 @@ return &process_resource_coordinator_; } +void RenderProcessHostImpl::CreateURLLoaderFactoryForRendererProcess( + network::mojom::URLLoaderFactoryRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + base::Optional<url::Origin> request_initiator_site_lock; + GURL process_lock = + ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock(GetID()); + if (process_lock.is_valid()) { + request_initiator_site_lock = SiteInstanceImpl::GetRequestInitiatorSiteLock( + GetBrowserContext(), process_lock); + } + + CreateURLLoaderFactory(request_initiator_site_lock, + nullptr /* header_client */, std::move(request)); +} + void RenderProcessHostImpl::CreateURLLoaderFactory( const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // "chrome-guest://..." is never used as a |request_initiator|. Therefore // it doesn't make sense to associate a URLLoaderFactory with a // chrome-guest-based |origin|.
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index f17fb77..efaf56d 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -661,6 +661,15 @@ // execute. void CancelProcessShutdownDelayForUnload(); + // Creates a URLLoaderFactory that can be used by the renderer process, + // without binding it to a specific frame or an origin. + // + // TODO(kinuko, lukasza): https://crbug.com/891872: Remove, once all + // URLLoaderFactories are associated with a specific origin and an execution + // context (e.g. a frame, a service worker or any other kind of worker). + void CreateURLLoaderFactoryForRendererProcess( + network::mojom::URLLoaderFactoryRequest request); + mojo::OutgoingInvitation mojo_invitation_; std::unique_ptr<ChildConnection> child_connection_;
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 1536a11..dfe596f 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -164,7 +164,7 @@ } // namespace // static -const int64_t RenderViewHostImpl::kUnloadTimeoutMS = 1000; +const int64_t RenderViewHostImpl::kUnloadTimeoutMS = 500; /////////////////////////////////////////////////////////////////////////////// // RenderViewHost, public:
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 02c5cd1..1da0c85d 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -12910,9 +12910,18 @@ cc::TouchAction expected_touch_action = cc::kTouchActionPan; GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, effective_touch_action, whitelisted_touch_action); - EXPECT_EQ(expected_touch_action, effective_touch_action.has_value() - ? effective_touch_action.value() - : cc::kTouchActionAuto); + cc::TouchAction effective_touch_action_result = + effective_touch_action.has_value() ? effective_touch_action.value() + : cc::kTouchActionAuto; + // TouchAction might have not been propagated to child frames yet, loop until + // we get the expected touch action value. + while (expected_touch_action != effective_touch_action_result) { + GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, + effective_touch_action, whitelisted_touch_action); + effective_touch_action_result = effective_touch_action.has_value() + ? effective_touch_action.value() + : cc::kTouchActionAuto; + } if (whitelisted_touch_action.has_value()) EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value()); @@ -12926,9 +12935,16 @@ child_thread_observer.get()); GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, effective_touch_action, whitelisted_touch_action); - EXPECT_EQ(expected_touch_action, effective_touch_action.has_value() - ? effective_touch_action.value() - : cc::kTouchActionAuto); + effective_touch_action_result = effective_touch_action.has_value() + ? effective_touch_action.value() + : cc::kTouchActionAuto; + while (expected_touch_action != effective_touch_action_result) { + GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, + effective_touch_action, whitelisted_touch_action); + effective_touch_action_result = effective_touch_action.has_value() + ? effective_touch_action.value() + : cc::kTouchActionAuto; + } if (whitelisted_touch_action.has_value()) EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value()); @@ -12941,9 +12957,16 @@ expected_touch_action = cc::kTouchActionAuto; GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, effective_touch_action, whitelisted_touch_action); - EXPECT_EQ(expected_touch_action, effective_touch_action.has_value() - ? effective_touch_action.value() - : cc::kTouchActionAuto); + effective_touch_action_result = effective_touch_action.has_value() + ? effective_touch_action.value() + : cc::kTouchActionAuto; + while (expected_touch_action != effective_touch_action_result) { + GetTouchActionsForChild(router, rwhv_root, rwhv_child, point_inside_child, + effective_touch_action, whitelisted_touch_action); + effective_touch_action_result = effective_touch_action.has_value() + ? effective_touch_action.value() + : cc::kTouchActionAuto; + } if (whitelisted_touch_action.has_value()) EXPECT_EQ(expected_touch_action, whitelisted_touch_action.value()); }
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 1904759..b3b1de9 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -477,6 +477,11 @@ if (base::FeatureList::IsEnabled(blink::features::kWritableFilesAPI)) WebRuntimeFeatures::EnableFeatureFromString("WritableFiles", true); + if (base::FeatureList::IsEnabled( + blink::features::kForbidSyncXHRInPageDismissal)) { + WebRuntimeFeatures::EnableForbidSyncXHRInPageDismissal(true); + } + // End individual features. // Do not add individual features below this line.
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index 6750a68..941d58b 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -187,6 +187,15 @@ : thread_bundle_( std::make_unique<TestBrowserThreadBundle>(thread_bundle_options)) {} +RenderViewHostTestHarness::RenderViewHostTestHarness( + base::test::ScopedTaskEnvironment::MainThreadType main_thread_type, + base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode, + int thread_bundle_options) + : thread_bundle_( + std::make_unique<TestBrowserThreadBundle>(main_thread_type, + execution_control_mode, + thread_bundle_options)) {} + RenderViewHostTestHarness::~RenderViewHostTestHarness() { }
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index a95b908..9c7cbf7 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -192,6 +192,10 @@ // Constructs a RenderViewHostTestHarness which uses |thread_bundle_options| // to initialize its TestBrowserThreadBundle. explicit RenderViewHostTestHarness(int thread_bundle_options = 0); + RenderViewHostTestHarness( + base::test::ScopedTaskEnvironment::MainThreadType main_thread_type, + base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode, + int thread_bundle_options = 0); ~RenderViewHostTestHarness() override; NavigationController& controller();
diff --git a/content/test/data/accessibility/html/video-controls-expected-auralinux.txt b/content/test/data/accessibility/html/video-controls-expected-auralinux.txt new file mode 100644 index 0000000..9ed3131 --- /dev/null +++ b/content/test/data/accessibility/html/video-controls-expected-auralinux.txt
@@ -0,0 +1,16 @@ +[document web] +++[section] +++++[video] +++++++[section] +++++++++[tool bar] name='video' description='video' horizontal +++++++++[tool bar] name='video' description='video' horizontal +++++++++++[tool bar] name='video' description='video' horizontal +++++++++++++[tool bar] name='video' description='video' horizontal +++++++++++++++[push button] name='play' +++++++++++++++[text] name='0:00' +++++++++++++++[section] +++++++++++++++++[section] +++++++++++++++++[push button] name='mute' +++++++++++++++[push button] name='enter full screen' +++++++++++++++[push button] name='show more media controls' description='more options' +++++++++++++[slider] description='movie time scrubber' horizontal
diff --git a/content/test/data/accessibility/html/video-controls-expected-blink.txt b/content/test/data/accessibility/html/video-controls-expected-blink.txt new file mode 100644 index 0000000..ae9e018 --- /dev/null +++ b/content/test/data/accessibility/html/video-controls-expected-blink.txt
@@ -0,0 +1,18 @@ +rootWebArea +++genericContainer +++++video +++++++genericContainer +++++++++toolbar horizontal description='video' name='video' descriptionFrom=uninitialized +++++++++toolbar horizontal description='video' name='video' descriptionFrom=uninitialized +++++++++++toolbar horizontal description='video' name='video' descriptionFrom=uninitialized +++++++++++++toolbar horizontal description='video' name='video' descriptionFrom=uninitialized +++++++++++++++button name='play' restriction=disabled +++++++++++++++staticText name='0:00' +++++++++++++++++inlineTextBox name='0:00' +++++++++++++++genericContainer +++++++++++++++++genericContainer +++++++++++++++++button name='mute' restriction=disabled +++++++++++++++button name='enter full screen' restriction=disabled +++++++++++++++button description='more options' name='show more media controls' descriptionFrom=uninitialized restriction=disabled +++++++++++++slider horizontal description='movie time scrubber' value='0:00' descriptionFrom=uninitialized valueForRange=0.00 minValueForRange=0.00 maxValueForRange=0.00 +++++++++++++++sliderThumb
diff --git a/content/test/data/accessibility/html/video-controls.html b/content/test/data/accessibility/html/video-controls.html new file mode 100644 index 0000000..c69705a --- /dev/null +++ b/content/test/data/accessibility/html/video-controls.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> + <body> + <video controls></video> + </body> +</html>
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index cadbe39..b6ea88c3 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn
@@ -68,7 +68,6 @@ deps = [ ":fuzzer_support", ] - additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ] } fuzzer_test("clear_site_data_fuzzer") { @@ -90,7 +89,6 @@ ":html_tree_proto", "//third_party/libprotobuf-mutator", ] - additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ] } proto_library("html_tree_proto") {
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 54ac8fa5..09da641c 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -49,16 +49,11 @@ # TODO(vmiura) check / generate reference images for Android devices self.Fail('Pixel_SolidColorBackground', ['mac', 'android'], bug=624256) - # TODO(michaelludwig): restore after Skia roll (see below) - #self.Fail('Pixel_CSSFilterEffects', ['mac', ('nvidia', 0xfe9)], bug=690277) + self.Fail('Pixel_CSSFilterEffects', ['mac', ('nvidia', 0xfe9)], bug=690277) # Became flaky on 10.13.6. When it flakes, it flakes 3 times, so # mark failing, unfortunately. - # TODO(michaelludwig): restore after Skia roll (see below) - #self.Fail('Pixel_CSSFilterEffects', ['highsierra', 'amd'], bug=872423) - - # TODO(michaelludwig): remove after Skia roll - self.Fail('Pixel_CSSFilterEffects', bug=915735) + self.Fail('Pixel_CSSFilterEffects', ['highsierra', 'amd'], bug=872423) # TODO(kbr): flakily timing out on this configuration. self.Flaky('*', ['linux', 'intel', 'debug'], bug=648369)
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn index b7e91c73..c27c7cf 100644 --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn
@@ -69,9 +69,6 @@ "symmetric_key.h", ] - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":platform", "//base", @@ -154,8 +151,6 @@ ] } - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":crypto", ":platform",
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.mm index f19bc5a..53bb1bf 100644 --- a/ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.mm
@@ -142,7 +142,7 @@ - (void)loadModel { [super loadModel]; - TableViewModel* model = self.tableViewModel; + TableViewModel<TableViewItem*>* model = self.tableViewModel; BOOL isEditing = self.tableView.editing;
diff --git a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h index 1fd4e3c0..dce72b7 100644 --- a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h +++ b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h
@@ -7,18 +7,15 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" - -@class MDCButton; +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" // Item that configures a CopiedToChromeCell. -@interface CopiedToChromeItem : CollectionViewItem +@interface CopiedToChromeItem : TableViewItem @end // A cell indicating that the credit card has been copied to Chrome. Includes a // button to clear the copy. -@interface CopiedToChromeCell : MDCCollectionViewCell +@interface CopiedToChromeCell : UITableViewCell // Text label displaying the item's text. @property(nonatomic, readonly, strong) UILabel* textLabel;
diff --git a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm index 45ac0f2..1185dc40 100644 --- a/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm +++ b/ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.mm
@@ -5,28 +5,16 @@ #import "ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h" #include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" -#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -namespace { -// Padding used on the leading and trailing edges of the cell. -const CGFloat kHorizontalPadding = 16; - -// Padding used on the top and bottom edges of the cell. -const CGFloat kVerticalPadding = 16; -} // namespace - @implementation CopiedToChromeItem - (instancetype)initWithType:(NSInteger)type { @@ -42,10 +30,10 @@ @implementation CopiedToChromeCell @synthesize textLabel = _textLabel; -@synthesize button = _button; -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString*)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { UIView* contentView = self.contentView; @@ -53,8 +41,9 @@ _textLabel.translatesAutoresizingMaskIntoConstraints = NO; _textLabel.text = l10n_util::GetNSString(IDS_IOS_AUTOFILL_DESCRIBE_LOCAL_COPY); - _textLabel.font = [UIFont systemFontOfSize:kUIKitMainFontSize]; - _textLabel.textColor = UIColorFromRGB(kUIKitMainTextColor); + _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _textLabel.adjustsFontForContentSizeCategory = YES; + _textLabel.textColor = UIColor.blackColor; [_textLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis: @@ -62,7 +51,7 @@ [contentView addSubview:_textLabel]; _button = [UIButton buttonWithType:UIButtonTypeCustom]; - [_button setTitleColor:UIColorFromRGB(kUIKitFooterLinkColor) + [_button setTitleColor:UIColorFromRGB(kTableViewTextLabelColorBlue) forState:UIControlStateNormal]; _button.translatesAutoresizingMaskIntoConstraints = NO; @@ -75,18 +64,20 @@ [NSLayoutConstraint activateConstraints:@[ [_textLabel.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor - constant:kHorizontalPadding], + constant:kTableViewHorizontalSpacing], [_textLabel.trailingAnchor constraintLessThanOrEqualToAnchor:_button.leadingAnchor - constant:-kHorizontalPadding], + constant:-kTableViewHorizontalSpacing], [_textLabel.centerYAnchor constraintEqualToAnchor:contentView.centerYAnchor], - [_button.trailingAnchor constraintEqualToAnchor:contentView.trailingAnchor - constant:-kHorizontalPadding], + [_button.trailingAnchor + constraintEqualToAnchor:contentView.trailingAnchor + constant:-kTableViewHorizontalSpacing], [_button.firstBaselineAnchor constraintEqualToAnchor:_textLabel.firstBaselineAnchor], ]]; - AddOptionalVerticalPadding(contentView, _textLabel, kVerticalPadding); + AddOptionalVerticalPadding(contentView, _textLabel, + kTableViewLargeVerticalSpacing); } return self; }
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm index 1b889ae..866ecff 100644 --- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm +++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" #import "ios/chrome/browser/ui/icons/chrome_icon.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" +#import "ios/chrome/browser/ui/settings/cells/copied_to_chrome_item.h" #import "ios/chrome/browser/ui/settings/cells/encryption_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_detail_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h" @@ -282,6 +283,11 @@ [model addItem:autofillItemWithAllTexts toSectionWithIdentifier:SectionIdentifierAutofill]; + CopiedToChromeItem* copiedToChrome = + [[CopiedToChromeItem alloc] initWithType:ItemTypeAutofillData]; + [model addItem:copiedToChrome + toSectionWithIdentifier:SectionIdentifierAutofill]; + // SectionIdentifierAccount. TableViewSigninPromoItem* signinPromo = [[TableViewSigninPromoItem alloc] initWithType:ItemTypeAccount];
diff --git a/media/learning/common/learning_task.h b/media/learning/common/learning_task.h index 9e1d630..8319d208 100644 --- a/media/learning/common/learning_task.h +++ b/media/learning/common/learning_task.h
@@ -28,6 +28,7 @@ // combination of orderings and types. enum class Model { kRandomForest, + kExtraTrees, }; enum class Ordering {
diff --git a/media/learning/common/training_example.cc b/media/learning/common/training_example.cc index 5055f25..a0b03eaa 100644 --- a/media/learning/common/training_example.cc +++ b/media/learning/common/training_example.cc
@@ -22,10 +22,14 @@ TrainingExample::~TrainingExample() = default; std::ostream& operator<<(std::ostream& out, const TrainingExample& example) { - for (const auto& feature : example.features) - out << " " << feature; + out << example.features << " => " << example.target_value; - out << " => " << example.target_value; + return out; +} + +std::ostream& operator<<(std::ostream& out, const FeatureVector& features) { + for (const auto& feature : features) + out << " " << feature; return out; }
diff --git a/media/learning/common/training_example.h b/media/learning/common/training_example.h index 8252c8b..0252a58 100644 --- a/media/learning/common/training_example.h +++ b/media/learning/common/training_example.h
@@ -107,6 +107,9 @@ COMPONENT_EXPORT(LEARNING_COMMON) std::ostream& operator<<(std::ostream& out, const TrainingExample& example); +COMPONENT_EXPORT(LEARNING_COMMON) +std::ostream& operator<<(std::ostream& out, const FeatureVector& features); + } // namespace learning } // namespace media
diff --git a/media/learning/impl/BUILD.gn b/media/learning/impl/BUILD.gn index 777da95..0a2c150 100644 --- a/media/learning/impl/BUILD.gn +++ b/media/learning/impl/BUILD.gn
@@ -7,6 +7,8 @@ visibility = [ "//media/learning/impl:unit_tests" ] sources = [ + "extra_trees_trainer.cc", + "extra_trees_trainer.h", "learning_session_impl.cc", "learning_session_impl.h", "learning_task_controller.h", @@ -15,8 +17,6 @@ "model.h", "one_hot.cc", "one_hot.h", - "random_forest.cc", - "random_forest.h", "random_forest_trainer.cc", "random_forest_trainer.h", "random_number_generator.cc", @@ -26,6 +26,8 @@ "target_distribution.cc", "target_distribution.h", "training_algorithm.h", + "voting_ensemble.cc", + "voting_ensemble.h", ] defines = [ "IS_LEARNING_IMPL_IMPL" ] @@ -43,6 +45,7 @@ testonly = true sources = [ + "extra_trees_trainer_unittest.cc", "fisher_iris_dataset.cc", "fisher_iris_dataset.h", "learning_session_impl_unittest.cc",
diff --git a/media/learning/impl/extra_trees_trainer.cc b/media/learning/impl/extra_trees_trainer.cc new file mode 100644 index 0000000..27e0346d --- /dev/null +++ b/media/learning/impl/extra_trees_trainer.cc
@@ -0,0 +1,49 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/extra_trees_trainer.h" + +#include <set> + +#include "base/logging.h" +#include "media/learning/impl/one_hot.h" +#include "media/learning/impl/random_tree_trainer.h" +#include "media/learning/impl/voting_ensemble.h" + +namespace media { +namespace learning { + +ExtraTreesTrainer::ExtraTreesTrainer() = default; + +ExtraTreesTrainer::~ExtraTreesTrainer() = default; + +std::unique_ptr<Model> ExtraTreesTrainer::Train( + const LearningTask& task, + const TrainingData& training_data) { + int n_trees = task.rf_number_of_trees; + + RandomTreeTrainer tree_trainer(rng()); + std::vector<std::unique_ptr<Model>> trees; + trees.reserve(n_trees); + + // RandomTree requires one-hot vectors to properly choose split points the way + // that ExtraTrees require. + std::unique_ptr<OneHotConverter> converter = + std::make_unique<OneHotConverter>(task, training_data); + TrainingData converted_training_data = converter->Convert(training_data); + + for (int i = 0; i < n_trees; i++) { + // Train the tree. + std::unique_ptr<Model> tree = tree_trainer.Train( + converter->converted_task(), converted_training_data); + + trees.push_back(std::move(tree)); + } + + return std::make_unique<ConvertingModel>( + std::move(converter), std::make_unique<VotingEnsemble>(std::move(trees))); +} + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/extra_trees_trainer.h b/media/learning/impl/extra_trees_trainer.h new file mode 100644 index 0000000..34a99187 --- /dev/null +++ b/media/learning/impl/extra_trees_trainer.h
@@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_IMPL_EXTRA_TREES_TRAINER_H_ +#define MEDIA_LEARNING_IMPL_EXTRA_TREES_TRAINER_H_ + +#include <memory> +#include <vector> + +#include "base/component_export.h" +#include "base/macros.h" +#include "media/learning/common/learning_task.h" +#include "media/learning/impl/random_number_generator.h" +#include "media/learning/impl/training_algorithm.h" + +namespace media { +namespace learning { + +// Bagged forest of extremely randomized trees. +// +// These are an ensemble of trees. Each tree is constructed from the full +// training set. The trees are constructed by selecting a random subset of +// features at each node. For each feature, a uniformly random split point is +// chosen. The feature with the best randomly chosen split point is used. +// +// These will automatically convert nominal values to one-hot vectors. +class COMPONENT_EXPORT(LEARNING_IMPL) ExtraTreesTrainer + : public HasRandomNumberGenerator { + public: + ExtraTreesTrainer(); + ~ExtraTreesTrainer(); + + std::unique_ptr<Model> Train(const LearningTask& task, + const TrainingData& training_data); + + private: + DISALLOW_COPY_AND_ASSIGN(ExtraTreesTrainer); +}; + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_IMPL_EXTRA_TREES_TRAINER_H_
diff --git a/media/learning/impl/extra_trees_trainer_unittest.cc b/media/learning/impl/extra_trees_trainer_unittest.cc new file mode 100644 index 0000000..c830c523 --- /dev/null +++ b/media/learning/impl/extra_trees_trainer_unittest.cc
@@ -0,0 +1,103 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/extra_trees_trainer.h" + +#include "base/memory/ref_counted.h" +#include "media/learning/impl/fisher_iris_dataset.h" +#include "media/learning/impl/test_random_number_generator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { +namespace learning { + +class ExtraTreesTest : public testing::TestWithParam<LearningTask::Ordering> { + public: + ExtraTreesTest() : rng_(0), ordering_(GetParam()) { + trainer_.SetRandomNumberGeneratorForTesting(&rng_); + } + + // Set up |task_| to have |n| features with the given ordering. + void SetupFeatures(size_t n) { + for (size_t i = 0; i < n; i++) { + LearningTask::ValueDescription desc; + desc.ordering = ordering_; + task_.feature_descriptions.push_back(desc); + } + } + + TestRandomNumberGenerator rng_; + ExtraTreesTrainer trainer_; + LearningTask task_; + // Feature ordering. + LearningTask::Ordering ordering_; +}; + +TEST_P(ExtraTreesTest, EmptyTrainingDataWorks) { + TrainingData empty; + auto model = trainer_.Train(task_, empty); + EXPECT_NE(model.get(), nullptr); + EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetDistribution()); +} + +TEST_P(ExtraTreesTest, FisherIrisDataset) { + SetupFeatures(4); + FisherIrisDataset iris; + TrainingData training_data = iris.GetTrainingData(); + auto model = trainer_.Train(task_, training_data); + + // Verify predictions on the training set, just for sanity. + size_t num_correct = 0; + for (const TrainingExample& example : training_data) { + TargetDistribution distribution = + model->PredictDistribution(example.features); + TargetValue predicted_value; + if (distribution.FindSingularMax(&predicted_value) && + predicted_value == example.target_value) { + num_correct += example.weight; + } + } + + // Expect very high accuracy. We should get ~100%. + // We get about 96% for one-hot features, and 100% for numeric. Since the + // data really is numeric, that seems reasonable. + double train_accuracy = ((double)num_correct) / training_data.total_weight(); + EXPECT_GT(train_accuracy, 0.95); +} + +TEST_P(ExtraTreesTest, WeightedTrainingSetIsSupported) { + // Create a training set with unseparable data, but give one of them a large + // weight. See if that one wins. + SetupFeatures(1); + TrainingExample example_1({FeatureValue(123)}, TargetValue(1)); + TrainingExample example_2({FeatureValue(123)}, TargetValue(2)); + const size_t weight = 100; + TrainingData training_data; + example_1.weight = weight; + training_data.push_back(example_1); + // Push many |example_2|'s, which will win without the weights. + training_data.push_back(example_2); + training_data.push_back(example_2); + training_data.push_back(example_2); + training_data.push_back(example_2); + + // Create a weighed set with |weight| for each example's weight. + EXPECT_FALSE(training_data.is_unweighted()); + auto model = trainer_.Train(task_, training_data); + + // The singular max should be example_1. + TargetDistribution distribution = + model->PredictDistribution(example_1.features); + TargetValue predicted_value; + EXPECT_TRUE(distribution.FindSingularMax(&predicted_value)); + EXPECT_EQ(predicted_value, example_1.target_value); +} + +INSTANTIATE_TEST_CASE_P(ExtraTreesTest, + ExtraTreesTest, + testing::ValuesIn({LearningTask::Ordering::kUnordered, + LearningTask::Ordering::kNumeric})); + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc index 50d38c0..0c8f9c3 100644 --- a/media/learning/impl/learning_task_controller_impl.cc +++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "media/learning/impl/extra_trees_trainer.h" #include "media/learning/impl/random_tree_trainer.h" namespace media { @@ -15,6 +16,15 @@ LearningTaskControllerImpl::LearningTaskControllerImpl(const LearningTask& task) : task_(task), training_data_(std::make_unique<TrainingData>()) { switch (task_.model) { + case LearningTask::Model::kExtraTrees: + training_cb_ = base::BindRepeating( + [](const LearningTask& task, TrainingData training_data, + TrainedModelCB model_cb) { + ExtraTreesTrainer trainer; + std::move(model_cb).Run(trainer.Train(task, training_data)); + }, + task_); + break; case LearningTask::Model::kRandomForest: // TODO(liberato): forest! training_cb_ = RandomTreeTrainer::GetTrainingAlgorithmCB(task_);
diff --git a/media/learning/impl/random_forest.cc b/media/learning/impl/random_forest.cc deleted file mode 100644 index d533536..0000000 --- a/media/learning/impl/random_forest.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/learning/impl/random_forest.h" - -namespace media { -namespace learning { - -RandomForest::RandomForest(std::vector<std::unique_ptr<Model>> trees) - : trees_(std::move(trees)) {} - -RandomForest::~RandomForest() = default; - -TargetDistribution RandomForest::PredictDistribution( - const FeatureVector& instance) { - TargetDistribution forest_distribution; - - for (auto iter = trees_.begin(); iter != trees_.end(); iter++) - forest_distribution += (*iter)->PredictDistribution(instance); - - return forest_distribution; -} - -} // namespace learning -} // namespace media
diff --git a/media/learning/impl/random_forest.h b/media/learning/impl/random_forest.h deleted file mode 100644 index 84b80587..0000000 --- a/media/learning/impl/random_forest.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_LEARNING_IMPL_RANDOM_FOREST_H_ -#define MEDIA_LEARNING_IMPL_RANDOM_FOREST_H_ - -#include <memory> -#include <vector> - -#include "base/component_export.h" -#include "base/macros.h" -#include "media/learning/impl/model.h" - -namespace media { -namespace learning { - -// Bagged forest of randomized trees. -// TODO(liberato): consider a generic Bagging class, since this doesn't really -// depend on RandomTree at all. -class COMPONENT_EXPORT(LEARNING_IMPL) RandomForest : public Model { - public: - RandomForest(std::vector<std::unique_ptr<Model>> trees); - ~RandomForest() override; - - // Model - TargetDistribution PredictDistribution( - const FeatureVector& instance) override; - - private: - std::vector<std::unique_ptr<Model>> trees_; - - DISALLOW_COPY_AND_ASSIGN(RandomForest); -}; - -} // namespace learning -} // namespace media - -#endif // MEDIA_LEARNING_IMPL_RANDOM_FOREST_H_
diff --git a/media/learning/impl/random_forest_trainer.cc b/media/learning/impl/random_forest_trainer.cc index 6593f458..6895de7 100644 --- a/media/learning/impl/random_forest_trainer.cc +++ b/media/learning/impl/random_forest_trainer.cc
@@ -7,8 +7,8 @@ #include <set> #include "base/logging.h" -#include "media/learning/impl/random_forest.h" #include "media/learning/impl/random_tree_trainer.h" +#include "media/learning/impl/voting_ensemble.h" namespace media { namespace learning { @@ -77,8 +77,8 @@ trees.push_back(std::move(tree)); } - std::unique_ptr<RandomForest> forest = - std::make_unique<RandomForest>(std::move(trees)); + std::unique_ptr<VotingEnsemble> forest = + std::make_unique<VotingEnsemble>(std::move(trees)); // Compute OOB accuracy. int num_correct = 0;
diff --git a/media/learning/impl/random_tree_trainer.h b/media/learning/impl/random_tree_trainer.h index 534fec7..215d437 100644 --- a/media/learning/impl/random_tree_trainer.h +++ b/media/learning/impl/random_tree_trainer.h
@@ -42,6 +42,22 @@ // target values that ended up in each group. The index with the best score is // chosen for the split. // +// For nominal features, we split the feature into all of its nominal values. +// This is somewhat nonstandard; one would normally convert to one-hot numeric +// features first. See OneHotConverter if you'd like to do this. +// +// For numeric features, we choose a split point uniformly at random between its +// min and max values in the training data. We do this because it's suitable +// for extra trees. RandomForest trees want to select the best split point for +// each feature, rather than uniformly. Either way, of course, we choose the +// best split among the (feature, split point) pairs we're considering. +// +// Also note that for one-hot features, these are the same thing. So, this +// implementation is suitable for extra trees with numeric (possibly one hot) +// features, or RF with one-hot nominal features. Note that non-one-hot nominal +// features probably work fine with RF too. Numeric, non-binary features don't +// work with RF, unless one changes the split point selection. +// // The training algorithm then recurses to build child nodes. One child node is // created for each observed value of the |i|-th feature in the training set. // The child node is trained using the subset of the training set that shares
diff --git a/media/learning/impl/voting_ensemble.cc b/media/learning/impl/voting_ensemble.cc new file mode 100644 index 0000000..667e7399 --- /dev/null +++ b/media/learning/impl/voting_ensemble.cc
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/voting_ensemble.h" + +namespace media { +namespace learning { + +VotingEnsemble::VotingEnsemble(std::vector<std::unique_ptr<Model>> models) + : models_(std::move(models)) {} + +VotingEnsemble::~VotingEnsemble() = default; + +TargetDistribution VotingEnsemble::PredictDistribution( + const FeatureVector& instance) { + TargetDistribution distribution; + + for (auto iter = models_.begin(); iter != models_.end(); iter++) + distribution += (*iter)->PredictDistribution(instance); + + return distribution; +} + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/voting_ensemble.h b/media/learning/impl/voting_ensemble.h new file mode 100644 index 0000000..2b4bf11 --- /dev/null +++ b/media/learning/impl/voting_ensemble.h
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_IMPL_VOTING_ENSEMBLE_H_ +#define MEDIA_LEARNING_IMPL_VOTING_ENSEMBLE_H_ + +#include <memory> +#include <vector> + +#include "base/component_export.h" +#include "base/macros.h" +#include "media/learning/impl/model.h" + +namespace media { +namespace learning { + +// Ensemble classifier. Takes multiple models and returns an aggregate of the +// individual predictions. +class COMPONENT_EXPORT(LEARNING_IMPL) VotingEnsemble : public Model { + public: + VotingEnsemble(std::vector<std::unique_ptr<Model>> models); + ~VotingEnsemble() override; + + // Model + TargetDistribution PredictDistribution( + const FeatureVector& instance) override; + + private: + std::vector<std::unique_ptr<Model>> models_; + + DISALLOW_COPY_AND_ASSIGN(VotingEnsemble); +}; + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_IMPL_VOTING_ENSEMBLE_H_
diff --git a/services/tracing/coordinator.cc b/services/tracing/coordinator.cc index ba0271e..59a0bac 100644 --- a/services/tracing/coordinator.cc +++ b/services/tracing/coordinator.cc
@@ -87,10 +87,6 @@ agent_entry, std::move(ptr))); } - // Called from |backend_task_runner_| to close the recorder proxy on the - // correct task runner. - void CloseRecorder(mojom::RecorderPtr recorder) {} - // Called from |main_task_runner_| either after flushing is complete or at // shutdown. We either will not write to the stream afterwards or do not care // what happens to what we try to write. @@ -435,8 +431,7 @@ // Recorders are created and closed on |backend_task_runner_|. backend_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&Coordinator::TraceStreamer::CloseRecorder, - trace_streamer_->AsWeakPtr(), std::move(recorder))); + base::BindOnce([](mojom::RecorderPtr ptr) {}, std::move(recorder))); } }
diff --git a/testing/android/proguard_for_test.flags b/testing/android/proguard_for_test.flags index a013550..cb65c1cd 100644 --- a/testing/android/proguard_for_test.flags +++ b/testing/android/proguard_for_test.flags
@@ -21,6 +21,16 @@ # all classes from the test apk. -keep class **.test.** { *; } +# These 2 rules together keep all interfaces that are mocked by Mockito, since +# Mockito generates these mocks at runtime, and the interfaces could get methods +# stripped out. +-if class * { + @org.mockito.Mock * *; +} +-keep interface <2> { + <methods>; +} + # Keep all enum members since they might be reflectively called by JUnit4 runner -keepclassmembers enum * { *; }
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 424d0099..b9eaeed 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -431,9 +431,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_ash_unittests", + "name": "non_single_process_mash_ash_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -510,10 +510,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--override-use-software-gl-for-tests" ], - "name": "single_process_mash_browser_tests", + "name": "non_single_process_mash_browser_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 20 @@ -621,6 +621,18 @@ }, { "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests" + ], + "name": "non_single_process_mash_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=TracingPerfettoBackend", "--gtest_filter=TracingControllerTest.*" ], @@ -632,18 +644,6 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--override-use-software-gl-for-tests" - ], - "name": "single_process_mash_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 5 - }, - "test": "content_browsertests" - }, - { - "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -661,9 +661,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_content_unittests", + "name": "non_single_process_mash_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -717,9 +717,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_exo_unittests", + "name": "non_single_process_mash_exo_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -788,9 +788,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_interactive_ui_tests", + "name": "non_single_process_mash_interactive_ui_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 3 @@ -1042,9 +1042,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_unit_tests", + "name": "non_single_process_mash_unit_tests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1137,9 +1137,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_ash_unittests", + "name": "non_single_process_mash_ash_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1216,10 +1216,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--override-use-software-gl-for-tests" ], - "name": "single_process_mash_browser_tests", + "name": "non_single_process_mash_browser_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 10 @@ -1327,6 +1327,18 @@ }, { "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests" + ], + "name": "non_single_process_mash_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=TracingPerfettoBackend", "--gtest_filter=TracingControllerTest.*" ], @@ -1338,18 +1350,6 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--override-use-software-gl-for-tests" - ], - "name": "single_process_mash_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 5 - }, - "test": "content_browsertests" - }, - { - "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -1367,9 +1367,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_content_unittests", + "name": "non_single_process_mash_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1423,9 +1423,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_exo_unittests", + "name": "non_single_process_mash_exo_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -1494,9 +1494,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_interactive_ui_tests", + "name": "non_single_process_mash_interactive_ui_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 3 @@ -1747,9 +1747,9 @@ }, { "args": [ - "--enable-features=SingleProcessMash" + "--disable-features=SingleProcessMash" ], - "name": "single_process_mash_unit_tests", + "name": "non_single_process_mash_unit_tests", "swarming": { "can_use_on_swarming_builders": true },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index d6324176..8f4a868 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -4169,10 +4169,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_ash_unittests", + "name": "non_single_process_mash_ash_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -4277,11 +4277,11 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--override-use-software-gl-for-tests", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_browser_tests", + "name": "non_single_process_mash_browser_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 30 @@ -4426,6 +4426,19 @@ }, { "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests", + "--test-launcher-print-test-stdio=always" + ], + "name": "non_single_process_mash_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=TracingPerfettoBackend", "--gtest_filter=TracingControllerTest.*", "--test-launcher-print-test-stdio=always" @@ -4438,19 +4451,6 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--override-use-software-gl-for-tests", - "--test-launcher-print-test-stdio=always" - ], - "name": "single_process_mash_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 5 - }, - "test": "content_browsertests" - }, - { - "args": [ "--enable-features=VizDisplayCompositor", "--test-launcher-print-test-stdio=always" ], @@ -4472,10 +4472,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_content_unittests", + "name": "non_single_process_mash_content_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -4548,10 +4548,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_exo_unittests", + "name": "non_single_process_mash_exo_unittests", "swarming": { "can_use_on_swarming_builders": true }, @@ -4641,10 +4641,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_interactive_ui_tests", + "name": "non_single_process_mash_interactive_ui_tests", "swarming": { "can_use_on_swarming_builders": true, "shards": 3 @@ -5010,10 +5010,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_unit_tests", + "name": "non_single_process_mash_unit_tests", "swarming": { "can_use_on_swarming_builders": true }, @@ -5181,10 +5181,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_ash_unittests", + "name": "non_single_process_mash_ash_unittests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5355,11 +5355,11 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--override-use-software-gl-for-tests", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_browser_tests", + "name": "non_single_process_mash_browser_tests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5592,6 +5592,25 @@ }, { "args": [ + "--disable-features=SingleProcessMash", + "--override-use-software-gl-for-tests", + "--test-launcher-print-test-stdio=always" + ], + "name": "non_single_process_mash_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Ubuntu-14.04" + } + ], + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=TracingPerfettoBackend", "--gtest_filter=TracingControllerTest.*", "--test-launcher-print-test-stdio=always" @@ -5610,25 +5629,6 @@ }, { "args": [ - "--enable-features=SingleProcessMash", - "--override-use-software-gl-for-tests", - "--test-launcher-print-test-stdio=always" - ], - "name": "single_process_mash_content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Ubuntu-14.04" - } - ], - "shards": 5 - }, - "test": "content_browsertests" - }, - { - "args": [ "--enable-features=VizDisplayCompositor", "--test-launcher-print-test-stdio=always" ], @@ -5663,10 +5663,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_content_unittests", + "name": "non_single_process_mash_content_unittests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5787,10 +5787,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_exo_unittests", + "name": "non_single_process_mash_exo_unittests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -5940,10 +5940,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_interactive_ui_tests", + "name": "non_single_process_mash_interactive_ui_tests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -6534,10 +6534,10 @@ }, { "args": [ - "--enable-features=SingleProcessMash", + "--disable-features=SingleProcessMash", "--test-launcher-print-test-stdio=always" ], - "name": "single_process_mash_unit_tests", + "name": "non_single_process_mash_unit_tests", "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter b/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter index 555a0a8c99..c987f6e 100644 --- a/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter +++ b/testing/buildbot/filters/chromeos.mash.fyi.interactive_ui_tests.filter
@@ -44,25 +44,9 @@ -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/0 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/1 -# TabDragging: crbug.com/890071 --TabDragging/DetachToBrowserTabDragControllerTest.DeleteBeforeStartedDragging/0 --TabDragging/DetachToBrowserTabDragControllerTest.DeleteBeforeStartedDragging/1 --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/0 --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/1 --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowWhileInImmersiveFullscreenMode/0 --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowWhileInImmersiveFullscreenMode/1 --TabDragging/DetachToBrowserTabDragControllerTest.DoNotObserveDraggedWidgetAfterDragEnds/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragAllToSeparateWindow/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragAllToSeparateWindow/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragAllToSeparateWindowAndCancel/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragAllToSeparateWindowAndCancel/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragToOverviewNewWindowItem/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragToOverviewWindow/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragToSeparateWindow/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragToSeparateWindow/1 --TabDragging/DetachToBrowserTabDragControllerTest.DragWithMaskedWindows/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragWithMaskedWindows/1 --TabDragging/DetachToBrowserTabDragControllerTestTouch.PressSecondFingerWhileDetached/0 +# TabDragging: https://crbug.com/890071 +-TabDragging/DetachToBrowserTabDragControllerTest.* +-TabDragging/DetachToBrowserTabDragControllerTestTouch.* # This test is flaky. https://crbug.com/897879 -ExtensionApiTest.DisplayModeWindowIsInFullscreen
diff --git a/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter b/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter index f7fdf85..15bd28a 100644 --- a/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter +++ b/testing/buildbot/filters/mac_window_server_killers.browser_tests.filter
@@ -64,6 +64,7 @@ -DeclarativeNetRequestBrowserTest.* -DeclarativeNetRequestHostPermissionsBrowserTest.* -DevToolsExtensionTest.* +-DevToolsManagerDelegateTest.* -DevToolsSanityTest.* -DeviceManagementServiceIntegrationTestInstance/DeviceManagementServiceIntegrationTest.* -DiceBrowserTest.* @@ -174,6 +175,7 @@ -PrefsFunctionalTest.* -PrefsTabHelperBrowserTest.* -PrerenderBrowserTest.* +-PresentationReceiverWindowViewBrowserTest.* -PrintBrowserTest.* -PrintPreviewDialogControllerBrowserTest.* -PrintPreviewSettingsSectionsTest.*
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 2cf7daea..b5572b16 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -957,6 +957,29 @@ }, }, }, + 'non_single_process_mash_browser_tests': { + 'modifications': { + # chromium.chromiumos + 'linux-chromeos-dbg': { + 'swarming': { + 'shards': 20, + }, + }, + # chromium.memory + 'Linux Chromium OS ASan LSan Tests (1)': { + # These are very slow on the ASAN trybot for some reason. + # crbug.com/794372 + 'swarming': { + 'shards': 30, + }, + }, + 'Linux ChromiumOS MSan Tests': { + 'swarming': { + 'shards': 20, + }, + }, + }, + }, 'not_site_per_process_webkit_layout_tests': { 'remove_from': [ # chromium.linux @@ -1024,29 +1047,6 @@ 'Linux MSan Tests', # https://crbug.com/831676 ], }, - 'single_process_mash_browser_tests': { - 'modifications': { - # chromium.chromiumos - 'linux-chromeos-dbg': { - 'swarming': { - 'shards': 20, - }, - }, - # chromium.memory - 'Linux Chromium OS ASan LSan Tests (1)': { - # These are very slow on the ASAN trybot for some reason. - # crbug.com/794372 - 'swarming': { - 'shards': 30, - }, - }, - 'Linux ChromiumOS MSan Tests': { - 'swarming': { - 'shards': 20, - }, - }, - }, - }, 'sizes': { 'remove_from': [ 'win32-dbg',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 272db5dd..1e492a4 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3508,57 +3508,57 @@ }, 'ozone_unittests': {}, 'ozone_x11_unittests': {}, - 'single_process_mash_ash_unittests': { + 'non_single_process_mash_ash_unittests': { 'test': 'ash_unittests', 'args': [ - '--enable-features=SingleProcessMash', + '--disable-features=SingleProcessMash', ], }, - 'single_process_mash_browser_tests': { + 'non_single_process_mash_browser_tests': { 'test': 'browser_tests', 'args': [ - '--enable-features=SingleProcessMash', + '--disable-features=SingleProcessMash', '--override-use-software-gl-for-tests' ], 'swarming': { 'shards': 10, }, }, - 'single_process_mash_content_unittests': { + 'non_single_process_mash_content_unittests': { 'test': 'content_unittests', 'args': [ - '--enable-features=SingleProcessMash', + '--disable-features=SingleProcessMash', ], }, - 'single_process_mash_content_browsertests': { + 'non_single_process_mash_content_browsertests': { 'test': 'content_browsertests', 'args': [ - '--enable-features=SingleProcessMash', + '--disable-features=SingleProcessMash', '--override-use-software-gl-for-tests' ], 'swarming': { 'shards': 5, }, }, - 'single_process_mash_exo_unittests': { + 'non_single_process_mash_exo_unittests': { 'test': 'exo_unittests', 'args': [ - '--enable-features=SingleProcessMash', + '--disable-features=SingleProcessMash', ], }, - 'single_process_mash_interactive_ui_tests': { + 'non_single_process_mash_interactive_ui_tests': { 'test': 'interactive_ui_tests', 'args': [ - '--enable-features=SingleProcessMash' + '--disable-features=SingleProcessMash' ], 'swarming': { 'shards': 3, }, }, - 'single_process_mash_unit_tests': { + 'non_single_process_mash_unit_tests': { 'test': 'unit_tests', 'args': [ - '--enable-features=SingleProcessMash' + '--disable-features=SingleProcessMash' ], }, 'ui_chromeos_unittests': {},
diff --git a/testing/libfuzzer/fuzzers/libxml_xml_read_memory_fuzzer.cc b/testing/libfuzzer/fuzzers/libxml_xml_read_memory_fuzzer.cc index 3c2589c..b90fbb5 100644 --- a/testing/libfuzzer/fuzzers/libxml_xml_read_memory_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/libxml_xml_read_memory_fuzzer.cc
@@ -33,7 +33,8 @@ const int options[] = {0, random_option}; for (const auto option_value : options) { - if (auto doc = xmlReadMemory(data_string.c_str(), data_string.length(), + // Intentionally pass raw data as the API does not require trailing \0. + if (auto doc = xmlReadMemory(reinterpret_cast<const char*>(data), size, "noname.xml", NULL, option_value)) { auto buffer = xmlBufferCreate(); assert(buffer);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 689ed65..683cd19f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1990,6 +1990,25 @@ ] } ], + "ForbidSyncXHRInPageDismissal": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ForbidSyncXHRInPageDismissal" + ] + } + ] + } + ], "FrameTypePriorityExperiment": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/media/controls/accessibility-volume-slider.html b/third_party/WebKit/LayoutTests/media/controls/accessibility-volume-slider.html new file mode 100644 index 0000000..f183a573 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/accessibility-volume-slider.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Media Controls: volume slider accessibility tests</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../media-controls.js"></script> +<video controls></video> +<script> +async_test(t => { + // Ensure that we will show the volume slider. + setPreferHiddenVolumeControlsForTest(t, false); + + assert_true(internals.runtimeFlags.accessibilityObjectModelEnabled); + + var video = document.querySelector('video'); + video.src = '../content/test.ogv'; + + video.onloadedmetadata = t.step(function() { + + var volume_slider = volumeSliderElement(video); + assert_not_equals(volume_slider, null); + + assert_equals(volume_slider.getAttribute('aria-label'), 'volume'); + assert_equals(volume_slider.getAttribute('aria-valuemin'), '0'); + assert_equals(volume_slider.getAttribute('aria-valuemax'), '100'); + assert_equals(volume_slider.getAttribute('aria-valuenow'), '100'); + + // Trigger events that will update the timeline internal state. + video.volume = 0.54; + video.onvolumechange = t.step_func_done(function(event) { + assert_equals(volume_slider.getAttribute('aria-valuenow'), '54'); + }); + }); +}); +</script>
diff --git a/third_party/accessibility_test_framework/proguard.flags b/third_party/accessibility_test_framework/proguard.flags index c6b5e18b8..f4b89f75 100644 --- a/third_party/accessibility_test_framework/proguard.flags +++ b/third_party/accessibility_test_framework/proguard.flags
@@ -1,2 +1 @@ -dontwarn com.google.protobuf.** --dontwarn com.google.android.apps.common.testing.accessibility.framework.proto.FrameworkProtos*
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 48096f1d..61549b7 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -137,6 +137,10 @@ const base::Feature kWritableFilesAPI{"WritableFilesAPI", base::FEATURE_DISABLED_BY_DEFAULT}; +// Allows for synchronous XHR requests during page dismissal +const base::Feature kForbidSyncXHRInPageDismissal{ + "ForbidSyncXHRInPageDismissal", base::FEATURE_DISABLED_BY_DEFAULT}; + const char kAutofillPreviewStyleExperimentBgColorParameterName[] = "bg_color"; const char kAutofillPreviewStyleExperimentColorParameterName[] = "color";
diff --git a/third_party/blink/common/font_unique_name_lookup/OWNERS b/third_party/blink/common/font_unique_name_lookup/OWNERS new file mode 100644 index 0000000..5819672 --- /dev/null +++ b/third_party/blink/common/font_unique_name_lookup/OWNERS
@@ -0,0 +1,3 @@ +drott@chromium.org + +# COMPONENT: Blink>Fonts
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 05f70bf..eba61f2 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -40,6 +40,7 @@ BLINK_COMMON_EXPORT extern const base::Feature kStopNonTimersInBackground; BLINK_COMMON_EXPORT extern const base::Feature kWasmCodeCache; BLINK_COMMON_EXPORT extern const base::Feature kWritableFilesAPI; +BLINK_COMMON_EXPORT extern const base::Feature kForbidSyncXHRInPageDismissal; BLINK_COMMON_EXPORT extern const char kAutofillPreviewStyleExperimentBgColorParameterName[];
diff --git a/third_party/blink/public/common/font_unique_name_lookup/OWNERS b/third_party/blink/public/common/font_unique_name_lookup/OWNERS new file mode 100644 index 0000000..9251fa1 --- /dev/null +++ b/third_party/blink/public/common/font_unique_name_lookup/OWNERS
@@ -0,0 +1,6 @@ +drott@chromium.org + +# COMPONENT: Blink>Fonts + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 82de52a3..eaa37cb 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2159,6 +2159,7 @@ kV8HTMLMediaElement_CanPlayType_Method = 2718, kHistoryLength = 2719, kFeaturePolicyReportOnlyHeader = 2720, + kV8PaymentRequest_HasEnrolledInstrument_Method = 2721, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 40ab6bc..d6dc342 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -220,6 +220,7 @@ BLINK_PLATFORM_EXPORT static void EnableTranslateService(bool); BLINK_PLATFORM_EXPORT static void EnableMergeBlockingNonBlockingPools(bool); BLINK_PLATFORM_EXPORT static void EnableGetDisplayMedia(bool); + BLINK_PLATFORM_EXPORT static void EnableForbidSyncXHRInPageDismissal(bool); private: WebRuntimeFeatures();
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index a5b05239..796219b 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -155,11 +155,6 @@ } return script; } - // TODO(v8:8252): Remove the default case once deprecated options are - // removed from v8::ScriptCompiler::CompileOptions. - default: - NOTREACHED(); - break; } // All switch branches should return and we should never get here.
diff --git a/third_party/blink/renderer/core/OWNERS b/third_party/blink/renderer/core/OWNERS index 18b45eb..5109981f5 100644 --- a/third_party/blink/renderer/core/OWNERS +++ b/third_party/blink/renderer/core/OWNERS
@@ -55,7 +55,7 @@ pkasting@chromium.org rego@igalia.com rbyers@chromium.org -rob.buis@samsung.com +rbuis@igalia.com robhogan@gmail.com schenney@chromium.org senorblanco@chromium.org
diff --git a/third_party/blink/renderer/core/display_lock/BUILD.gn b/third_party/blink/renderer/core/display_lock/BUILD.gn index 73e6b23..c0a8bc2 100644 --- a/third_party/blink/renderer/core/display_lock/BUILD.gn +++ b/third_party/blink/renderer/core/display_lock/BUILD.gn
@@ -14,6 +14,8 @@ "strict_yielding_display_lock_budget.h", "unyielding_display_lock_budget.cc", "unyielding_display_lock_budget.h", + "yielding_display_lock_budget.cc", + "yielding_display_lock_budget.h", ] public_deps = [
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc index 875829fa..d32b99b 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -8,13 +8,16 @@ #include "third_party/blink/renderer/core/display_lock/display_lock_context.h" #include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h" #include "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h" +#include "third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" namespace blink { class DisplayLockBudgetTest : public RenderingTest { + public: void SetUp() override { RenderingTest::SetUp(); features_backup_.emplace(); @@ -28,6 +31,10 @@ } } + double GetBudgetMs(const YieldingDisplayLockBudget& budget) const { + return budget.GetCurrentBudgetMs(); + } + private: base::Optional<RuntimeEnabledFeatures::Backup> features_backup_; }; @@ -257,4 +264,101 @@ // completing whenever necessary. EXPECT_FALSE(budget.NeedsLifecycleUpdates()); } + +TEST_F(DisplayLockBudgetTest, YieldingBudget) { + // Note that we're not testing the display lock here, just the budget so we + // can do minimal work to ensure we have a context, ignoring containment and + // other requirements. + SetBodyInnerHTML(R"HTML( + <div id="container"></div> + )HTML"); + + auto* element = GetDocument().getElementById("container"); + { + auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame()); + ScriptState::Scope scope(script_state); + element->getDisplayLockForBindings()->acquire(script_state, nullptr); + } + + ASSERT_TRUE(element->GetDisplayLockContext()); + YieldingDisplayLockBudget budget(element->GetDisplayLockContext()); + + WTF::ScopedMockClock clock; + + // Since the lifecycle is clean, we don't actually need any updates. + EXPECT_FALSE(budget.NeedsLifecycleUpdates()); + + // Dirtying the element will cause us to do updates. + element->GetLayoutObject()->SetNeedsLayout(""); + EXPECT_TRUE(budget.NeedsLifecycleUpdates()); + + budget.WillStartLifecycleUpdate(); + // Initially all of the phase checks should return true, since we don't know + // which phase the system wants to process next. + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Not doing anything should ensure that we schedule another animation by + // returning true here. + EXPECT_TRUE(budget.NeedsLifecycleUpdates()); + + // Advancing the clock a bit will make us still want to the phases. + clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) / 2)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // However, once we're out of budget, we will not do anything. + clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget))); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Starting a new lifecycle will reset the budget. + budget.WillStartLifecycleUpdate(); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Performing a phase still keeps the rest of the phases available for work + // since we haven't advanced the clock. + budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Now that we're out of budget, phases performed previously should remain + // true. + clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Sanity check here: the element still needs layout. + EXPECT_TRUE(budget.NeedsLifecycleUpdates()); + + // Resetting the budget, and advnacing again should yield the same results as + // before. + budget.WillStartLifecycleUpdate(); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + clock.Advance(TimeDelta::FromMillisecondsD(GetBudgetMs(budget) * 2)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + + // Eventually the budget becomes essentially infinite. + for (int i = 0; i < 60; ++i) + budget.WillStartLifecycleUpdate(); + + EXPECT_GT(GetBudgetMs(budget), 1e6); + for (int i = 0; i < 60; ++i) { + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout)); + EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint)); + clock.Advance(TimeDelta::FromMillisecondsD(10000)); + } +} } // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 5e631a67..932c9f8 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/display_lock/display_lock_options.h" #include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h" #include "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h" +#include "third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -81,6 +82,7 @@ // going to be disposed. FinishUpdateResolver(kDetach); FinishCommitResolver(kDetach); + CancelTimeoutTask(); state_ = kUnlocked; if (element_ && element_->GetDocument().View()) @@ -139,8 +141,8 @@ } ScriptPromise DisplayLockContext::update(ScriptState* script_state) { - // Reject if we're unlocked. - if (state_ == kUnlocked) + // Reject if we're unlocked or disconnected. + if (state_ == kUnlocked || !element_->isConnected()) return GetRejectedPromise(script_state); // If we have a resolver, then we're at least updating already, just return @@ -151,10 +153,7 @@ } update_resolver_ = ScriptPromiseResolver::Create(script_state); - // We only need to kick off an Update if we're in a locked state, all other - // states are already updating. - if (state_ == kLocked) - StartUpdate(); + StartUpdateIfNeeded(); return update_resolver_->Promise(); } @@ -180,8 +179,9 @@ // of the promises. DCHECK_NE(state_, kCommitting); commit_resolver_ = ScriptPromiseResolver::Create(script_state); + auto promise = commit_resolver_->Promise(); StartCommit(); - return commit_resolver_->Promise(); + return promise; } void DisplayLockContext::FinishUpdateResolver(ResolverState state) { @@ -354,6 +354,19 @@ } void DisplayLockContext::StartCommit() { + // If we don't have an element or we're not connected, then the process of + // committing is the same as just unlocking the element. + if (!element_ || !element_->isConnected()) { + state_ = kUnlocked; + update_budget_.reset(); + FinishUpdateResolver(kReject); + // TODO(vmpstr): Should we resolve here? What's the path to unlocking an + // element without connecting it (i.e. acquire the lock, then change your + // mind). + FinishCommitResolver(kReject); + return; + } + DCHECK_LT(state_, kCommitting); if (state_ != kUpdating) ScheduleAnimation(); @@ -391,12 +404,19 @@ layout_invalidation_reason::kDisplayLockCommitting); } -void DisplayLockContext::StartUpdate() { - DCHECK_EQ(state_, kLocked); - state_ = kUpdating; +void DisplayLockContext::StartUpdateIfNeeded() { + // We should not be calling this if we're unlocked. + DCHECK_NE(state_, kUnlocked); + // Any state other than kLocked means that we are already in the process of + // updating/committing, so we can piggy back on that process without kicking + // off any new updates. + if (state_ != kLocked) + return; + // We don't need to mark anything dirty since the budget will take care of // that for us. update_budget_ = CreateNewBudget(); + state_ = kUpdating; ScheduleAnimation(); } @@ -407,8 +427,7 @@ case BudgetType::kStrictYieldBetweenLifecyclePhases: return base::WrapUnique(new StrictYieldingDisplayLockBudget(this)); case BudgetType::kYieldBetweenLifecyclePhases: - NOTIMPLEMENTED(); - return nullptr; + return base::WrapUnique(new YieldingDisplayLockBudget(this)); } NOTREACHED(); return nullptr; @@ -486,6 +505,7 @@ if (state_ == kCommitting) { FinishUpdateResolver(kResolve); FinishCommitResolver(kResolve); + CancelTimeoutTask(); state_ = kUnlocked; return; } @@ -493,6 +513,15 @@ if (state_ != kUpdating) return; + // If we became disconnected for any reason, then we should reject the + // update promise and go back to the locked state. + if (!element_ || !element_->isConnected()) { + FinishUpdateResolver(kReject); + update_budget_.reset(); + state_ = kLocked; + return; + } + if (update_budget_->NeedsLifecycleUpdates()) { // Note that we post a task to schedule an animation, since rAF requests can // be ignored if they happen from within a lifecycle update. @@ -509,6 +538,8 @@ } void DisplayLockContext::ScheduleAnimation() { + DCHECK(element_->isConnected()); + // Schedule an animation to perform the lifecycle phases. element_->GetDocument().GetPage()->Animator().ScheduleVisualUpdate( element_->GetDocument().GetFrame()); @@ -539,8 +570,7 @@ } void DisplayLockContext::TriggerTimeout() { - if (element_ && state_ < kCommitting) - StartCommit(); + StartCommit(); timeout_task_is_scheduled_ = false; }
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index b8956f9..4bd5eb3 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -46,7 +46,7 @@ kDoNotYield, kStrictYieldBetweenLifecyclePhases, kYieldBetweenLifecyclePhases, - kDefault = kDoNotYield + kDefault = kYieldBetweenLifecyclePhases }; // See GetScopedPendingFrameRect() for description. @@ -149,7 +149,7 @@ // Initiate a commit. void StartCommit(); // Initiate an update. - void StartUpdate(); + void StartUpdateIfNeeded(); // The following functions propagate dirty bits from the locked element up to // the ancestors in order to be reached. They return true if the element or
diff --git a/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc new file mode 100644 index 0000000..c41dcc5 --- /dev/null +++ b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.cc
@@ -0,0 +1,89 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h" + +#include "third_party/blink/renderer/platform/wtf/time.h" + +#include <algorithm> + +namespace blink { + +YieldingDisplayLockBudget::YieldingDisplayLockBudget( + DisplayLockContext* context) + : DisplayLockBudget(context) {} + +bool YieldingDisplayLockBudget::ShouldPerformPhase(Phase phase) const { + // We should perform any phase earlier than the one we already completed. + if (last_completed_phase_ && phase <= *last_completed_phase_) + return true; + + // Otherwise, we can still do work while we're not past the deadline. + return CurrentTimeTicks() < deadline_; +} + +void YieldingDisplayLockBudget::DidPerformPhase(Phase phase) { + if (!last_completed_phase_ || phase > *last_completed_phase_) + last_completed_phase_ = phase; +} + +void YieldingDisplayLockBudget::WillStartLifecycleUpdate() { + ++lifecycle_count_; + deadline_ = + CurrentTimeTicks() + TimeDelta::FromMillisecondsD(GetCurrentBudgetMs()); + + // Figure out the next phase we would run. If we had completed a phase before, + // then we should try to complete the next one, otherwise we'll start with the + // first phase. + Phase next_phase = + last_completed_phase_ + ? static_cast<Phase>( + std::min(static_cast<unsigned>(*last_completed_phase_) + 1, + static_cast<unsigned>(Phase::kLast))) + : Phase::kFirst; + + // Mark the next phase we're scheduled to run. + for (auto phase = static_cast<unsigned>(next_phase); + phase <= static_cast<unsigned>(Phase::kLast); ++phase) { + if (MarkAncestorsDirtyForPhaseIfNeeded(static_cast<Phase>(phase))) + break; + } +} + +bool YieldingDisplayLockBudget::NeedsLifecycleUpdates() const { + if (last_completed_phase_ && *last_completed_phase_ == Phase::kLast) + return false; + + auto next_phase = last_completed_phase_ + ? static_cast<Phase>( + static_cast<unsigned>(*last_completed_phase_) + 1) + : Phase::kFirst; + // Check if any future phase needs updates. + for (auto phase = static_cast<unsigned>(next_phase); + phase <= static_cast<unsigned>(Phase::kLast); ++phase) { + if (IsElementDirtyForPhase(static_cast<Phase>(phase))) + return true; + } + return false; +} + +double YieldingDisplayLockBudget::GetCurrentBudgetMs() const { + if (TimeTicks::IsHighResolution()) { + if (lifecycle_count_ < 3) + return 4.; + if (lifecycle_count_ < 10) + return 8.; + if (lifecycle_count_ < 60) + return 16.; + } else { + // Without a high resolution clock, the resolution can be as bad as 15ms, so + // increase the budgets accordingly to ensure we don't abort before doing + // any phases. + if (lifecycle_count_ < 60) + return 16.; + } + return 1e9; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h new file mode 100644 index 0000000..41a7d18 --- /dev/null +++ b/third_party/blink/renderer/core/display_lock/yielding_display_lock_budget.h
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_YIELDING_DISPLAY_LOCK_BUDGET_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_YIELDING_DISPLAY_LOCK_BUDGET_H_ + +#include "base/optional.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h" +#include "third_party/blink/renderer/platform/wtf/time.h" + +namespace blink { + +// This budget yields between lifecycle phases even if that phase is quick. In +// other words, it will only do one new lifecycle phase at a time, and block the +// future ones. Any lifecycle phases that have already been allowed by this +// budget in the past are not blocked. +class CORE_EXPORT YieldingDisplayLockBudget final : public DisplayLockBudget { + public: + YieldingDisplayLockBudget(DisplayLockContext*); + ~YieldingDisplayLockBudget() override = default; + + bool ShouldPerformPhase(Phase) const override; + void DidPerformPhase(Phase) override; + void WillStartLifecycleUpdate() override; + // Returns true if any of the lifecycles that have been previously blocked by + // this budget need updates. Note that this does not check lifecycle phases + // that have already completed by this budget even if they are now dirty + // again. This is done to prevent starvation (ie, it is possible for the + // budget to always schedule more work if something in rAF keeps dirtying + // layout, for example). + bool NeedsLifecycleUpdates() const override; + + protected: + friend class DisplayLockBudgetTest; + + double GetCurrentBudgetMs() const; + + int lifecycle_count_ = 0; + TimeTicks deadline_; + base::Optional<Phase> last_completed_phase_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_YIELDING_DISPLAY_LOCK_BUDGET_H_
diff --git a/third_party/blink/renderer/core/inspector/InspectorOverlayPage.html b/third_party/blink/renderer/core/inspector/InspectorOverlayPage.html index 0122dc5..27e8e59 100644 --- a/third_party/blink/renderer/core/inspector/InspectorOverlayPage.html +++ b/third_party/blink/renderer/core/inspector/InspectorOverlayPage.html
@@ -546,24 +546,47 @@ function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow) { - var tooltipContainer = parentElement.createChild("div"); - var tooltipContent = tooltipContainer.createChild("div", "tooltip-content"); + const tooltipContainer = parentElement.createChild("div"); + const tooltipContent = tooltipContainer.createChild("div", "tooltip-content"); tooltipContent.appendChild(contentElement); - var titleWidth = tooltipContent.offsetWidth; - var titleHeight = tooltipContent.offsetHeight; - var arrowRadius = 8; - var pageMargin = 2; + const titleWidth = tooltipContent.offsetWidth; + const titleHeight = tooltipContent.offsetHeight; + const arrowHalfWidth = 8; + const pageMargin = 2; + const arrowWidth = arrowHalfWidth * 2; + const arrowInset = arrowHalfWidth + 2; - var boxX = Math.min(bounds.minX, canvasWidth - titleWidth - pageMargin); + const containerMinX = pageMargin + arrowInset; + const containerMaxX = canvasWidth - pageMargin - arrowInset - arrowWidth; - var boxY = bounds.minY - arrowRadius - titleHeight; - var onTop = true; + // Left align arrow to the tooltip but ensure it is pointing to the element. + // Center align arrow if the inspected element bounds are too narrow. + const boundsAreTooNarrow = bounds.maxX - bounds.minX < arrowWidth + 2 * arrowInset; + let arrowX; + if (boundsAreTooNarrow) { + arrowX = (bounds.minX + bounds.maxX) * 0.5 - arrowHalfWidth; + } else { + const xFromLeftBound = bounds.minX + arrowInset; + const xFromRightBound = bounds.maxX - arrowInset - arrowWidth; + if (xFromLeftBound > containerMinX && xFromLeftBound < containerMaxX) + arrowX = xFromLeftBound; + else + arrowX = Number.constrain(containerMinX, xFromLeftBound, xFromRightBound); + } + // Hide arrow if element is completely off the sides of the page. + const arrowHidden = arrowX < containerMinX || arrowX > containerMaxX; + + let boxX = arrowX - arrowInset; + boxX = Number.constrain(boxX, pageMargin, canvasWidth - titleWidth - pageMargin); + + let boxY = bounds.minY - arrowHalfWidth - titleHeight; + let onTop = true; if (boxY < 0) { - boxY = Math.min(canvasHeight - titleHeight, bounds.maxY + arrowRadius); + boxY = Math.min(canvasHeight - titleHeight, bounds.maxY + arrowHalfWidth); onTop = false; } else if (bounds.minY > canvasHeight) { - boxY = canvasHeight - arrowRadius - titleHeight; + boxY = canvasHeight - arrowHalfWidth - titleHeight; } tooltipContent.style.top = boxY + "px"; @@ -571,18 +594,11 @@ if (!withArrow) return; - var tooltipArrow = tooltipContainer.createChild("div", "material-tooltip-arrow"); - // Left align arrow to the tooltip but ensure it is pointing to the element. - var tooltipBorderRadius = 2; - var arrowX = boxX + arrowRadius + tooltipBorderRadius; - if (arrowX < bounds.minX) - arrowX = bounds.minX + arrowRadius; - // Hide arrow if element is completely off the sides of the page. - var arrowHidden = arrowX < pageMargin + tooltipBorderRadius || arrowX + arrowRadius * 2 > canvasWidth - pageMargin - tooltipBorderRadius; + const tooltipArrow = tooltipContainer.createChild("div", "material-tooltip-arrow"); tooltipArrow.classList.toggle("hidden", arrowHidden); if (!arrowHidden) { tooltipArrow.classList.toggle("tooltip-arrow-top", onTop); - tooltipArrow.style.top = (onTop ? boxY + titleHeight : boxY - arrowRadius) + "px"; + tooltipArrow.style.top = (onTop ? boxY + titleHeight : boxY - arrowHalfWidth) + "px"; tooltipArrow.style.left = arrowX + "px"; } } @@ -910,6 +926,20 @@ return this.substr(0, maxLength - 1) + "\u2026"; } +/** + * @param {number} num + * @param {number} min + * @param {number} max + * @return {number} + */ + Number.constrain = function(num, min, max) { + if (num < min) + num = min; + else if (num > max) + num = max; + return num; +}; + window.addEventListener("DOMContentLoaded", onLoaded); document.addEventListener("keydown", onDocumentKeyDown); </script>
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 60c3aa3..fecc1dc2 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -3058,6 +3058,10 @@ optional number deltaX # Y delta in CSS pixels for mouse wheel event (default: 0). optional number deltaY + # Pointer type (default: "mouse"). + optional enum pointerType + mouse + pen # Dispatches a touch event to the page. command dispatchTouchEvent
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 9461cb1..ec37fc3b 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -352,10 +352,6 @@ return "code"; case v8::ScriptCompiler::kEagerCompile: return "full code"; - // TODO(v8:8252): Remove the default branch once deprecated options are - // removed from v8::ScriptCompiler::CompileOptions. - default: - NOTREACHED(); } NOTREACHED(); return "";
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc index f006da1..996bd3f 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc +++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -1461,45 +1461,4 @@ last_set_worked_on_ = state.ColumnSet(); } -unsigned LayoutMultiColumnFlowThread::CalculateActualColumnCountAllowance() - const { - // To avoid performance problems, limit the maximum number of columns. Try to - // identify legitimate reasons for creating many columns, and allow many - // columns in such cases. The amount of "content" will determine the - // allowance. - unsigned allowance = 0; - - // This isn't a particularly clever algorithm. For example, we don't account - // for parallel flows (absolute positioning, floats, visible overflow, table - // cells, flex items). We just generously add everything together. - for (const LayoutObject* descendant = this; descendant;) { - bool examine_children = false; - if (descendant->IsBox() && !descendant->IsInline() && - !ToLayoutBox(descendant)->IsWritingModeRoot()) { - // Give one point to any kind of block level content. - allowance++; - if (descendant->IsLayoutBlockFlow() && descendant->ChildrenInline()) { - // It's a block-level block container in the same writing mode, and it - // has inline children. Count the lines and add it to the allowance. - allowance += ToLayoutBlockFlow(descendant)->LineCount(); - } else { - // We could examine other types of layout modes (tables, flexbox, etc.) - // as well, but then again, that might be overkill. Just enter and see - // what we find. - examine_children = true; - } - } - - if (allowance >= ColumnCountClampMax()) - return ColumnCountClampMax(); - - descendant = examine_children - ? descendant->NextInPreOrder(this) - : descendant->NextInPreOrderAfterChildren(this); - } - - DCHECK_LE(allowance, ColumnCountClampMax()); - return std::max(allowance, ColumnCountClampMin()); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h index 6b5e654..697e426 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h +++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h
@@ -190,18 +190,6 @@ unsigned ColumnCount() const { return column_count_; } - // Calculate and return the actual column count allowance. This method should - // only be called when we ended up with an actual column count larger than - // ColumnCountClampMin() in some fragmentainer group. - unsigned CalculateActualColumnCountAllowance() const; - - // Any actual column count value lower than this will be allowed - // unconditionally. - static unsigned ColumnCountClampMin() { return 10; } - - // The maximum actual column count we're going to allow. - static unsigned ColumnCountClampMax() { return 2000; } - // Total height available to columns and spanners. This is the multicol // container's content box logical height, or 0 if auto. LayoutUnit ColumnHeightAvailable() const { return column_height_available_; }
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc index 70fbce4..a5e8c94 100644 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc +++ b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
@@ -10,6 +10,15 @@ namespace blink { +// Limit the maximum column count, to prevent potential performance problems. +static const unsigned kColumnCountClampMax = 10000; + +// Clamp "infinite" clips to a number of pixels that can be losslessly +// converted to and from floating point, to avoid loss of precision. +// Note that tables have something similar, see +// TableLayoutAlgorithm::kTableMaxWidth. +static const int kMulticolMaxClipPixels = 1000000; + MultiColumnFragmentainerGroup::MultiColumnFragmentainerGroup( const LayoutMultiColumnSet& column_set) : column_set_(column_set) {} @@ -62,7 +71,6 @@ } void MultiColumnFragmentainerGroup::ResetColumnHeight() { - actual_column_count_allowance_ = 0; max_logical_height_ = CalculateMaxColumnHeight(); LayoutMultiColumnFlowThread* flow_thread = @@ -138,24 +146,6 @@ // height. is_logical_height_known_ = true; - unsigned column_count = UnclampedActualColumnCount(); - if (column_count > LayoutMultiColumnFlowThread::ColumnCountClampMax() || - (column_count > LayoutMultiColumnFlowThread::ColumnCountClampMin() && - column_count > column_set_.UsedColumnCount())) { - // That's a lot of columns! We have either exceeded the maximum value, or we - // have overflowing columns, and the proposed count is within clamping - // range. Calculate allowance to make sure we have a legitimate reason for - // it, or else clamp it. We have quadratic performance complexity for - // painting columns. - if (!actual_column_count_allowance_) { - const auto* flow_thread = column_set_.MultiColumnFlowThread(); - unsigned allowance = flow_thread->CalculateActualColumnCountAllowance(); - DCHECK_GE(allowance, LayoutMultiColumnFlowThread::ColumnCountClampMin()); - DCHECK_LE(allowance, LayoutMultiColumnFlowThread::ColumnCountClampMax()); - actual_column_count_allowance_ = allowance; - } - } - if (logical_height_ == old_column_height) return false; // No change. We're done. @@ -329,8 +319,7 @@ unsigned MultiColumnFragmentainerGroup::ActualColumnCount() const { unsigned count = UnclampedActualColumnCount(); - if (actual_column_count_allowance_) - count = std::min(count, actual_column_count_allowance_); + count = std::min(count, kColumnCountClampMax); DCHECK_GE(count, 1u); return count; } @@ -453,12 +442,6 @@ column_set_.PageLogicalWidth()); } -// Clamp "infinite" clips to a number of pixels that can be losslessly -// converted to and from floating point, to avoid loss of precision. -// Note that tables have something similar, see -// TableLayoutAlgorithm::kTableMaxWidth. -static const int kMulticolMaxClipPixels = 1000000; - LayoutRect MultiColumnFragmentainerGroup::FlowThreadPortionOverflowRectAt( unsigned column_index) const { // This function determines the portion of the flow thread that paints for the
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h index 7252791..f5f0483c 100644 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h +++ b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
@@ -194,8 +194,6 @@ // Maximum logical height allowed. LayoutUnit max_logical_height_; - unsigned actual_column_count_allowance_ = 0; - bool is_logical_height_known_ = false; };
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc index 1d9420fa..f86cb314 100644 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc +++ b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc
@@ -97,32 +97,6 @@ EXPECT_EQ(GroupCount(group_list), 1); } -// The following test tests that we restrict actual column count, to not run -// into unnecessary performance problems. The code that applies this limitation -// is in MultiColumnFragmentainerGroup::ActualColumnCount(). -TEST_F(MultiColumnFragmentainerGroupTest, TallEmptyContent) { - SetBodyInnerHTML(R"HTML( - <div id="multicol" style="columns:3; column-gap:1px; width:101px; line-height:50px; height:200px;"> - <div style="height:1000000px;"></div> - </div> - )HTML"); - const auto* multicol = GetLayoutObjectByElementId("multicol"); - ASSERT_TRUE(multicol); - ASSERT_TRUE(multicol->IsLayoutBlockFlow()); - const auto* column_set = multicol->SlowLastChild(); - ASSERT_TRUE(column_set); - ASSERT_TRUE(column_set->IsLayoutMultiColumnSet()); - const auto& fragmentainer_group = - ToLayoutMultiColumnSet(column_set)->FirstFragmentainerGroup(); - EXPECT_EQ(fragmentainer_group.ActualColumnCount(), 10U); - EXPECT_EQ(fragmentainer_group.GroupLogicalHeight(), LayoutUnit(200)); - auto overflow = ToLayoutBox(multicol)->LayoutOverflowRect(); - EXPECT_EQ(ToLayoutBox(multicol)->LogicalWidth(), LayoutUnit(101)); - EXPECT_EQ(ToLayoutBox(multicol)->LogicalHeight(), LayoutUnit(200)); - EXPECT_EQ(overflow.Width(), LayoutUnit(339)); - EXPECT_EQ(overflow.Height(), LayoutUnit(998200)); -} - // The following test tests that we DON'T restrict actual column count, when // there's a legitimate reason to use many columns. The code that checks the // allowance and potentially applies this limitation is in
diff --git a/third_party/blink/renderer/core/paint/block_painter.cc b/third_party/blink/renderer/core/paint/block_painter.cc index a794330..8f261054 100644 --- a/third_party/blink/renderer/core/paint/block_painter.cc +++ b/third_party/blink/renderer/core/paint/block_painter.cc
@@ -106,22 +106,12 @@ layout_block_.PaintObject(local_paint_info, paint_offset); } - // Our scrollbar widgets paint exactly when we tell them to, so that they work - // properly with z-index. We paint after we painted the background/border, so - // that the scrollbars will sit above the background/border. + // We paint scrollbars after we painted the other things, so that the + // scrollbars will sit above them. local_paint_info.phase = original_phase; - PaintOverflowControlsIfNeeded(local_paint_info, paint_offset); -} - -void BlockPainter::PaintOverflowControlsIfNeeded( - const PaintInfo& paint_info, - const LayoutPoint& paint_offset) { - if (layout_block_.HasOverflowClip() && - layout_block_.StyleRef().Visibility() == EVisibility::kVisible && - ShouldPaintSelfBlockBackground(paint_info.phase)) { - ScrollableAreaPainter(*layout_block_.Layer()->GetScrollableArea()) - .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset), - false /* painting_overlay_controls */); + if (auto* scrollable_area = layout_block_.GetScrollableArea()) { + ScrollableAreaPainter(*scrollable_area) + .PaintOverflowControls(local_paint_info, RoundedIntPoint(paint_offset)); } }
diff --git a/third_party/blink/renderer/core/paint/block_painter.h b/third_party/blink/renderer/core/paint/block_painter.h index e16f0be..7fe1e38 100644 --- a/third_party/blink/renderer/core/paint/block_painter.h +++ b/third_party/blink/renderer/core/paint/block_painter.h
@@ -28,8 +28,6 @@ void PaintContents(const PaintInfo&, const LayoutPoint& paint_offset); void PaintChildren(const PaintInfo&); void PaintChild(const LayoutBox&, const PaintInfo&); - void PaintOverflowControlsIfNeeded(const PaintInfo&, - const LayoutPoint& paint_offset); // See ObjectPainter::PaintAllPhasesAtomically(). void PaintAllChildPhasesAtomically(const LayoutBox&, const PaintInfo&);
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 55f34d8e..8423165 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -3128,13 +3128,6 @@ paint_info.paint_layer->SubpixelAccumulation()); PaintLayerPainter(*paint_info.paint_layer) .PaintLayerContents(context, painting_info, paint_layer_flags); - - if (paint_info.paint_layer->ContainsDirtyOverlayScrollbars()) { - PaintLayerPainter(*paint_info.paint_layer) - .PaintLayerContents( - context, painting_info, - paint_layer_flags | kPaintLayerPaintingOverlayScrollbars); - } } else { PaintLayerPaintingInfo painting_info( paint_info.paint_layer, CullRect(dirty_rect), kGlobalPaintNormalPhase,
diff --git a/third_party/blink/renderer/core/paint/frame_painter.cc b/third_party/blink/renderer/core/paint/frame_painter.cc index 38b39e3d..f2bc7e39 100644 --- a/third_party/blink/renderer/core/paint/frame_painter.cc +++ b/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -104,11 +104,6 @@ layer_painter.Paint(context, cull_rect, updated_global_paint_flags, root_layer_paint_flags); - if (root_layer->ContainsDirtyOverlayScrollbars()) { - layer_painter.PaintOverlayScrollbars(context, cull_rect, - updated_global_paint_flags); - } - // Regions may have changed as a result of the visibility/z-index of element // changing. if (document->AnnotatedRegionsDirty())
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 0390581..6efef55 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -192,11 +192,13 @@ PaintObject(info, paint_offset); } - // Our scrollbar widgets paint exactly when we tell them to, so that they work - // properly with z-index. We paint after we painted the background/border, so - // that the scrollbars will sit above the background/border. + // We paint scrollbars after we painted other things, so that the scrollbars + // will sit above them. info.phase = original_phase; - PaintOverflowControlsIfNeeded(info, paint_offset); + if (box_fragment_.HasOverflowClip()) { + ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea()) + .PaintOverflowControls(info, RoundedIntPoint(paint_offset)); + } } void NGBoxFragmentPainter::RecordHitTestData(const PaintInfo& paint_info, @@ -851,19 +853,6 @@ box_fragment_.GetLayoutObject() == paint_info.PaintContainer(); } -// Clone of BlockPainter::PaintOverflowControlsIfNeeded -void NGBoxFragmentPainter::PaintOverflowControlsIfNeeded( - const PaintInfo& paint_info, - const LayoutPoint& paint_offset) { - if (box_fragment_.HasOverflowClip() && - box_fragment_.Style().Visibility() == EVisibility::kVisible && - ShouldPaintSelfBlockBackground(paint_info.phase)) { - ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea()) - .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset), - false /* painting_overlay_controls */); - } -} - bool NGBoxFragmentPainter::ShouldPaint( const ScopedPaintState& paint_state) const { // TODO(layout-dev): Add support for scrolling, see BlockPainter::ShouldPaint.
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h index d2887ee..061d6b94 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -99,8 +99,6 @@ void PaintFloatingChildren(NGPaintFragment::ChildList, const PaintInfo&); void PaintFloats(const PaintInfo&); void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset); - void PaintOverflowControlsIfNeeded(const PaintInfo&, - const LayoutPoint& paint_offset); void PaintAtomicInline(const PaintInfo&); void PaintBackground(const PaintInfo&, const LayoutRect&,
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 4a65163..68e58825 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -148,7 +148,6 @@ needs_position_update_(!IsRootLayer()), #endif has3d_transformed_descendant_(false), - contains_dirty_overlay_scrollbars_(false), needs_ancestor_dependent_compositing_inputs_update_( !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()), child_needs_compositing_inputs_update_(
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 8467c06..b2f4f9f6 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -594,13 +594,6 @@ bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&, bool should_check_children) const; - bool ContainsDirtyOverlayScrollbars() const { - return contains_dirty_overlay_scrollbars_; - } - void SetContainsDirtyOverlayScrollbars(bool dirty_scrollbars) { - contains_dirty_overlay_scrollbars_ = dirty_scrollbars; - } - // If the input CompositorFilterOperation is not empty, it will be populated // only if |filter_on_effect_node_dirty_| is true or the reference box has // changed. Otherwise it will be populated unconditionally. @@ -1270,8 +1263,6 @@ // in a preserves3D hierarchy. Hint to do 3D-aware hit testing. unsigned has3d_transformed_descendant_ : 1; - unsigned contains_dirty_overlay_scrollbars_ : 1; - unsigned needs_ancestor_dependent_compositing_inputs_update_ : 1; unsigned child_needs_compositing_inputs_update_ : 1;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc index fddbe89..2f6e4bc 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -181,8 +181,7 @@ if (painting_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers) return false; - if (paint_flags & - (kPaintLayerPaintingOverlayScrollbars | kPaintLayerUncachedClipRects)) + if (paint_flags & kPaintLayerUncachedClipRects) return false; // When in FOUC-avoidance mode, don't cache any subsequences, to avoid having @@ -372,8 +371,6 @@ AdjustForPaintProperties(context, painting_info, paint_flags); bool is_self_painting_layer = paint_layer_.IsSelfPaintingLayer(); - bool is_painting_overlay_scrollbars = - paint_flags & kPaintLayerPaintingOverlayScrollbars; bool is_painting_scrolling_content = paint_flags & kPaintLayerPaintingCompositingScrollingPhase; bool is_painting_composited_foreground = @@ -390,7 +387,7 @@ // It is painted as part of the decoration phase which paints content that // is not scrolled and should be above scrolled content. bool should_paint_self_outline = - is_self_painting_layer && !is_painting_overlay_scrollbars && + is_self_painting_layer && (is_painting_composited_decoration || (!is_painting_overflow_contents && !is_painting_mask)) && paint_layer_.GetLayoutObject().StyleRef().HasOutline(); @@ -449,13 +446,11 @@ // Content under a LayoutSVGHiddenContainer is auxiliary resources for // painting. Foreign content should never paint in this situation, as it // is primary, not auxiliary. - !paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer && - !is_painting_overlay_scrollbars; + !paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer; PaintLayerFragments layer_fragments; - if (should_paint_content || should_paint_self_outline || - is_painting_overlay_scrollbars) { + if (should_paint_content || should_paint_self_outline) { // Collect the fragments. This will compute the clip rectangles and paint // offsets for each layer fragment. LayoutPoint offset_to_clipper; @@ -532,7 +527,6 @@ is_painting_composited_foreground && should_paint_content; bool should_paint_normal_flow_and_pos_z_order_lists = is_painting_composited_foreground; - bool should_paint_overlay_scrollbars = is_painting_overlay_scrollbars; base::Optional<ScopedPaintChunkProperties> subsequence_forced_chunk_properties; @@ -590,12 +584,7 @@ result = kMayBeClippedByCullRect; } - if (should_paint_overlay_scrollbars) { - PaintOverflowControlsForFragments(layer_fragments, context, - local_painting_info, paint_flags); - } - - if (!is_painting_overlay_scrollbars && paint_layer_.PaintsWithFilters() && + if (paint_layer_.PaintsWithFilters() && display_item_list_size_before_painting == context.GetPaintController().NewDisplayItemList().size()) { // If a layer with filters painted nothing, we need to issue a no-op @@ -735,42 +724,6 @@ return result; } -void PaintLayerPainter::PaintOverflowControlsForFragments( - const PaintLayerFragments& layer_fragments, - GraphicsContext& context, - const PaintLayerPaintingInfo& painting_info, - PaintLayerFlags paint_flags) { - PaintLayerScrollableArea* scrollable_area = paint_layer_.GetScrollableArea(); - if (!scrollable_area) - return; - - ForAllFragments( - context, layer_fragments, [&](const PaintLayerFragment& fragment) { - ScopedPaintChunkProperties fragment_paint_chunk_properties( - context.GetPaintController(), - fragment.fragment_data->LocalBorderBoxProperties(), paint_layer_, - DisplayItem::kOverflowControls); - - // We need to apply the same clips and transforms that - // paintFragmentWithPhase would have. - LayoutRect cull_rect = fragment.background_rect.Rect(); - PaintInfo paint_info( - context, PixelSnappedIntRect(cull_rect), - PaintPhase::kSelfBlockBackgroundOnly, - painting_info.GetGlobalPaintFlags(), paint_flags, - &painting_info.root_layer->GetLayoutObject(), - fragment.fragment_data - ? fragment.fragment_data->LogicalTopInFlowThread() - : LayoutUnit()); - // We pass IntPoint() as the paint offset here, because - // ScrollableArea::paintOverflowControls just ignores it and uses the - // offset found in a previous pass. - ScrollableAreaPainter(*scrollable_area) - .PaintOverflowControls(paint_info, IntPoint(), - true /* painting_overlay_controls */); - }); -} - void PaintLayerPainter::PaintFragmentWithPhase( PaintPhase phase, const PaintLayerFragment& fragment, @@ -974,20 +927,6 @@ }); } -void PaintLayerPainter::PaintOverlayScrollbars( - GraphicsContext& context, - const CullRect& cull_rect, - const GlobalPaintFlags paint_flags) { - if (!paint_layer_.ContainsDirtyOverlayScrollbars()) - return; - - PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, paint_flags, - LayoutSize()); - Paint(context, painting_info, kPaintLayerPaintingOverlayScrollbars); - - paint_layer_.SetContainsDirtyOverlayScrollbars(false); -} - void PaintLayerPainter::FillMaskingFragment(GraphicsContext& context, const ClipRect& clip_rect, const DisplayItemClient& client) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.h b/third_party/blink/renderer/core/paint/paint_layer_painter.h index 4c39e00..ac6d603 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.h +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -49,10 +49,6 @@ const PaintLayerPaintingInfo&, PaintLayerFlags); - void PaintOverlayScrollbars(GraphicsContext&, - const CullRect&, - const GlobalPaintFlags); - // Returns true if the painted output of this PaintLayer and its children is // invisible and therefore can't impact painted output. bool PaintedOutputInvisible(const ComputedStyle&, @@ -96,10 +92,6 @@ GraphicsContext&, const PaintLayerPaintingInfo&, PaintLayerFlags); - void PaintOverflowControlsForFragments(const PaintLayerFragments&, - GraphicsContext&, - const PaintLayerPaintingInfo&, - PaintLayerFlags); void PaintMaskForFragments(const PaintLayerFragments&, GraphicsContext&, const PaintLayerPaintingInfo&,
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painting_info.h b/third_party/blink/renderer/core/paint/paint_layer_painting_info.h index bee6fa8e..eecbf5e 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painting_info.h +++ b/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
@@ -63,7 +63,6 @@ kPaintLayerNoFlag = 0, kPaintLayerHaveTransparency = 1, kPaintLayerUncachedClipRects = 1 << 2, - kPaintLayerPaintingOverlayScrollbars = 1 << 3, kPaintLayerPaintingCompositingBackgroundPhase = 1 << 4, kPaintLayerPaintingCompositingForegroundPhase = 1 << 5, kPaintLayerPaintingCompositingMaskPhase = 1 << 6, @@ -140,8 +139,6 @@ append("kPaintLayerHaveTransparency"); if (flags & kPaintLayerUncachedClipRects) append("kPaintLayerUncachedClipRects"); - if (flags & kPaintLayerPaintingOverlayScrollbars) - append("kPaintLayerPaintingOverlayScrollbars"); if (flags & kPaintLayerPaintingCompositingScrollingPhase) append("kPaintLayerPaintingCompositingScrollingPhase"); if (flags & kPaintLayerPaintingOverflowContents)
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 48def2b..225e030 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -447,13 +447,6 @@ LayoutScrollbarPart* Resizer() const { return resizer_; } - const IntPoint& CachedOverlayScrollbarOffset() { - return cached_overlay_scrollbar_offset_; - } - void SetCachedOverlayScrollbarOffset(const IntPoint& offset) { - cached_overlay_scrollbar_offset_ = offset; - } - IntRect RectForHorizontalScrollbar(const IntRect& border_box_rect) const; IntRect RectForVerticalScrollbar(const IntRect& border_box_rect) const; @@ -679,8 +672,6 @@ // This is the offset from the beginning of content flow. ScrollOffset scroll_offset_; - IntPoint cached_overlay_scrollbar_offset_; - // LayoutObject to hold our custom scroll corner. LayoutScrollbarPart* scroll_corner_;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index c09566bd..33fed0f1 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -5535,22 +5535,6 @@ EXPECT_EQ(LayoutRect(390, -10, 20, 20), second_fragment->VisualRect()); } -// The following test tests that we restrict actual column count, to not run -// into unnecessary performance problems. The code that applies this limitation -// is in MultiColumnFragmentainerGroup::ActualColumnCount(). -TEST_P(PaintPropertyTreeBuilderTest, ShortColumnTallContent) { - SetBodyInnerHTML(R"HTML( - <div id="multicol" style="columns:3; column-gap:1px; width:101px; height:1px;"> - <div style="height:1000000px;"></div> - </div> - )HTML"); - - const auto* flow_thread = - GetLayoutObjectByElementId("multicol")->SlowFirstChild(); - ASSERT_TRUE(flow_thread->IsLayoutFlowThread()); - EXPECT_EQ(10u, NumFragments(flow_thread)); -} - TEST_P(PaintPropertyTreeBuilderTest, FragmentClipPixelSnapped) { SetBodyInnerHTML(R"HTML( <div id="container" style="columns: 2; column-gap: 0; width: 49.5px">
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc index f2f01a0e..c02359c 100644 --- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc +++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -123,56 +123,23 @@ void ScrollableAreaPainter::PaintOverflowControls( const PaintInfo& paint_info, - const IntPoint& paint_offset, - bool painting_overlay_controls) { + const IntPoint& paint_offset) { // Don't do anything if we have no overflow. - if (!GetScrollableArea().GetLayoutBox()->HasOverflowClip()) + const auto& box = *GetScrollableArea().GetLayoutBox(); + if (!box.HasOverflowClip() || + box.StyleRef().Visibility() != EVisibility::kVisible) return; - IntPoint adjusted_paint_offset = paint_offset; - if (painting_overlay_controls) - adjusted_paint_offset = GetScrollableArea().CachedOverlayScrollbarOffset(); - - CullRect adjusted_cull_rect = paint_info.GetCullRect(); - adjusted_cull_rect.MoveBy(-adjusted_paint_offset); - // Overlay scrollbars paint in a second pass through the layer tree so that - // they will paint on top of everything else. If this is the normal painting - // pass, paintingOverlayControls will be false, and we should just tell the - // root layer that there are overlay scrollbars that need to be painted. That - // will cause the second pass through the layer tree to run, and we'll paint - // the scrollbars then. In the meantime, cache tx and ty so that the second - // pass doesn't need to re-enter the LayoutTree to get it right. - if (GetScrollableArea().HasOverlayScrollbars() && - !painting_overlay_controls) { - GetScrollableArea().SetCachedOverlayScrollbarOffset(paint_offset); - // It's not necessary to do the second pass if the scrollbars paint into - // layers. - if ((GetScrollableArea().HorizontalScrollbar() && - GetScrollableArea().LayerForHorizontalScrollbar()) || - (GetScrollableArea().VerticalScrollbar() && - GetScrollableArea().LayerForVerticalScrollbar())) + // Overlay scrollbars are painted in the foreground paint phase, and normal + // scrollbars are painted in the background paint phase. + if (GetScrollableArea().HasOverlayScrollbars()) { + if (paint_info.phase != PaintPhase::kForeground) return; - if (!OverflowControlsIntersectRect(adjusted_cull_rect)) - return; - - LayoutView* layout_view = GetScrollableArea().GetLayoutBox()->View(); - - PaintLayer* painting_root = - GetScrollableArea().Layer()->EnclosingLayerWithCompositedLayerMapping( - kIncludeSelf); - if (!painting_root) - painting_root = layout_view->Layer(); - - painting_root->SetContainsDirtyOverlayScrollbars(true); + } else if (!ShouldPaintSelfBlockBackground(paint_info.phase)) { return; } - // This check is required to avoid painting custom CSS scrollbars twice. - if (painting_overlay_controls && !GetScrollableArea().HasOverlayScrollbars()) - return; - GraphicsContext& context = paint_info.context; - const auto& box = *GetScrollableArea().GetLayoutBox(); const auto* fragment = paint_info.FragmentToPaint(box); if (!fragment) return; @@ -190,6 +157,8 @@ } } + CullRect adjusted_cull_rect = paint_info.GetCullRect(); + adjusted_cull_rect.MoveBy(-paint_offset); if (GetScrollableArea().HorizontalScrollbar() && !GetScrollableArea().LayerForHorizontalScrollbar()) { GetScrollableArea().HorizontalScrollbar()->Paint(context, @@ -199,51 +168,27 @@ !GetScrollableArea().LayerForVerticalScrollbar()) { GetScrollableArea().VerticalScrollbar()->Paint(context, adjusted_cull_rect); } + if (!GetScrollableArea().LayerForScrollCorner()) { // We fill our scroll corner with white if we have a scrollbar that doesn't // run all the way up to the edge of the box. - PaintScrollCorner(context, adjusted_paint_offset, paint_info.GetCullRect()); + PaintScrollCorner(context, paint_offset, paint_info.GetCullRect()); // Paint our resizer last, since it sits on top of the scroll corner. - PaintResizer(context, adjusted_paint_offset, paint_info.GetCullRect()); + PaintResizer(context, paint_offset, paint_info.GetCullRect()); } } -bool ScrollableAreaPainter::OverflowControlsIntersectRect( - const CullRect& cull_rect) const { - const IntRect border_box = - GetScrollableArea().GetLayoutBox()->PixelSnappedBorderBoxRect( - GetScrollableArea().Layer()->SubpixelAccumulation()); - - if (cull_rect.Intersects( - GetScrollableArea().RectForHorizontalScrollbar(border_box))) - return true; - - if (cull_rect.Intersects( - GetScrollableArea().RectForVerticalScrollbar(border_box))) - return true; - - if (cull_rect.Intersects(GetScrollableArea().ScrollCornerRect())) - return true; - - if (cull_rect.Intersects(GetScrollableArea().ResizerCornerRect( - border_box, kResizerForPointer))) - return true; - - return false; -} - -void ScrollableAreaPainter::PaintScrollCorner( - GraphicsContext& context, - const IntPoint& paint_offset, - const CullRect& adjusted_cull_rect) { +void ScrollableAreaPainter::PaintScrollCorner(GraphicsContext& context, + const IntPoint& paint_offset, + const CullRect& cull_rect) { IntRect abs_rect = GetScrollableArea().ScrollCornerRect(); if (abs_rect.IsEmpty()) return; abs_rect.MoveBy(paint_offset); if (const auto* scroll_corner = GetScrollableArea().ScrollCorner()) { - if (!adjusted_cull_rect.Intersects(abs_rect)) + if (!cull_rect.Intersects(abs_rect)) return; ScrollbarPainter::PaintIntoRect(*scroll_corner, context, paint_offset, LayoutRect(abs_rect));
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.h b/third_party/blink/renderer/core/paint/scrollable_area_painter.h index d6c884a..86346c3 100644 --- a/third_party/blink/renderer/core/paint/scrollable_area_painter.h +++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.h
@@ -26,10 +26,7 @@ PaintLayerScrollableArea& paint_layer_scrollable_area) : scrollable_area_(&paint_layer_scrollable_area) {} - void PaintOverflowControls(const PaintInfo&, - const IntPoint& paint_offset, - bool painting_overlay_controls); - + void PaintOverflowControls(const PaintInfo&, const IntPoint& paint_offset); void PaintResizer(GraphicsContext&, const IntPoint& paint_offset, const CullRect&); @@ -39,7 +36,6 @@ private: void DrawPlatformResizerImage(GraphicsContext&, IntRect resizer_corner_rect); - bool OverflowControlsIntersectRect(const CullRect&) const; PaintLayerScrollableArea& GetScrollableArea() const; const DisplayItemClient& DisplayItemClientForCorner() const;
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 79a3c44..47793ce7 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -26,7 +26,9 @@ #include <memory> #include "base/auto_reset.h" +#include "base/feature_list.h" #include "third_party/blink/public/common/blob/blob_utils.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_document_or_string_or_form_data_or_url_search_params.h" @@ -1099,9 +1101,6 @@ resource_loader_options.data_buffering_policy = kDoNotBufferData; } - exception_code_ = DOMExceptionCode::kNoError; - error_ = false; - if (async_) { UseCounter::Count(&execution_context, WebFeature::kXMLHttpRequestAsynchronous); @@ -1133,11 +1132,22 @@ DEFINE_STATIC_LOCAL(EnumerationHistogram, syncxhr_pagedismissal_histogram, ("XHR.Sync.PageDismissal", 5)); syncxhr_pagedismissal_histogram.Count(pagedismissal); + // Disallow synchronous requests on page dismissal + if (base::FeatureList::IsEnabled( + features::kForbidSyncXHRInPageDismissal)) { + HandleNetworkError(); + ThrowForLoadFailureIfNeeded(exception_state, + "Synchronous XHR in page dismissal."); + return; + } } } resource_loader_options.synchronous_policy = kRequestSynchronously; } + exception_code_ = DOMExceptionCode::kNoError; + error_ = false; + loader_ = MakeGarbageCollected<ThreadableLoader>(execution_context, this, resource_loader_options); loader_->SetTimeout(timeout_);
diff --git a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js index 7531b84..1f2aeb17 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -2028,15 +2028,20 @@ UI.createExpandableText = function(text, maxLength) { const fragment = createDocumentFragment(); fragment.textContent = text.slice(0, maxLength); - const hiddenText = text.slice(maxLength); - - const expandButton = fragment.createChild('span', 'expandable-inline-button'); - expandButton.setAttribute('data-text', ls`Show ${Number.withThousandsSeparator(hiddenText.length)} more`); - expandButton.addEventListener('click', () => { - if (expandButton.parentElement) - expandButton.parentElement.insertBefore(createTextNode(hiddenText), expandButton); - expandButton.remove(); - }); + const expandElement = fragment.createChild('span'); + const totalBytes = Number.bytesToString(2 * text.length); + if (text.length < 10000000) { + expandElement.setAttribute('data-text', ls`Show more (${totalBytes})`); + expandElement.classList.add('expandable-inline-button'); + expandElement.addEventListener('click', () => { + if (expandElement.parentElement) + expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement); + expandElement.remove(); + }); + } else { + expandElement.setAttribute('data-text', ls`long text was truncated (${totalBytes})`); + expandElement.classList.add('undisplayable-text'); + } const copyButton = fragment.createChild('span', 'expandable-inline-button'); copyButton.setAttribute('data-text', ls`Copy`);
diff --git a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css index 1ab2d02..dc4baa36 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css +++ b/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
@@ -402,21 +402,31 @@ .expandable-inline-button { background-color: #dedede; - padding: 2px 4px; - margin: 0 2px; color: #333; cursor: pointer; border-radius: 3px; +} + +.undisplayable-text, +.expandable-inline-button { + padding: 2px 4px; + margin: 0 2px; font-size: 12px; font-family: sans-serif; white-space: nowrap; display: inline-block; } +.undisplayable-text::after, .expandable-inline-button::after { content: attr(data-text); } +.undisplayable-text { + color: rgb(128, 128, 128); + font-style: italic; +} + .expandable-inline-button:hover { background-color: #d5d5d5; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc index e5f5f9a..d8d69f7b 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
@@ -58,10 +58,6 @@ case kMediaSlider: return AccessibilityMediaTimeline::Create(layout_object, ax_object_cache); - case kMediaVolumeSlider: - return AccessibilityMediaVolumeSlider::Create(layout_object, - ax_object_cache); - case kMediaCurrentTimeDisplay: case kMediaTimeRemainingDisplay: return AccessibilityMediaTimeDisplay::Create(layout_object, @@ -98,6 +94,11 @@ case kMediaAnimatedArrowContainer: return MakeGarbageCollected<AccessibilityMediaControl>(layout_object, ax_object_cache); + // Removed as a part of the a11y tree rewrite https://crbug.com/836549. + case kMediaVolumeSlider: + NOTREACHED(); + return MakeGarbageCollected<AccessibilityMediaControl>(layout_object, + ax_object_cache); } NOTREACHED(); @@ -372,38 +373,6 @@ } // -// AccessibilityMediaVolumeSlider - -AccessibilityMediaVolumeSlider::AccessibilityMediaVolumeSlider( - LayoutObject* layout_object, - AXObjectCacheImpl& ax_object_cache) - : AXSlider(layout_object, ax_object_cache) {} - -AXObject* AccessibilityMediaVolumeSlider::Create( - LayoutObject* layout_object, - AXObjectCacheImpl& ax_object_cache) { - return MakeGarbageCollected<AccessibilityMediaVolumeSlider>(layout_object, - ax_object_cache); -} - -String AccessibilityMediaVolumeSlider::Description( - ax::mojom::NameFrom name_from, - ax::mojom::DescriptionFrom& description_from, - AXObjectVector* description_objects) const { - return QueryString(WebLocalizedString::kAXMediaVolumeSliderHelp); -} - -bool AccessibilityMediaVolumeSlider::InternalSetAccessibilityFocusAction() { - MediaControlElementsHelper::NotifyMediaControlAccessibleFocus(GetElement()); - return AXSlider::InternalSetAccessibilityFocusAction(); -} - -bool AccessibilityMediaVolumeSlider::InternalClearAccessibilityFocusAction() { - MediaControlElementsHelper::NotifyMediaControlAccessibleBlur(GetElement()); - return AXSlider::InternalClearAccessibilityFocusAction(); -} - -// // AccessibilityMediaTimeDisplay AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.h b/third_party/blink/renderer/modules/accessibility/ax_media_controls.h index 5299069..ad984667 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.h +++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.h
@@ -81,24 +81,6 @@ DISALLOW_COPY_AND_ASSIGN(AccessibilityMediaTimeline); }; -class AccessibilityMediaVolumeSlider final : public AXSlider { - public: - static AXObject* Create(LayoutObject*, AXObjectCacheImpl&); - - AccessibilityMediaVolumeSlider(LayoutObject*, AXObjectCacheImpl&); - ~AccessibilityMediaVolumeSlider() override = default; - - String Description(ax::mojom::NameFrom, - ax::mojom::DescriptionFrom&, - AXObjectVector* description_objects) const override; - - bool InternalSetAccessibilityFocusAction() override; - bool InternalClearAccessibilityFocusAction() override; - - private: - DISALLOW_COPY_AND_ASSIGN(AccessibilityMediaVolumeSlider); -}; - class AXMediaControlsContainer final : public AccessibilityMediaControl { public: static AXObject* Create(LayoutObject*, AXObjectCacheImpl&);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 3ec0f3f..8ceeb86 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -82,6 +82,7 @@ #include "third_party/blink/renderer/modules/accessibility/ax_slider.h" #include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h" #include "third_party/blink/renderer/modules/accessibility/ax_virtual_object.h" +#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" #include "third_party/blink/renderer/modules/permissions/permission_utils.h" namespace blink { @@ -311,8 +312,13 @@ return AXList::Create(layout_object, *this); // media controls - if (node && node->IsMediaControlElement()) + // TODO(https://crbug.com/836549): Remove for the rest of the controls. + // kMediaVolumeSlider has already been removed. + if (node && node->IsMediaControlElement() && + MediaControlElementsHelper::GetMediaControlElementType(node) != + kMediaVolumeSlider) { return AccessibilityMediaControl::Create(layout_object, *this); + } if (IsHTMLOptionElement(node)) return AXListBoxOption::Create(layout_object, *this);
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc index c5dc536c..220580d4 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.cc
@@ -20,6 +20,9 @@ MediaControlsImpl& media_controls) : MediaControlSliderElement(media_controls, kMediaVolumeSlider) { setAttribute(html_names::kMaxAttr, "1"); + setAttribute(html_names::kAriaValuemaxAttr, "100"); + setAttribute(html_names::kAriaValueminAttr, "0"); + setAttribute(html_names::kAriaLabelAttr, "volume"); SetShadowPseudoId(AtomicString("-webkit-media-controls-volume-slider")); SetVolumeInternal(MediaElement().volume()); @@ -104,6 +107,9 @@ void MediaControlVolumeSliderElement::SetVolumeInternal(double volume) { SetupBarSegments(); SetAfterSegmentPosition(MediaControlSliderElement::Position(0, volume)); + int percent_vol = 100 * volume; + setAttribute(html_names::kAriaValuenowAttr, + WTF::AtomicString::Number(percent_vol)); } bool MediaControlVolumeSliderElement::KeepEventInNode(
diff --git a/third_party/blink/renderer/modules/payments/payment_request.idl b/third_party/blink/renderer/modules/payments/payment_request.idl index db1d392..e2a1c83d 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.idl +++ b/third_party/blink/renderer/modules/payments/payment_request.idl
@@ -17,7 +17,7 @@ [CallWith=ScriptState, NewObject] Promise<PaymentResponse> show(); [CallWith=ScriptState, NewObject] Promise<void> abort(); [CallWith=ScriptState, HighEntropy, Measure, NewObject] Promise<boolean> canMakePayment(); - [CallWith=ScriptState, NewObject, RuntimeEnabled=PaymentRequestHasEnrolledInstrument] Promise<boolean> hasEnrolledInstrument(); + [CallWith=ScriptState, HighEntropy, Measure, NewObject, RuntimeEnabled=PaymentRequestHasEnrolledInstrument] Promise<boolean> hasEnrolledInstrument(); readonly attribute DOMString id; [ImplementedAs=getShippingAddress] readonly attribute PaymentAddress? shippingAddress;
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 6797fb98..5424377 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -614,4 +614,8 @@ RuntimeEnabledFeatures::SetGetDisplayMediaEnabled(enable); } +void WebRuntimeFeatures::EnableForbidSyncXHRInPageDismissal(bool enable) { + RuntimeEnabledFeatures::SetForbidSyncXHRInPageDismissalEnabled(enable); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h index 46899a7..06ec28e 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
@@ -12,7 +12,7 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #if DCHECK_IS_ON() -#include "third_party/blink/renderer/platform/wtf/list_hash_set.h" +#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #endif @@ -208,7 +208,7 @@ return node; } - ListHashSet<const NodeType*> nodes_; + LinkedHashSet<const NodeType*> nodes_; }; template <typename NodeType>
diff --git a/third_party/blink/renderer/platform/network/http_parsers_fuzzer.cc b/third_party/blink/renderer/platform/network/http_parsers_fuzzer.cc index ad0dbf8..0d5dcc9 100644 --- a/third_party/blink/renderer/platform/network/http_parsers_fuzzer.cc +++ b/third_party/blink/renderer/platform/network/http_parsers_fuzzer.cc
@@ -28,12 +28,19 @@ unsigned failure_position = 0; std::string terminated(reinterpret_cast<const char*>(data), size); + + // There are no guarantees regarding the string capacity, but we are doing our + // best to make it |size + 1|. + terminated.shrink_to_fit(); + blink::IsValidHTTPToken(terminated.c_str()); blink::ParseCacheControlDirectives(terminated.c_str(), AtomicString()); blink::ParseCommaDelimitedHeader(terminated.c_str(), set); blink::ParseHTTPRefresh(terminated.c_str(), nullptr, delay, url); - blink::ParseMultipartHeadersFromBody(terminated.c_str(), terminated.size(), - &response, &end); + + // Intentionally pass raw data as the API does not require trailing \0. + blink::ParseMultipartHeadersFromBody(reinterpret_cast<const char*>(data), + size, &response, &end); blink::ParseServerTimingHeader(terminated.c_str()); blink::ParseContentTypeOptionsHeader(terminated.c_str()); blink::ParseXSSProtectionHeader(terminated.c_str(), failure_reason,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index eca0ba09..b746e09 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -519,6 +519,10 @@ }, // For simulating Android's overlay fullscreen video in web tests on Linux. { + name: "ForbidSyncXHRInPageDismissal", + status: "test", + }, + { name: "ForceOverlayFullscreenVideo", }, {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 40034ff4..4e7e22b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1047,7 +1047,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/client-rects-rtl.html [ Crash Failure ] crbug.com/874506 virtual/layout_ng_experimental/fast/multicol/column-break-with-balancing.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/column-clamping.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/column-count-with-rules.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/column-rules.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/columns-shorthand-parsing.html [ Failure ] @@ -2728,6 +2727,8 @@ # Chrome touch-action computation ignores div transforms. crbug.com/715148 external/wpt/pointerevents/pointerevent_touch-action-rotated-divs_touch-manual.html [ Skip ] +crbug.com/606367 external/wpt/pointerevents/pointerevent_pointerout_pen-manual.html [ Skip ] + # Disabled until v8 roll. crbug.com/906847 inspector-protocol/runtime/runtime-getProperties.js [ Skip ] crbug.com/906847 inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js [ Skip ]
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-commit.html index cf250d4..74ed187 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-commit.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-commit.html
@@ -34,7 +34,7 @@ function runTest() { let container = document.createElement("div"); - container.getDisplayLock().acquire().then(() => { + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { let child = document.createElement("div"); child.id = "child"; container.appendChild(child);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-infinite-timeout-no-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-infinite-timeout-no-commit.html index 78068c1..87ec706 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-infinite-timeout-no-commit.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-infinite-timeout-no-commit.html
@@ -1,7 +1,7 @@ <!doctype HTML> <!-- -Runs an acquireDisplayLock, which suspends the context. +Runs an acquire, with no commit. The associated promise should never resolve. -->
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html index 604eb696..94fb15d 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-measure-remove.html
@@ -67,7 +67,7 @@ function runTest() { let container = document.createElement("div"); container.id = "container"; - container.getDisplayLock().acquire().then(() => { + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { construct(container); document.getElementById("empty").appendChild(container); container.getDisplayLock().update().then(measureAndRemove).then(finish);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove-expected.html new file mode 100644 index 0000000..1333caeb --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove-expected.html
@@ -0,0 +1,4 @@ +<!doctype HTML> + +<div id="log">PASS</div> +
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove.html new file mode 100644 index 0000000..d7043a1 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-remove.html
@@ -0,0 +1,44 @@ +<!doctype HTML> + +<!-- +Runs an acquire(), then calls update() but disconnects the element before update finishes. +--> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightblue; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.id = "container"; + + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { + document.body.appendChild(container); + container.getDisplayLock().update().then( + () => { finishTest("FAIL"); }, + () => { finishTest("PASS"); }); + container.remove(); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-added-containment.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-added-containment.html index c588863..12e0c92 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-added-containment.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-added-containment.html
@@ -29,7 +29,7 @@ async function runTest() { let container = document.createElement("div"); - await container.getDisplayLock().acquire(); + await container.getDisplayLock().acquire({ timeout: Infinity }); container.classList = "contained"; document.body.appendChild(container);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-inline-fails.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-inline-fails.html index cc777c5..54a7009 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-inline-fails.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-inline-fails.html
@@ -28,7 +28,7 @@ async function acquire() { let container = document.createElement("span"); container.id = "container"; - await container.getDisplayLock().acquire(); + await container.getDisplayLock().acquire({ timeout: Infinity }); document.body.appendChild(container); container.getDisplayLock().commit().then( () => { finishTest("FAIL"); },
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-no-containment-fails.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-no-containment-fails.html index f61e972..69eca2d8 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-no-containment-fails.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-on-no-containment-fails.html
@@ -21,7 +21,7 @@ async function acquire() { let container = document.createElement("div"); - await container.getDisplayLock().acquire(); + await container.getDisplayLock().acquire({ timeout: Infinity }); document.body.appendChild(container); container.getDisplayLock().commit().then( () => { finishTest("FAIL"); },
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected-expected.html new file mode 100644 index 0000000..a2fa191 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected-expected.html
@@ -0,0 +1,14 @@ +<!doctype HTML> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightblue; +} +</style> + +<div id="log">PASS</div> +<div id="container"></div> +
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected.html new file mode 100644 index 0000000..962f85de --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-while-disconnected.html
@@ -0,0 +1,45 @@ +<!doctype HTML> + +<!-- +Runs an acquire(), then commits without connecting the element, which should just unlock and fail. +--> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightblue; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.id = "container"; + + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { + container.getDisplayLock().commit().then( + () => { finishTest("FAIL"); }, + () => { + document.body.appendChild(container); + finishTest("PASS"); + }); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html index c6df5c9..ef6cb4e3 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-forced-layout.html
@@ -74,7 +74,7 @@ async function runTest() { let container = document.createElement("div"); container.id = "container"; - await container.getDisplayLock().acquire(); + await container.getDisplayLock().acquire({ timeout: Infinity }); document.getElementById("parent").appendChild(container); construct(container);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html index 67ad858..e5c2c7b 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-updated-layout.html
@@ -74,7 +74,7 @@ async function runTest() { let container = document.createElement("div"); container.id = "container"; - await container.getDisplayLock().acquire(); + await container.getDisplayLock().acquire({ timeout: Infinity }); document.getElementById("parent").appendChild(container); construct(container);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-acquires-all-succeed.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-acquires-all-succeed.html index 9d9444ed2..eb47bb6 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-acquires-all-succeed.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-acquires-all-succeed.html
@@ -35,10 +35,10 @@ function runTest() { let container = document.createElement("div"); Promise.all([ - container.getDisplayLock().acquire(), - container.getDisplayLock().acquire(), - container.getDisplayLock().acquire(), - container.getDisplayLock().acquire() + container.getDisplayLock().acquire({ timeout: Infinity }), + container.getDisplayLock().acquire({ timeout: Infinity }), + container.getDisplayLock().acquire({ timeout: Infinity }), + container.getDisplayLock().acquire({ timeout: Infinity }) ]).then(() => { let child = document.createElement("div"); child.id = "child";
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected-expected.html new file mode 100644 index 0000000..09d5a52d4 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected-expected.html
@@ -0,0 +1,13 @@ +<!doctype HTML> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightblue; +} +</style> +<div id="log">PASS if container is visible</div> +<div id="container"></div> +
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected.html b/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected.html new file mode 100644 index 0000000..6d9d2b93 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/timeout-while-disconnected.html
@@ -0,0 +1,43 @@ +<!doctype HTML> + +<!-- +Runs an acquire(), times out without ever connecting the element. +--> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightblue; +} +</style> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.id = "container"; + + container.getDisplayLock().acquire({ timeout: 100 }).then(() => { + setTimeout(() => { + document.body.appendChild(container); + finishTest("PASS if container is visible"); + }, 200); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-together-with-commit-both-succeed.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-together-with-commit-both-succeed.html index f2dcef7c..3b657b6 100644 --- a/third_party/blink/web_tests/display-lock/lock-before-append/update-together-with-commit-both-succeed.html +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-together-with-commit-both-succeed.html
@@ -34,7 +34,7 @@ function runTest() { let container = document.createElement("div"); - container.getDisplayLock().acquire().then(() => { + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { let child = document.createElement("div"); child.id = "child"; container.appendChild(child);
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected-expected.html new file mode 100644 index 0000000..1333caeb --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected-expected.html
@@ -0,0 +1,4 @@ +<!doctype HTML> + +<div id="log">PASS</div> +
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected.html new file mode 100644 index 0000000..9f0e4ed --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-while-disconnected.html
@@ -0,0 +1,33 @@ +<!doctype HTML> + +<!-- +Runs an acquire(), then updates without connecting the element. +--> + +<div id="log"></div> + +<script> +// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait. +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function runTest() { + let container = document.createElement("div"); + container.id = "container"; + + container.getDisplayLock().acquire({ timeout: Infinity }).then(() => { + container.getDisplayLock().update().then( + () => { finishTest("FAIL"); }, + () => { finishTest("PASS"); }); + }); +} + +window.onload = runTest; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/large-actual-column-count.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/large-actual-column-count.html new file mode 100644 index 0000000..615e3f2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/large-actual-column-count.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#pseudo-algorithm"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div id="container" style="overflow:hidden; columns:1; column-fill:auto; column-gap:0; width:100px; height:100px; background:red;"> + <div style="height:300000px;"></div> + <div style="width:100px; height:100px; background:green;"></div> + <div style="height:123456px;"></div> +</div> +<script> + document.getElementById("container").scrollLeft = 300000; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen-manual.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen.html similarity index 85% rename from third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen-manual.html rename to third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen.html index 5e38952..972f99d9 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen-manual.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_pointerout_pen.html
@@ -6,6 +6,9 @@ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> + <script src="/resources/testdriver.js"></script> + <script src="/resources/testdriver-actions.js"></script> + <script src="/resources/testdriver-vendor.js"></script> <!-- Additional helper script for common checks across event types --> <script type="text/javascript" src="pointerevent_support.js"></script> </head> @@ -45,6 +48,13 @@ }, "you have to use pen for this test"); } }); + + // Inject pen inputs. + new test_driver.Actions() + .addPointer("pointer1", "pen") + .pointerMove(0, 0, {origin: target0}) + .pointerMove(0, 0) + .send(); } </script>
diff --git a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-automation.js deleted file mode 100644 index d2fa8fc..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-automation.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - return penMoveIntoTarget('#target0').then(function() { - penMoveToDocument(); - }); -} -
diff --git a/third_party/blink/web_tests/fast/multicol/column-clamping-expected.html b/third_party/blink/web_tests/fast/multicol/column-clamping-expected.html deleted file mode 100644 index 703581c6..0000000 --- a/third_party/blink/web_tests/fast/multicol/column-clamping-expected.html +++ /dev/null
@@ -1,5 +0,0 @@ -<!DOCTYPE html> -<!-- See crbug.com/808189 - this test assumes that we're not allowed - to use more than 10 columns if the column height is 10px. --> -<p>There should be a hotpink square below.</p> -<div style="width:100px; height:100px; background:hotpink;"></div>
diff --git a/third_party/blink/web_tests/fast/multicol/column-clamping.html b/third_party/blink/web_tests/fast/multicol/column-clamping.html deleted file mode 100644 index aa2f7430..0000000 --- a/third_party/blink/web_tests/fast/multicol/column-clamping.html +++ /dev/null
@@ -1,8 +0,0 @@ -<!DOCTYPE html> -<!-- See crbug.com/808189 - this test assumes that we're not allowed - to use more than 10 columns if the column height is 10px. --> -<p>There should be a hotpink square below.</p> -<div style="columns:3; column-gap:0; width:30px; height:10px;"> - <div style="height:190px; background:hotpink;"></div> -</div> -<div style="width:90px; height:90px; background:hotpink;"></div>
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/destroy-overlay-scrollbar-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/destroy-overlay-scrollbar-expected.txt index 631ee54..0ba1c4a2 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/destroy-overlay-scrollbar-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/scroll/destroy-overlay-scrollbar-expected.txt
@@ -18,7 +18,7 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV", + "object": "VerticalScrollbar", "rect": [193, 100, 7, 200], "reason": "chunk disappeared" }
diff --git a/third_party/crashpad/crashpad/third_party/cpp-httplib/cpp-httplib/httplib.h b/third_party/crashpad/crashpad/third_party/cpp-httplib/cpp-httplib/httplib.h index a2a5c46..dadab1d 100644 --- a/third_party/crashpad/crashpad/third_party/cpp-httplib/cpp-httplib/httplib.h +++ b/third_party/crashpad/crashpad/third_party/cpp-httplib/cpp-httplib/httplib.h
@@ -39,7 +39,6 @@ #endif typedef SOCKET socket_t; -constexpr socket_t kInvalidSocket = INVALID_SOCKET; #else #include <pthread.h> #include <unistd.h>
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium index 8ec6138b..6bb040c 100644 --- a/third_party/feed/README.chromium +++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Short name: feed URL: https://chromium.googlesource.com/feed Version: 0 -Revision: e2809cef2bf967cf572527e0944307fd2a9277d0 +Revision: 84617ef81ded68396acf495e8392266950972223 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/feed/java_sources.gni b/third_party/feed/java_sources.gni index 7dd0774..0000d38 100644 --- a/third_party/feed/java_sources.gni +++ b/third_party/feed/java_sources.gni
@@ -18,6 +18,7 @@ "src/src/main/java/com/google/android/libraries/feed/api/knowncontent/ContentRemoval.java", "src/src/main/java/com/google/android/libraries/feed/api/knowncontent/KnownContentApi.java", "src/src/main/java/com/google/android/libraries/feed/api/lifecycle/AppLifecycleListener.java", + "src/src/main/java/com/google/android/libraries/feed/api/lifecycle/Resettable.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChange.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChangeObserver.java", "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelChild.java", @@ -34,6 +35,7 @@ "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/TokenCompletedObserver.java", "src/src/main/java/com/google/android/libraries/feed/api/protocoladapter/ProtocolAdapter.java", "src/src/main/java/com/google/android/libraries/feed/api/requestmanager/RequestManager.java", + "src/src/main/java/com/google/android/libraries/feed/api/scope/ClearAllListener.java", "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java", "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java", "src/src/main/java/com/google/android/libraries/feed/api/sessionmanager/SessionManager.java", @@ -64,12 +66,6 @@ "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/drivers/NoContentDriver.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/drivers/StreamDriver.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/drivers/ZeroStateDriver.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/LoggingListener.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/OneShotVisibilityLoggingListener.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/SpinnerLogger.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/StreamContentLoggingData.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/VisibilityListener.java", - "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/logging/VisibilityMonitor.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/scroll/ScrollRestorer.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/viewholders/ContinuationViewHolder.java", "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/viewholders/FeedViewHolder.java", @@ -91,7 +87,6 @@ "src/src/main/java/com/google/android/libraries/feed/common/functional/Consumer.java", "src/src/main/java/com/google/android/libraries/feed/common/functional/Function.java", "src/src/main/java/com/google/android/libraries/feed/common/functional/Predicate.java", - "src/src/main/java/com/google/android/libraries/feed/common/functional/SettableSupplier.java", "src/src/main/java/com/google/android/libraries/feed/common/functional/Supplier.java", "src/src/main/java/com/google/android/libraries/feed/common/locale/LocaleUtils.java", "src/src/main/java/com/google/android/libraries/feed/common/logging/Dumpable.java", @@ -237,13 +232,18 @@ "src/src/main/java/com/google/android/libraries/feed/piet/host/HostBindingProvider.java", "src/src/main/java/com/google/android/libraries/feed/piet/ui/AspectRatioScalingImageView.java", "src/src/main/java/com/google/android/libraries/feed/piet/ui/BorderDrawable.java", - "src/src/main/java/com/google/android/libraries/feed/piet/ui/DrawableScalingHelper.java", "src/src/main/java/com/google/android/libraries/feed/piet/ui/GridRowView.java", "src/src/main/java/com/google/android/libraries/feed/piet/ui/RoundedCornerViewHelper.java", "src/src/main/java/com/google/android/libraries/feed/piet/ui/RoundedCornerWrapperView.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/contentchanged/StreamContentChangedListener.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/contextmenumanager/ContextMenuManager.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/contextmenumanager/ContextMenuManagerImpl.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/LoggingListener.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/OneShotVisibilityLoggingListener.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/SpinnerLogger.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/StreamContentLoggingData.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/VisibilityListener.java", + "src/src/main/java/com/google/android/libraries/feed/sharedstream/logging/VisibilityMonitor.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/offlinemonitor/StreamOfflineMonitor.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/piet/PietAssetProvider.java", "src/src/main/java/com/google/android/libraries/feed/sharedstream/piet/PietCustomElementProvider.java", @@ -258,6 +258,7 @@ feed_conformance_test_lib_sources = [ "src/src/main/java/com/google/android/libraries/feed/api/common/testing/ContentIdGenerators.java", "src/src/main/java/com/google/android/libraries/feed/api/common/testing/InternalProtocolBuilder.java", + "src/src/main/java/com/google/android/libraries/feed/common/concurrent/testing/FakeMainThreadRunner.java", "src/src/main/java/com/google/android/libraries/feed/common/testing/FakeClock.java", "src/src/main/java/com/google/android/libraries/feed/common/testing/FakeRequestManager.java", "src/src/main/java/com/google/android/libraries/feed/common/testing/InfrastructureIntegrationScope.java",
diff --git a/third_party/feed/update_java_sources.sh b/third_party/feed/update_java_sources.sh index 11e3a6f..ffc39cd 100755 --- a/third_party/feed/update_java_sources.sh +++ b/third_party/feed/update_java_sources.sh
@@ -24,7 +24,7 @@ " >> java_sources.gni echo "feed_conformance_test_lib_sources = [" >> java_sources.gni -find src/src/main/java/com/google/android/libraries/feed -wholename "*/common/testing/*.java" |\ +find src/src/main/java/com/google/android/libraries/feed -regex ".*/common/\(.*/\)*testing/.*\.java" |\ env LC_COLLATE=en_US.ASCII sort | sed 's/^\(.*\)$/ "\1",/g' >> java_sources.gni find src/src/main/java/com/google/android/libraries/feed/testing/conformance -wholename "*.java" |\ env LC_COLLATE=en_US.ASCII sort | sed 's/^\(.*\)$/ "\1",/g' >> java_sources.gni
diff --git a/third_party/qcms/qcms_color_space_fuzzer.cc b/third_party/qcms/qcms_color_space_fuzzer.cc index be08c88..106149d 100644 --- a/third_party/qcms/qcms_color_space_fuzzer.cc +++ b/third_party/qcms/qcms_color_space_fuzzer.cc
@@ -7,6 +7,7 @@ #include <random> #include "base/logging.h" +#include "base/stl_util.h" #include "testing/libfuzzer/fuzzers/color_space_data.h" #include "third_party/qcms/src/qcms.h" @@ -18,7 +19,7 @@ static std::uniform_int_distribution<uint32_t> uniform(0u, ~0u); std::mt19937_64 random(hash); - for (size_t i = 0; i < arraysize(pixels); ++i) + for (size_t i = 0; i < base::size(pixels); ++i) pixels[i] = uniform(random); } @@ -46,9 +47,9 @@ static qcms_profile* SelectProfile(size_t hash) { static qcms_profile* profiles[4] = { - qcms_profile_from_memory(kSRGBData, arraysize(kSRGBData)), - qcms_profile_from_memory(kSRGBPara, arraysize(kSRGBPara)), - qcms_profile_from_memory(kAdobeData, arraysize(kAdobeData)), + qcms_profile_from_memory(kSRGBData, base::size(kSRGBData)), + qcms_profile_from_memory(kSRGBPara, base::size(kSRGBPara)), + qcms_profile_from_memory(kAdobeData, base::size(kAdobeData)), qcms_profile_sRGB(), };
diff --git a/third_party/zlib/google/compression_utils_unittest.cc b/third_party/zlib/google/compression_utils_unittest.cc index adcb773..942b7c03 100644 --- a/third_party/zlib/google/compression_utils_unittest.cc +++ b/third_party/zlib/google/compression_utils_unittest.cc
@@ -10,7 +10,7 @@ #include <string> #include "base/logging.h" -#include "base/macros.h" +#include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace compression { @@ -34,24 +34,24 @@ } // namespace TEST(CompressionUtilsTest, GzipCompression) { - std::string data(reinterpret_cast<const char*>(kData), arraysize(kData)); + std::string data(reinterpret_cast<const char*>(kData), base::size(kData)); std::string compressed_data; EXPECT_TRUE(GzipCompress(data, &compressed_data)); std::string golden_compressed_data( reinterpret_cast<const char*>(kCompressedData), - arraysize(kCompressedData)); + base::size(kCompressedData)); EXPECT_EQ(golden_compressed_data, compressed_data); } TEST(CompressionUtilsTest, GzipUncompression) { std::string compressed_data(reinterpret_cast<const char*>(kCompressedData), - arraysize(kCompressedData)); + base::size(kCompressedData)); std::string uncompressed_data; EXPECT_TRUE(GzipUncompress(compressed_data, &uncompressed_data)); std::string golden_data(reinterpret_cast<const char*>(kData), - arraysize(kData)); + base::size(kData)); EXPECT_EQ(golden_data, uncompressed_data); } @@ -76,10 +76,10 @@ TEST(CompressionUtilsTest, InPlace) { const std::string original_data(reinterpret_cast<const char*>(kData), - arraysize(kData)); + base::size(kData)); const std::string golden_compressed_data( reinterpret_cast<const char*>(kCompressedData), - arraysize(kCompressedData)); + base::size(kCompressedData)); std::string data(original_data); EXPECT_TRUE(GzipCompress(data, &data));
diff --git a/tools/android/roll/android_deps/README.md b/tools/android/roll/android_deps/README.md index fe37c23..1ba9a7b 100644 --- a/tools/android/roll/android_deps/README.md +++ b/tools/android/roll/android_deps/README.md
@@ -38,8 +38,8 @@ variable in `BuildConfigGenerator.groovy` in order to ensure that each tag in CIPD is unique. - One option to thoroughly test your change is to run - `rm -rf third_party/android_deps/libs/[!O]*` before running with - `--update-all`. This will ensure all your deps are fresh. The commands + `rm -rf third_party/android_deps/libs/[!O]* && tools/android/roll/android_deps/fetch_all.py --update-all`. + This will ensure all your deps are fresh. The commands printed out in the following step will ensure you do not upload duplicate instances.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 56ad330..e25e761b 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3502,6 +3502,7 @@ <int value="15" label="Component update task"/> <int value="16" label="Deprecated Explore Sites refresh task"/> <int value="17" label="Explore Sites refresh task"/> + <int value="18" label="Download auto-resumption task"/> </enum> <enum name="BackgroundTracingState"> @@ -21145,6 +21146,7 @@ <int value="2718" label="V8HTMLMediaElement_CanPlayType_Method"/> <int value="2719" label="HistoryLength"/> <int value="2720" label="FeaturePolicyReportOnlyHeader"/> + <int value="2721" label="V8PaymentRequest_HasEnrolledInstrument_Method"/> </enum> <enum name="FeaturePolicyFeature"> @@ -31367,6 +31369,7 @@ <int value="105046382" label="ParallelDownloading:disabled"/> <int value="106840653" label="mus"/> <int value="107900612" label="ChromeHomePersistentIph:disabled"/> + <int value="109577361" label="ForbidSyncXHRInPageDismissal:enabled"/> <int value="115915570" label="OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRef:enabled"/> <int value="118991027" label="enable-accelerated-fixed-root-background"/> @@ -31980,6 +31983,7 @@ <int value="1237297772" label="no-pings"/> <int value="1240073971" label="ash-disable-smooth-screen-rotation"/> <int value="1242632259" label="ContentSuggestionsCategoryOrder:disabled"/> + <int value="1243890754" label="ForbidSyncXHRInPageDismissal:disabled"/> <int value="1245889469" label="enable-surface-worker"/> <int value="1247293682" label="topchrome-md"/> <int value="1250071868" label="disable-timezone-tracking-option"/> @@ -32402,6 +32406,7 @@ <int value="1971964569" label="NewEncodeCpuLoadEstimator:disabled"/> <int value="1972232935" label="DisplayMoveWindowAccels:enabled"/> <int value="1972720114" label="WebPaymentsJustInTimePaymentApp:enabled"/> + <int value="1974565950" label="enable-experimental-accessibility-labels"/> <int value="1979222611" label="XRSandbox:disabled"/> <int value="1980011075" label="debug-packed-apps"/> <int value="1980648371" label="PointerEventV1SpecCapturing:enabled"/> @@ -42923,7 +42928,7 @@ <int value="0" label="Path suffix"/> <int value="1" label="Navigation to Previews Domain"/> <int value="2" label="Navigation to Private Domain"/> - <int value="3" label="The requested host was blacklisted by the server"/> + <int value="3" label="Host was blacklisted in a previous server request"/> </enum> <enum name="PreviewsServerLitePageIneligibleReason">
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 5a01aac..840526f2 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -164,6 +164,7 @@ <item id="oauth2_mint_token_flow" hash_code="1112842" type="1" second_id="29188932" content_hash_code="91581432" os_list="linux,windows" semantics_fields="1,2,3,4,5" policy_fields="3,4" file_path="google_apis/gaia/oauth2_mint_token_flow.cc"/> <item id="ocsp_start_url_request" hash_code="60921996" type="0" content_hash_code="24127780" os_list="linux" file_path="net/cert_net/nss_ocsp.cc"/> <item id="offline_prefetch" hash_code="19185953" type="0" content_hash_code="112039446" os_list="linux,windows" file_path="components/offline_pages/core/prefetch/prefetch_request_fetcher.cc"/> + <item id="omnibox_debug_results_change" hash_code="71252052" type="0" content_hash_code="88668874" os_list="linux,windows" file_path="chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc"/> <item id="omnibox_documentsuggest" hash_code="6055066" type="0" content_hash_code="126973249" os_list="linux,windows" file_path="components/omnibox/browser/document_suggestions_service.cc"/> <item id="omnibox_navigation_observer" hash_code="61684939" type="0" content_hash_code="70941231" os_list="linux,windows" file_path="chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc"/> <item id="omnibox_prefetch_image" hash_code="109200878" type="0" content_hash_code="107906693" os_list="linux,windows" file_path="chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc"/> @@ -207,8 +208,8 @@ <item id="proxy_config_system" hash_code="11258689" type="0" content_hash_code="77057929" os_list="linux,windows" file_path="net/proxy_resolution/proxy_resolution_service.cc"/> <item id="proxy_script_fetcher" hash_code="37531401" type="0" deprecated="2018-03-16" content_hash_code="31866133" file_path=""/> <item id="puch_client_channel" hash_code="34459548" type="0" content_hash_code="92475475" os_list="linux,windows" file_path="components/invalidation/impl/push_client_channel.cc"/> - <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/quic_chromium_client_session.cc"/> <item id="quic_chromium_incoming_pending_session" hash_code="120830730" type="0" content_hash_code="52904665" os_list="linux,windows" file_path="net/quic/quic_chromium_client_session.cc"/> + <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/quic_chromium_client_session.cc"/> <item id="quic_chromium_packet_writer" hash_code="20153177" type="0" content_hash_code="29657765" os_list="linux,windows" file_path="net/quic/quic_chromium_packet_writer.cc"/> <item id="ranker_url_fetcher" hash_code="95682324" type="0" content_hash_code="45958626" os_list="linux,windows" file_path="components/assist_ranker/ranker_url_fetcher.cc"/> <item id="rappor_report" hash_code="44606780" type="0" content_hash_code="111287826" os_list="linux,windows" file_path="components/rappor/log_uploader.cc"/>
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc index 5428cb2..06315d994 100644 --- a/ui/accessibility/accessibility_switches.cc +++ b/ui/accessibility/accessibility_switches.cc
@@ -17,6 +17,10 @@ const char kEnableExperimentalAccessibilityAutoclick[] = "enable-experimental-accessibility-autoclick"; +// Enables additional image label features that haven't launched yet. +const char kEnableExperimentalAccessibilityLabels[] = + "enable-experimental-accessibility-labels"; + // Shows setting to enable Switch Access before it has launched. const char kEnableExperimentalAccessibilitySwitchAccess[] = "enable-experimental-accessibility-switch-access";
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h index 70588cd..31e05d9 100644 --- a/ui/accessibility/accessibility_switches.h +++ b/ui/accessibility/accessibility_switches.h
@@ -12,6 +12,7 @@ AX_EXPORT extern const char kEnableExperimentalAccessibilityFeatures[]; AX_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[]; +AX_EXPORT extern const char kEnableExperimentalAccessibilityLabels[]; AX_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccess[]; // Returns true if experimental accessibility features are enabled.
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 8678d04..b0d271f 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -47,11 +47,7 @@ defines = [ "UI_DATA_PACK_IMPLEMENTATION" ] - configs += [ - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", - "//build/config/compiler:wexit_time_destructors", - ] + configs += [ "//build/config/compiler:wexit_time_destructors" ] } buildflag_header("ui_features") { @@ -406,11 +402,7 @@ ] } - configs += [ - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", - "//build/config/compiler:wexit_time_destructors", - ] + configs += [ "//build/config/compiler:wexit_time_destructors" ] defines = [ "UI_BASE_IMPLEMENTATION" ] @@ -947,9 +939,6 @@ } } - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":ui_base_test_resources_grit", ":ui_base_unittests_bundle_data",
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index fe87e8fb..4d083be 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -138,8 +138,13 @@ const base::Feature kMashOopViz = {"MashOopViz", base::FEATURE_DISABLED_BY_DEFAULT}; +// Runs the window service in-process. Launch bug https://crbug.com/909816 const base::Feature kSingleProcessMash = {"SingleProcessMash", +#if defined(OS_CHROMEOS) + base::FEATURE_ENABLED_BY_DEFAULT}; +#else base::FEATURE_DISABLED_BY_DEFAULT}; +#endif bool IsUsingWindowService() { return IsSingleProcessMash() || IsMultiProcessMash();
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index a983afc..f8f5508 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -226,9 +226,6 @@ configs += [ "//build/config:precompiled_headers", - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", "//build/config/compiler:wexit_time_destructors", ] @@ -691,9 +688,6 @@ sources += [ "paint_vector_icon_unittest.cc" ] } - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] - deps = [ ":gfx", ":test_support",
diff --git a/ui/gfx/platform_font_skia.cc b/ui/gfx/platform_font_skia.cc index 81a77ad..b8910fe 100644 --- a/ui/gfx/platform_font_skia.cc +++ b/ui/gfx/platform_font_skia.cc
@@ -13,8 +13,8 @@ #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "third_party/skia/include/core/SkFont.h" #include "third_party/skia/include/core/SkFontStyle.h" -#include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkString.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font.h" @@ -306,18 +306,14 @@ if (metrics_need_computation_) { metrics_need_computation_ = false; - SkPaint paint; - paint.setAntiAlias(false); - paint.setSubpixelText(false); - paint.setTextSize(font_size_pixels_); - paint.setTypeface(typeface_); - paint.setFakeBoldText(weight_ >= Font::Weight::BOLD && - !typeface_->isBold()); - paint.setTextSkewX((Font::ITALIC & style_) && !typeface_->isItalic() - ? -SK_Scalar1 / 4 - : 0); + SkFont font(typeface_, font_size_pixels_); + font.setEdging(SkFont::Edging::kAlias); + font.setEmbolden(weight_ >= Font::Weight::BOLD && !typeface_->isBold()); + font.setSkewX((Font::ITALIC & style_) && !typeface_->isItalic() + ? -SK_Scalar1 / 4 + : 0); SkFontMetrics metrics; - paint.getFontMetrics(&metrics); + font.getMetrics(&metrics); ascent_pixels_ = SkScalarCeilToInt(-metrics.fAscent); height_pixels_ = ascent_pixels_ + SkScalarCeilToInt(metrics.fDescent); cap_height_pixels_ = SkScalarCeilToInt(metrics.fCapHeight);
diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc index 0680cde..a904ec3 100644 --- a/ui/gfx/platform_font_win.cc +++ b/ui/gfx/platform_font_win.cc
@@ -673,21 +673,20 @@ FontRenderParams::SubpixelRenderingToSkiaLCDOrientation( font_params.subpixel_rendering)); - SkPaint paint; - paint.setAntiAlias(font_params.antialiasing); - paint.setTypeface(std::move(skia_face)); - paint.setTextSize(-font_info.lfHeight); + SkFont font(std::move(skia_face), -font_info.lfHeight); + font.setEdging(font_params.antialiasing ? SkFont::Edging::kAntiAlias + : SkFont::Edging::kAlias); SkFontMetrics skia_metrics; - paint.getFontMetrics(&skia_metrics); + font.getMetrics(&skia_metrics); // The calculations below are similar to those in the CreateHFontRef // function. The height, baseline and cap height are rounded up to ensure // that they match up closely with GDI. const int height = std::ceil(skia_metrics.fDescent - skia_metrics.fAscent); const int baseline = std::max<int>(1, std::ceil(-skia_metrics.fAscent)); - const int cap_height = std::ceil(paint.getTextSize() * - static_cast<double>(dwrite_font_metrics.capHeight) / - dwrite_font_metrics.designUnitsPerEm); + const int cap_height = std::ceil( + font.getSize() * static_cast<double>(dwrite_font_metrics.capHeight) / + dwrite_font_metrics.designUnitsPerEm); // The metrics retrieved from skia don't have the average character width. In // any case if we get the average character width from skia then use that or
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index 849a1a8..926b9e8c 100644 --- a/ui/gfx/render_text_harfbuzz.cc +++ b/ui/gfx/render_text_harfbuzz.cc
@@ -490,12 +490,12 @@ line->segments.push_back(segment); line->size.set_width(line->size.width() + segment.width()); - SkPaint paint; - paint.setTypeface(run.font_params.skia_face); - paint.setTextSize(SkIntToScalar(run.font_params.font_size)); - paint.setAntiAlias(run.font_params.render_params.antialiasing); + SkFont font(run.font_params.skia_face, run.font_params.font_size); + font.setEdging(run.font_params.render_params.antialiasing + ? SkFont::Edging::kAntiAlias + : SkFont::Edging::kAlias); SkFontMetrics metrics; - paint.getFontMetrics(&metrics); + font.getMetrics(&metrics); // max_descent_ is y-down, fDescent is y-down, baseline_offset is y-down max_descent_ = std::max(max_descent_,
diff --git a/ui/gl/gl_image_ahardwarebuffer.cc b/ui/gl/gl_image_ahardwarebuffer.cc index 7e709d18..afee6bbe 100644 --- a/ui/gl/gl_image_ahardwarebuffer.cc +++ b/ui/gl/gl_image_ahardwarebuffer.cc
@@ -27,7 +27,7 @@ case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: return GL_RGB; default: - NOTREACHED(); + // For all other buffer formats, use GL_RGBA as internal format. return GL_RGBA; } }
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn index ee5189f..ba0038b3 100644 --- a/ui/message_center/BUILD.gn +++ b/ui/message_center/BUILD.gn
@@ -55,12 +55,7 @@ "//ui/resources", ] - configs += [ - "//build/config:precompiled_headers", - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", - ] + configs += [ "//build/config:precompiled_headers" ] sources = [ "lock_screen/empty_lock_screen_controller.cc", "lock_screen/empty_lock_screen_controller.h",
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index 9c42ce6..4520663 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -54,6 +54,9 @@ return SkColorSetA(gfx::kGoogleGrey800, 0xCC); case NativeTheme::kColorId_TextfieldDefaultBackground: return SkColorSetA(SK_ColorBLACK, 0x4D); + case NativeTheme::kColorId_LinkEnabled: + case NativeTheme::kColorId_LinkPressed: + return gfx::kGoogleBlue300; default: break;
diff --git a/ui/ozone/public/surface_ozone_canvas.h b/ui/ozone/public/surface_ozone_canvas.h index 65f6de4..05577a9 100644 --- a/ui/ozone/public/surface_ozone_canvas.h +++ b/ui/ozone/public/surface_ozone_canvas.h
@@ -32,13 +32,13 @@ virtual sk_sp<SkSurface> GetSurface() = 0; // Attempts to resize the canvas to match the viewport size. After - // resizing, the compositor must call GetCanvas() to get the next - // canvas - this invalidates any previous canvas from GetCanvas(). + // resizing, the compositor must call GetSurface() to get the next + // surface - this invalidates any previous surface from GetSurface(). virtual void ResizeCanvas(const gfx::Size& viewport_size) = 0; - // Present the current canvas. After presenting, the compositor must - // call GetCanvas() to get the next canvas - this invalidates any - // previous canvas from GetCanvas(). + // Present the current surface. After presenting, the compositor must + // call GetSurface() to get the next surface - this invalidates any + // previous surface from GetSurface(). // // The implementation may assume that any pixels outside the damage // rectangle are unchanged since the previous call to PresentCanvas().
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 714a80c..868136f 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -490,14 +490,7 @@ ] sources += get_target_outputs(":views_vector_icons") - - configs += [ - "//build/config:precompiled_headers", - - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - "//build/config/compiler:no_size_t_to_int_warning", - ] - + configs += [ "//build/config:precompiled_headers" ] defines = [ "VIEWS_IMPLEMENTATION" ] deps = [
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 95115bb..d6f764e0 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -88,7 +88,7 @@ default_title_->SetVisible(false); AddChildView(default_title_); - close_ = CreateCloseButton(this); + close_ = CreateCloseButton(this, GetNativeTheme()->SystemDarkModeEnabled()); close_->SetVisible(false); #if defined(OS_WIN) // Windows will automatically create a tooltip for the close button based on @@ -111,10 +111,13 @@ } // static -Button* BubbleFrameView::CreateCloseButton(ButtonListener* listener) { +Button* BubbleFrameView::CreateCloseButton(ButtonListener* listener, + bool is_dark_mode) { ImageButton* close_button = nullptr; close_button = CreateVectorImageButton(listener); - SetImageFromVectorIcon(close_button, vector_icons::kCloseRoundedIcon); + SetImageFromVectorIconWithColor( + close_button, vector_icons::kCloseRoundedIcon, + is_dark_mode ? SkColorSetA(SK_ColorWHITE, 0xDD) : gfx::kGoogleGrey700); close_button->SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_CLOSE)); close_button->SizeToPreferredSize();
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h index ca1a22c..8fe9fd5e 100644 --- a/ui/views/bubble/bubble_frame_view.h +++ b/ui/views/bubble/bubble_frame_view.h
@@ -38,7 +38,7 @@ const base::string16& title_text); // Creates a close button used in the corner of the dialog. - static Button* CreateCloseButton(ButtonListener* listener); + static Button* CreateCloseButton(ButtonListener* listener, bool is_dark_mode); // NonClientFrameView: gfx::Rect GetBoundsForClientView() const override;
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.h b/ui/views/cocoa/bridged_native_widget_host_impl.h index 45f5b4a..2bbec19 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.h +++ b/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -228,7 +228,6 @@ bool* found_word, gfx::DecoratedText* decorated_word, gfx::Point* baseline_point) override; - double SheetPositionY() override; views_bridge_mac::DragDropClient* GetDragDropClient() override; ui::TextInputClient* GetTextInputClient() override; void GetHasInputContext(bool* has_text_input_context) override; @@ -240,6 +239,7 @@ void OnVisibilityChanged(bool visible) override; void OnWindowNativeThemeChanged() override; void OnViewSizeChanged(const gfx::Size& new_size) override; + bool GetSheetOffsetY(int32_t* offset_y) override; void SetKeyboardAccessible(bool enabled) override; void OnIsFirstResponderChanged(bool is_first_responder) override; void OnMouseCaptureActiveChanged(bool capture_is_active) override; @@ -303,6 +303,7 @@ bool* was_handled) override; // views_bridge_mac::mojom::BridgedNativeWidgetHost, synchronous callbacks: + void GetSheetOffsetY(GetSheetOffsetYCallback callback) override; void DispatchKeyEventRemote(std::unique_ptr<ui::Event> event, DispatchKeyEventRemoteCallback callback) override; void DispatchKeyEventToMenuControllerRemote(
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm index 4319ee1..d8e8e14 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.mm +++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -519,10 +519,6 @@ return false; } -double BridgedNativeWidgetHostImpl::SheetPositionY() { - return native_widget_mac_->SheetPositionY(); -} - views_bridge_mac::DragDropClient* BridgedNativeWidgetHostImpl::GetDragDropClient() { return drag_drop_client_.get(); @@ -619,6 +615,11 @@ root_view_->SetSize(new_size); } +bool BridgedNativeWidgetHostImpl::GetSheetOffsetY(int32_t* offset_y) { + *offset_y = native_widget_mac_->SheetOffsetY(); + return true; +} + void BridgedNativeWidgetHostImpl::SetKeyboardAccessible(bool enabled) { views::FocusManager* focus_manager = root_view_->GetWidget()->GetFocusManager(); @@ -973,6 +974,13 @@ // BridgedNativeWidgetHostImpl, // views_bridge_mac::mojom::BridgedNativeWidgetHost synchronous callbacks: +void BridgedNativeWidgetHostImpl::GetSheetOffsetY( + GetSheetOffsetYCallback callback) { + int32_t offset_y = 0; + GetSheetOffsetY(&offset_y); + std::move(callback).Run(offset_y); +} + void BridgedNativeWidgetHostImpl::DispatchKeyEventRemote( std::unique_ptr<ui::Event> event, DispatchKeyEventRemoteCallback callback) {
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h index 6201956..cf1d7436 100644 --- a/ui/views/widget/native_widget_mac.h +++ b/ui/views/widget/native_widget_mac.h
@@ -50,9 +50,9 @@ // destroyed. void WindowDestroyed(); - // Returns the vertical position that sheets should be anchored, in pixels - // from the bottom of the window. - virtual int SheetPositionY(); + // The vertical position from which sheets should be anchored, from the top + // of the content view. + virtual int32_t SheetOffsetY(); // Returns in |override_titlebar_height| whether or not to override the // titlebar height and in |titlebar_height| the height of the titlebar.
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 9adc67f..d93c719 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -96,10 +96,8 @@ delete this; } -int NativeWidgetMac::SheetPositionY() { - NSView* view = GetNativeView().GetNativeNSView(); - return - [view convertPoint:NSMakePoint(0, NSHeight([view frame])) toView:nil].y; +int32_t NativeWidgetMac::SheetOffsetY() { + return 0; } void NativeWidgetMac::GetWindowFrameTitlebarHeight(
diff --git a/ui/views_bridge_mac/bridge_factory_impl.mm b/ui/views_bridge_mac/bridge_factory_impl.mm index 6ddab334..e4168c1 100644 --- a/ui/views_bridge_mac/bridge_factory_impl.mm +++ b/ui/views_bridge_mac/bridge_factory_impl.mm
@@ -72,7 +72,6 @@ gfx::Point* baseline_point) override { *found_word = false; } - double SheetPositionY() override { return 0; } views_bridge_mac::DragDropClient* GetDragDropClient() override { // Drag-drop only doesn't work across mojo yet. return nullptr;
diff --git a/ui/views_bridge_mac/bridged_native_widget_host_helper.h b/ui/views_bridge_mac/bridged_native_widget_host_helper.h index 2d19cbc..2d8d15d 100644 --- a/ui/views_bridge_mac/bridged_native_widget_host_helper.h +++ b/ui/views_bridge_mac/bridged_native_widget_host_helper.h
@@ -52,12 +52,6 @@ gfx::DecoratedText* decorated_word, gfx::Point* baseline_point) = 0; - // Returns the vertical position that sheets should be anchored, in pixels - // from the bottom of the window. - // TODO(ccameron): This should be either moved to the mojo interface or - // separated out in such a way as to avoid needing to go through mojo. - virtual double SheetPositionY() = 0; - // Return a pointer to host's DragDropClientMac. // TODO(ccameron): Drag-drop behavior needs to be implemented over mojo. virtual DragDropClient* GetDragDropClient() = 0;
diff --git a/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom b/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom index 40ea3fed..2a36cc3 100644 --- a/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom +++ b/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom
@@ -50,6 +50,11 @@ // bounds from OnWindowGeometryChanged. OnViewSizeChanged(gfx.mojom.Size new_size); + // The vertical position from which sheets should be anchored, from the top + // of the content view. + [Sync] + GetSheetOffsetY() => (int32 offset_y); + // Indicate if full keyboard accessibility is needed and update focus if // needed. SetKeyboardAccessible(bool enabled);
diff --git a/ui/views_bridge_mac/views_nswindow_delegate.mm b/ui/views_bridge_mac/views_nswindow_delegate.mm index 7d1fbfa..56869eb 100644 --- a/ui/views_bridge_mac/views_nswindow_delegate.mm +++ b/ui/views_bridge_mac/views_nswindow_delegate.mm
@@ -196,15 +196,18 @@ - (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)defaultSheetLocation { - // TODO(ccameron): This should go through the BridgedNativeWidgetHost - // interface. - CGFloat sheetPositionY = parent_->host_helper()->SheetPositionY(); + int32_t sheetPositionY = 0; + parent_->host()->GetSheetOffsetY(&sheetPositionY); + NSView* view = [window contentView]; + NSPoint pointInView = + NSMakePoint(0, NSMaxY([view bounds]) - sheetPositionY); + NSPoint pointInWindow = [view convertPoint:pointInView toView:nil]; // As per NSWindowDelegate documentation, the origin indicates the top left // point of the host frame in window coordinates. The width changes the // animation from vertical to trapezoid if it is smaller than the width of the // dialog. The height is ignored but should be set to zero. - return NSMakeRect(0, sheetPositionY, NSWidth(defaultSheetLocation), 0); + return NSMakeRect(0, pointInWindow.y, NSWidth(defaultSheetLocation), 0); } @end
diff --git a/ui/webui/resources/html/webui_listener_tracker.html b/ui/webui/resources/html/webui_listener_tracker.html deleted file mode 100644 index f63f03e..0000000 --- a/ui/webui/resources/html/webui_listener_tracker.html +++ /dev/null
@@ -1 +0,0 @@ -<script src="../js/webui_listener_tracker.js"></script>
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 6ad7c092..9b0a553 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -30,7 +30,6 @@ ":search_highlight_utils", ":util", ":web_ui_listener_behavior", - ":webui_listener_tracker", ":webui_resource_test", ] } @@ -60,12 +59,6 @@ js_library("event_tracker") { } -js_library("webui_listener_tracker") { - deps = [ - ":cr", - ] -} - js_library("search_highlight_utils") { deps = [ ":cr",
diff --git a/ui/webui/resources/js/webui_listener_tracker.js b/ui/webui/resources/js/webui_listener_tracker.js deleted file mode 100644 index 51ffb08..0000000 --- a/ui/webui/resources/js/webui_listener_tracker.js +++ /dev/null
@@ -1,42 +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. - -/** - * @fileoverview Class that manages the addition and removal of WebUI - * listeners. - */ - -/** - * Create a WebUIListenerTracker to track a set of Web UI listeners. - * @constructor - */ -function WebUIListenerTracker() { - /** - * The Web UI listeners being tracked. - * @private {!Array<!WebUIListener>} - */ - this.listeners_ = []; -} - -WebUIListenerTracker.prototype = { - /** - * Adds a WebUI listener to the array of listeners being tracked, which - * will be removed when removeAll() is called. - * Do not use this method if the listener will be removed manually. - * @param {string} eventName The event to listen to. - * @param {!Function} callback The callback to run when the event is fired. - */ - add: function(eventName, callback) { - this.listeners_.push(cr.addWebUIListener(eventName, callback)); - }, - - /** - * Removes all Web UI listeners that are currently being tracked. - */ - removeAll: function() { - while (this.listeners_.length > 0) { - cr.removeWebUIListener(this.listeners_.pop()); - } - }, -};
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd index 942555b..b22111a 100644 --- a/ui/webui/resources/webui_resources.grd +++ b/ui/webui/resources/webui_resources.grd
@@ -371,9 +371,6 @@ compress="gzip" /> <structure name="IDR_WEBUI_HTML_UTIL" file="html/util.html" type="chrome_html" compress="gzip" /> - <structure name="IDR_WEBUI_HTML_WEBUI_LISTENER_TRACKER" - file="html/webui_listener_tracker.html" type="chrome_html" - compress="gzip" /> <structure name="IDR_WEBUI_JS_ACTION_LINK" file="js/action_link.js" type="chrome_html" compress="gzip" /> @@ -521,9 +518,6 @@ <structure name="IDR_WEBUI_JS_EVENT_TRACKER" file="js/event_tracker.js" type="chrome_html" compress="gzip" /> - <structure name="IDR_WEBUI_JS_WEBUI_LISTENER_TRACKER" - file="js/webui_listener_tracker.js" type="chrome_html" - compress="gzip" /> <structure name="IDR_WEBUI_JS_ICON" file="js/icon.js" type="chrome_html" compress="gzip" flattenhtml="true" />